Commit 0ae80785 authored by Mikio Hara's avatar Mikio Hara

net: make LocalAddr on multicast UDPConn return a listening address

The package go.net/ipv4 allows to exist a single UDP listener
that join multiple different group addresses. That means that
LocalAddr on multicast UDPConn returns a first joined group
address is not desirable.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6822108
parent 7e7b89f7
...@@ -118,16 +118,29 @@ func TestSimpleMulticastListener(t *testing.T) { ...@@ -118,16 +118,29 @@ func TestSimpleMulticastListener(t *testing.T) {
func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) { func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
if !multicastRIBContains(t, gaddr.IP) { if !multicastRIBContains(t, gaddr.IP) {
t.Fatalf("%q not found in RIB", gaddr.String()) t.Errorf("%q not found in RIB", gaddr.String())
return
}
la := c.LocalAddr()
if la == nil {
t.Error("LocalAddr failed")
return
} }
if c.LocalAddr().String() != gaddr.String() { if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String()) t.Errorf("got %v; expected a proper address with non-zero port number", la)
return
} }
} }
func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) { func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
if c.LocalAddr().String() != gaddr.String() { la := c.LocalAddr()
t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String()) if la == nil {
t.Error("LocalAddr failed")
return
}
if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
t.Errorf("got %v; expected a proper address with non-zero port number", la)
return
} }
} }
......
...@@ -33,13 +33,19 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, ...@@ -33,13 +33,19 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
return nil, err return nil, err
} }
var blsa syscall.Sockaddr
if ulsa != nil { if ulsa != nil {
if blsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil { // We provide a socket that listens to a wildcard
// address with reusable UDP port when the given ulsa
// is an appropriate UDP multicast address prefix.
// This makes it possible for a single UDP listener
// to join multiple different group addresses, for
// multiple UDP listeners that listen on the same UDP
// port to join the same group address.
if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
closesocket(s) closesocket(s)
return nil, err return nil, err
} }
if err = syscall.Bind(s, blsa); err != nil { if err = syscall.Bind(s, ulsa); err != nil {
closesocket(s) closesocket(s)
return nil, err return nil, err
} }
...@@ -64,12 +70,7 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, ...@@ -64,12 +70,7 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
} }
lsa, _ := syscall.Getsockname(s) lsa, _ := syscall.Getsockname(s)
var laddr Addr laddr := toAddr(lsa)
if ulsa != nil && blsa != ulsa {
laddr = toAddr(ulsa)
} else {
laddr = toAddr(lsa)
}
rsa, _ := syscall.Getpeername(s) rsa, _ := syscall.Getpeername(s)
raddr := toAddr(rsa) raddr := toAddr(rsa)
fd.setAddr(laddr, raddr) fd.setAddr(laddr, raddr)
......
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