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) ...@@ -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) t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
} }
case "unixgram": 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 { if err != nil {
t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err) 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, ...@@ -65,10 +65,10 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
lsa, _ := syscall.Getsockname(s) lsa, _ := syscall.Getsockname(s)
laddr := toAddr(lsa) laddr := toAddr(lsa)
rsa, _ := syscall.Getpeername(s) rsa, _ := syscall.Getpeername(s)
if rsa == nil {
rsa = ursa
}
raddr := toAddr(rsa) raddr := toAddr(rsa)
fd.setAddr(laddr, raddr) fd.setAddr(laddr, raddr)
if fd.raddr == nil {
fd.raddr = toAddr(ursa)
}
return fd, nil return fd, nil
} }
...@@ -217,14 +217,12 @@ func TestTCPListenerName(t *testing.T) { ...@@ -217,14 +217,12 @@ func TestTCPListenerName(t *testing.T) {
for _, tt := range tcpListenerNameTests { for _, tt := range tcpListenerNameTests {
ln, err := ListenTCP(tt.net, tt.laddr) ln, err := ListenTCP(tt.net, tt.laddr)
if err != nil { if err != nil {
t.Errorf("ListenTCP failed: %v", err) t.Fatalf("ListenTCP failed: %v", err)
return
} }
defer ln.Close() defer ln.Close()
la := ln.Addr() la := ln.Addr()
if a, ok := la.(*TCPAddr); !ok || a.Port == 0 { if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
t.Errorf("got %v; expected a proper address with non-zero port number", la) t.Fatalf("got %v; expected a proper address with non-zero port number", la)
return
} }
} }
} }
......
...@@ -159,14 +159,50 @@ func TestUDPConnLocalName(t *testing.T) { ...@@ -159,14 +159,50 @@ func TestUDPConnLocalName(t *testing.T) {
for _, tt := range udpConnLocalNameTests { for _, tt := range udpConnLocalNameTests {
c, err := ListenUDP(tt.net, tt.laddr) c, err := ListenUDP(tt.net, tt.laddr)
if err != nil { if err != nil {
t.Errorf("ListenUDP failed: %v", err) t.Fatalf("ListenUDP failed: %v", err)
return
} }
defer c.Close() defer c.Close()
la := c.LocalAddr() la := c.LocalAddr()
if a, ok := la.(*UDPAddr); !ok || a.Port == 0 { if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
t.Errorf("got %v; expected a proper address with non-zero port number", la) t.Fatalf("got %v; expected a proper address with non-zero port number", la)
return }
}
}
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) { ...@@ -33,7 +33,6 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
off := make(chan bool) off := make(chan bool)
data := [5]byte{1, 2, 3, 4, 5} data := [5]byte{1, 2, 3, 4, 5}
go func() { go func() {
defer func() { off <- true }() defer func() { off <- true }()
s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0) s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
...@@ -54,15 +53,13 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) { ...@@ -54,15 +53,13 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, from, err := c.ReadFrom(b) n, from, err := c.ReadFrom(b)
if err != nil { if err != nil {
t.Errorf("UnixConn.ReadFrom failed: %v", err) t.Fatalf("UnixConn.ReadFrom failed: %v", err)
return
} }
if from != nil { if from != nil {
t.Errorf("neighbor address is %v", from) t.Fatalf("neighbor address is %v", from)
} }
if !bytes.Equal(b[:n], data[:]) { if !bytes.Equal(b[:n], data[:]) {
t.Errorf("got %v, want %v", b[:n], data[:]) t.Fatalf("got %v, want %v", b[:n], data[:])
return
} }
} }
...@@ -101,13 +98,12 @@ func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) { ...@@ -101,13 +98,12 @@ func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
<-off <-off
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
var peer Addr _, from, err := c.ReadFrom(nil)
if _, peer, err = c.ReadFrom(nil); err != nil { if err != nil {
t.Errorf("UnixConn.ReadFrom failed: %v", err) t.Fatalf("UnixConn.ReadFrom failed: %v", err)
return
} }
if peer != nil { if from != nil {
t.Errorf("peer adddress is %v", peer) t.Fatalf("neighbor address is %v", from)
} }
} }
...@@ -126,10 +122,10 @@ func TestUnixAutobind(t *testing.T) { ...@@ -126,10 +122,10 @@ func TestUnixAutobind(t *testing.T) {
// retrieve the autobind address // retrieve the autobind address
autoAddr := c1.LocalAddr().(*UnixAddr) autoAddr := c1.LocalAddr().(*UnixAddr)
if len(autoAddr.Name) <= 1 { if len(autoAddr.Name) <= 1 {
t.Fatalf("Invalid autobind address: %v", autoAddr) t.Fatalf("invalid autobind address: %v", autoAddr)
} }
if autoAddr.Name[0] != '@' { if autoAddr.Name[0] != '@' {
t.Fatalf("Invalid autobind address: %v", autoAddr) t.Fatalf("invalid autobind address: %v", autoAddr)
} }
c2, err := DialUnix("unixgram", nil, autoAddr) c2, err := DialUnix("unixgram", nil, autoAddr)
...@@ -139,6 +135,112 @@ func TestUnixAutobind(t *testing.T) { ...@@ -139,6 +135,112 @@ func TestUnixAutobind(t *testing.T) {
defer c2.Close() defer c2.Close()
if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) { 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 ( ...@@ -15,6 +15,13 @@ import (
"time" "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) { func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
var sotype int var sotype int
switch net { switch net {
...@@ -31,12 +38,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T ...@@ -31,12 +38,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T
var la, ra syscall.Sockaddr var la, ra syscall.Sockaddr
switch mode { switch mode {
case "dial": case "dial":
if laddr != nil { if !laddr.isUnnamed() {
la = &syscall.SockaddrUnix{Name: laddr.Name} la = &syscall.SockaddrUnix{Name: laddr.Name}
} }
if raddr != nil { if raddr != nil {
ra = &syscall.SockaddrUnix{Name: raddr.Name} 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} return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
} }
case "listen": case "listen":
...@@ -69,21 +76,21 @@ error: ...@@ -69,21 +76,21 @@ error:
func sockaddrToUnix(sa syscall.Sockaddr) Addr { func sockaddrToUnix(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok { if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unix"} return &UnixAddr{Name: s.Name, Net: "unix"}
} }
return nil return nil
} }
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr { func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok { if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unixgram"} return &UnixAddr{Name: s.Name, Net: "unixgram"}
} }
return nil return nil
} }
func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr { func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok { if s, ok := sa.(*syscall.SockaddrUnix); ok {
return &UnixAddr{s.Name, "unixpacket"} return &UnixAddr{Name: s.Name, Net: "unixpacket"}
} }
return nil return nil
} }
...@@ -92,10 +99,10 @@ func sotypeToNet(sotype int) string { ...@@ -92,10 +99,10 @@ func sotypeToNet(sotype int) string {
switch sotype { switch sotype {
case syscall.SOCK_STREAM: case syscall.SOCK_STREAM:
return "unix" return "unix"
case syscall.SOCK_SEQPACKET:
return "unixpacket"
case syscall.SOCK_DGRAM: case syscall.SOCK_DGRAM:
return "unixgram" return "unixgram"
case syscall.SOCK_SEQPACKET:
return "unixpacket"
default: default:
panic("sotypeToNet unknown socket type") panic("sotypeToNet unknown socket type")
} }
...@@ -124,7 +131,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) { ...@@ -124,7 +131,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
switch sa := sa.(type) { switch sa := sa.(type) {
case *syscall.SockaddrUnix: case *syscall.SockaddrUnix:
if sa.Name != "" { if sa.Name != "" {
addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)} addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
} }
} }
return return
...@@ -151,7 +158,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd ...@@ -151,7 +158,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
switch sa := sa.(type) { switch sa := sa.(type) {
case *syscall.SockaddrUnix: case *syscall.SockaddrUnix:
if sa.Name != "" { if sa.Name != "" {
addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)} addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
} }
} }
return 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