From bfb32dc6d1b8cbe6f4d2d52d3226e4c31e36b576 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sat, 23 Mar 2013 22:32:19 +0900 Subject: [PATCH] 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 --- src/pkg/net/server_test.go | 2 +- src/pkg/net/sock_posix.go | 6 +- src/pkg/net/tcp_test.go | 6 +- src/pkg/net/udp_test.go | 44 ++++++++++-- src/pkg/net/unix_test.go | 132 ++++++++++++++++++++++++++++++---- src/pkg/net/unixsock_posix.go | 25 ++++--- 6 files changed, 179 insertions(+), 36 deletions(-) diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go index c101ffecd1..9194a8ec24 100644 --- a/src/pkg/net/server_test.go +++ b/src/pkg/net/server_test.go @@ -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) } diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go index 2ebde87998..c8a94f5047 100644 --- a/src/pkg/net/sock_posix.go +++ b/src/pkg/net/sock_posix.go @@ -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 } diff --git a/src/pkg/net/tcp_test.go b/src/pkg/net/tcp_test.go index add8e48234..b89202f506 100644 --- a/src/pkg/net/tcp_test.go +++ b/src/pkg/net/tcp_test.go @@ -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) } } } diff --git a/src/pkg/net/udp_test.go b/src/pkg/net/udp_test.go index b3cafb096f..7a64c19ff2 100644 --- a/src/pkg/net/udp_test.go +++ b/src/pkg/net/udp_test.go @@ -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) + } } } } diff --git a/src/pkg/net/unix_test.go b/src/pkg/net/unix_test.go index 2eaabe86e4..5e63e9d9de 100644 --- a/src/pkg/net/unix_test.go +++ b/src/pkg/net/unix_test.go @@ -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) + } + } } } diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go index 8d57dacbd6..abdff09a8a 100644 --- a/src/pkg/net/unixsock_posix.go +++ b/src/pkg/net/unixsock_posix.go @@ -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 -- 2.48.1