Commit bfb32dc6 authored by Mikio Hara's avatar Mikio Hara

net: use original raddr if getpeername fails

This CL updates CL 7511043;
- adds new test cases for both UDPConn and UnixConn,
- makes sure unnamed UnixAddr handling,
- replaces t.Errorf with t.Fatalf in sockname related test cases.

Fixes #3721 (again).
Fixes #3838 (again).

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7627048
parent aa0dda76
......@@ -402,7 +402,7 @@ func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool)
t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
}
case "unixgram":
c, err = DialUnix(net, &UnixAddr{laddr, net}, &UnixAddr{taddr, net})
c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
if err != nil {
t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
}
......
......@@ -65,10 +65,10 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
lsa, _ := syscall.Getsockname(s)
laddr := toAddr(lsa)
rsa, _ := syscall.Getpeername(s)
if rsa == nil {
rsa = ursa
}
raddr := toAddr(rsa)
fd.setAddr(laddr, raddr)
if fd.raddr == nil {
fd.raddr = toAddr(ursa)
}
return fd, nil
}
......@@ -217,14 +217,12 @@ func TestTCPListenerName(t *testing.T) {
for _, tt := range tcpListenerNameTests {
ln, err := ListenTCP(tt.net, tt.laddr)
if err != nil {
t.Errorf("ListenTCP failed: %v", err)
return
t.Fatalf("ListenTCP failed: %v", err)
}
defer ln.Close()
la := ln.Addr()
if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
t.Errorf("got %v; expected a proper address with non-zero port number", la)
return
t.Fatalf("got %v; expected a proper address with non-zero port number", la)
}
}
}
......
......@@ -159,14 +159,50 @@ func TestUDPConnLocalName(t *testing.T) {
for _, tt := range udpConnLocalNameTests {
c, err := ListenUDP(tt.net, tt.laddr)
if err != nil {
t.Errorf("ListenUDP failed: %v", err)
return
t.Fatalf("ListenUDP failed: %v", err)
}
defer c.Close()
la := c.LocalAddr()
if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
t.Errorf("got %v; expected a proper address with non-zero port number", la)
return
t.Fatalf("got %v; expected a proper address with non-zero port number", la)
}
}
}
func TestUDPConnLocalAndRemoteNames(t *testing.T) {
for _, laddr := range []string{"", "127.0.0.1:0"} {
c1, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("ListenUDP failed: %v", err)
}
defer c1.Close()
var la *UDPAddr
if laddr != "" {
var err error
if la, err = ResolveUDPAddr("udp", laddr); err != nil {
t.Fatalf("ResolveUDPAddr failed: %v", err)
}
}
c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
if err != nil {
t.Fatalf("DialUDP failed: %v", err)
}
defer c2.Close()
var connAddrs = [4]struct {
got Addr
ok bool
}{
{c1.LocalAddr(), true},
{c1.(*UDPConn).RemoteAddr(), false},
{c2.LocalAddr(), true},
{c2.RemoteAddr(), true},
}
for _, ca := range connAddrs {
if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
}
}
}
}
......
......@@ -33,7 +33,6 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
off := make(chan bool)
data := [5]byte{1, 2, 3, 4, 5}
go func() {
defer func() { off <- true }()
s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
......@@ -54,15 +53,13 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, from, err := c.ReadFrom(b)
if err != nil {
t.Errorf("UnixConn.ReadFrom failed: %v", err)
return
t.Fatalf("UnixConn.ReadFrom failed: %v", err)
}
if from != nil {
t.Errorf("neighbor address is %v", from)
t.Fatalf("neighbor address is %v", from)
}
if !bytes.Equal(b[:n], data[:]) {
t.Errorf("got %v, want %v", b[:n], data[:])
return
t.Fatalf("got %v, want %v", b[:n], data[:])
}
}
......@@ -101,13 +98,12 @@ func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
<-off
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
var peer Addr
if _, peer, err = c.ReadFrom(nil); err != nil {
t.Errorf("UnixConn.ReadFrom failed: %v", err)
return
_, from, err := c.ReadFrom(nil)
if err != nil {
t.Fatalf("UnixConn.ReadFrom failed: %v", err)
}
if peer != nil {
t.Errorf("peer adddress is %v", peer)
if from != nil {
t.Fatalf("neighbor address is %v", from)
}
}
......@@ -126,10 +122,10 @@ func TestUnixAutobind(t *testing.T) {
// retrieve the autobind address
autoAddr := c1.LocalAddr().(*UnixAddr)
if len(autoAddr.Name) <= 1 {
t.Fatalf("Invalid autobind address: %v", autoAddr)
t.Fatalf("invalid autobind address: %v", autoAddr)
}
if autoAddr.Name[0] != '@' {
t.Fatalf("Invalid autobind address: %v", autoAddr)
t.Fatalf("invalid autobind address: %v", autoAddr)
}
c2, err := DialUnix("unixgram", nil, autoAddr)
......@@ -139,6 +135,112 @@ func TestUnixAutobind(t *testing.T) {
defer c2.Close()
if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) {
t.Fatalf("Expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
t.Fatalf("expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
}
}
func TestUnixConnLocalAndRemoteNames(t *testing.T) {
for _, laddr := range []string{"", testUnixAddr()} {
taddr := testUnixAddr()
ta, err := ResolveUnixAddr("unix", taddr)
if err != nil {
t.Fatalf("ResolveUnixAddr failed: %v", err)
}
ln, err := ListenUnix("unix", ta)
if err != nil {
t.Fatalf("ListenUnix failed: %v", err)
}
defer func() {
ln.Close()
os.Remove(taddr)
}()
done := make(chan int)
go transponder(t, ln, done)
la, err := ResolveUnixAddr("unix", laddr)
if err != nil {
t.Fatalf("ResolveUnixAddr failed: %v", err)
}
c, err := DialUnix("unix", la, ta)
if err != nil {
t.Fatalf("DialUnix failed: %v", err)
}
defer func() {
c.Close()
if la != nil {
defer os.Remove(laddr)
}
}()
if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
t.Fatalf("UnixConn.Write failed: %v", err)
}
if runtime.GOOS == "linux" && laddr == "" {
laddr = "@" // autobind feature
}
var connAddrs = [3]struct{ got, want Addr }{
{ln.Addr(), ta},
{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
{c.RemoteAddr(), ta},
}
for _, ca := range connAddrs {
if !reflect.DeepEqual(ca.got, ca.want) {
t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
}
}
<-done
}
}
func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
for _, laddr := range []string{"", testUnixAddr()} {
taddr := testUnixAddr()
ta, err := ResolveUnixAddr("unixgram", taddr)
if err != nil {
t.Fatalf("ResolveUnixAddr failed: %v", err)
}
c1, err := ListenUnixgram("unixgram", ta)
if err != nil {
t.Fatalf("ListenUnixgram failed: %v", err)
}
defer func() {
c1.Close()
os.Remove(taddr)
}()
var la *UnixAddr
if laddr != "" {
var err error
if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
t.Fatalf("ResolveUnixAddr failed: %v", err)
}
}
c2, err := DialUnix("unixgram", la, ta)
if err != nil {
t.Fatalf("DialUnix failed: %v", err)
}
defer func() {
c2.Close()
if la != nil {
defer os.Remove(laddr)
}
}()
if runtime.GOOS == "linux" && laddr == "" {
laddr = "@" // autobind feature
}
var connAddrs = [4]struct{ got, want Addr }{
{c1.LocalAddr(), ta},
{c1.RemoteAddr(), nil},
{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
{c2.RemoteAddr(), ta},
}
for _, ca := range connAddrs {
if !reflect.DeepEqual(ca.got, ca.want) {
t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
}
}
}
}
......@@ -15,6 +15,13 @@ import (
"time"
)
func (a *UnixAddr) isUnnamed() bool {
if a == nil || a.Name == "" {
return true
}
return false
}
func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
var sotype int
switch net {
......@@ -31,12 +38,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T
var la, ra syscall.Sockaddr
switch mode {
case "dial":
if laddr != nil {
if !laddr.isUnnamed() {
la = &syscall.SockaddrUnix{Name: laddr.Name}
}
if raddr != nil {
ra = &syscall.SockaddrUnix{Name: raddr.Name}
} else if sotype != syscall.SOCK_DGRAM || laddr == nil {
} else if sotype != syscall.SOCK_DGRAM || laddr.isUnnamed() {
return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
}
case "listen":
......@@ -69,21 +76,21 @@ error:
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unix"}
return &UnixAddr{Name: s.Name, Net: "unix"}
}
return nil
}
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unixgram"}
return &UnixAddr{Name: s.Name, Net: "unixgram"}
}
return nil
}
func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unixpacket"}
return &UnixAddr{Name: s.Name, Net: "unixpacket"}
}
return nil
}
......@@ -92,10 +99,10 @@ func sotypeToNet(sotype int) string {
switch sotype {
case syscall.SOCK_STREAM:
return "unix"
case syscall.SOCK_SEQPACKET:
return "unixpacket"
case syscall.SOCK_DGRAM:
return "unixgram"
case syscall.SOCK_SEQPACKET:
return "unixpacket"
default:
panic("sotypeToNet unknown socket type")
}
......@@ -124,7 +131,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
if sa.Name != "" {
addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
}
}
return
......@@ -151,7 +158,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
if sa.Name != "" {
addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
}
}
return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment