mirror of
https://github.com/golang/go
synced 2024-11-24 23:57:57 -07:00
net: platform-dependent default socket options
This CL revises existing platform-dependent default socket options to make it possible to accomodate multiple multicast datagram listeners on a single service port. Also removes unnecessary SO_REUSEADDR, SO_REUSEPORT socket options from unicast datagram sockets by default. Fixes #1692. R=devon.odell, alex.brainman, rsc CC=golang-dev https://golang.org/cl/5538052
This commit is contained in:
parent
2374edc640
commit
7419921bf3
@ -95,6 +95,49 @@ func TestMulticastUDP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleMulticastUDP(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
return
|
||||
}
|
||||
if !*multicast {
|
||||
t.Logf("test disabled; use --multicast to enable")
|
||||
return
|
||||
}
|
||||
|
||||
for _, tt := range multicastUDPTests {
|
||||
var ifi *Interface
|
||||
if tt.ipv6 {
|
||||
continue
|
||||
}
|
||||
tt.flags = FlagUp | FlagMulticast
|
||||
ift, err := Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("Interfaces failed: %v", err)
|
||||
}
|
||||
for _, x := range ift {
|
||||
if x.Flags&tt.flags == tt.flags {
|
||||
ifi = &x
|
||||
break
|
||||
}
|
||||
}
|
||||
if ifi == nil {
|
||||
t.Logf("an appropriate multicast interface not found")
|
||||
return
|
||||
}
|
||||
c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
|
||||
if err != nil {
|
||||
t.Fatalf("ListenUDP failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
|
||||
t.Fatalf("JoinGroup failed: %v", err)
|
||||
}
|
||||
if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
|
||||
t.Fatalf("LeaveGroup failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
|
||||
ifmc, err := ipv4MulticastInterface(fd)
|
||||
if err != nil {
|
||||
|
@ -28,7 +28,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
|
||||
syscall.CloseOnExec(s)
|
||||
syscall.ForkLock.RUnlock()
|
||||
|
||||
setKernelSpecificSockopt(s, f)
|
||||
setDefaultSockopts(s, f, p)
|
||||
|
||||
if la != nil {
|
||||
e = syscall.Bind(s, la)
|
||||
|
@ -12,22 +12,33 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setKernelSpecificSockopt(s, f int) {
|
||||
// Allow reuse of recently-used addresses.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
func setDefaultSockopts(s, f, p int) {
|
||||
switch f {
|
||||
case syscall.AF_INET6:
|
||||
// Allow both IP versions even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
|
||||
// Allow reuse of recently-used ports.
|
||||
// This option is supported only in descendants of 4.4BSD,
|
||||
// to make an effective multicast application and an application
|
||||
// that requires quick draw possible.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
|
||||
if f == syscall.AF_UNIX || p == syscall.IPPROTO_TCP {
|
||||
// Allow reuse of recently-used addresses.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
|
||||
// Allow reuse of recently-used ports.
|
||||
// This option is supported only in descendants of 4.4BSD,
|
||||
// to make an effective multicast application and an application
|
||||
// that requires quick draw possible.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
|
||||
}
|
||||
|
||||
// Allow broadcast.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
|
||||
|
||||
if f == syscall.AF_INET6 {
|
||||
// using ip, tcp, udp, etc.
|
||||
// allow both protocols even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaultMulticastSockopts(fd *netFD) {
|
||||
fd.incref()
|
||||
defer fd.decref()
|
||||
// Allow multicast UDP and raw IP datagram sockets to listen
|
||||
// concurrently across multiple listeners.
|
||||
syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
|
||||
}
|
||||
|
@ -10,16 +10,27 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setKernelSpecificSockopt(s, f int) {
|
||||
// Allow reuse of recently-used addresses.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
func setDefaultSockopts(s, f, p int) {
|
||||
switch f {
|
||||
case syscall.AF_INET6:
|
||||
// Allow both IP versions even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
|
||||
if f == syscall.AF_UNIX || p == syscall.IPPROTO_TCP {
|
||||
// Allow reuse of recently-used addresses.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
}
|
||||
|
||||
// Allow broadcast.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
|
||||
|
||||
if f == syscall.AF_INET6 {
|
||||
// using ip, tcp, udp, etc.
|
||||
// allow both protocols even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaultMulticastSockopts(fd *netFD) {
|
||||
fd.incref()
|
||||
defer fd.decref()
|
||||
// Allow multicast UDP and raw IP datagram sockets to listen
|
||||
// concurrently across multiple listeners.
|
||||
syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
}
|
||||
|
@ -10,7 +10,13 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setKernelSpecificSockopt(s syscall.Handle, f int) {
|
||||
func setDefaultSockopts(s syscall.Handle, f, p int) {
|
||||
switch f {
|
||||
case syscall.AF_INET6:
|
||||
// Allow both IP versions even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
|
||||
// Windows will reuse recently-used addresses by default.
|
||||
// SO_REUSEADDR should not be used here, as it allows
|
||||
// a socket to forcibly bind to a port in use by another socket.
|
||||
@ -21,9 +27,12 @@ func setKernelSpecificSockopt(s syscall.Handle, f int) {
|
||||
// Allow broadcast.
|
||||
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
|
||||
|
||||
if f == syscall.AF_INET6 {
|
||||
// using ip, tcp, udp, etc.
|
||||
// allow both protocols even if the OS default is otherwise.
|
||||
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaultMulticastSockopts(fd *netFD) {
|
||||
fd.incref()
|
||||
defer fd.decref()
|
||||
// Allow multicast UDP and raw IP datagram sockets to listen
|
||||
// concurrently across multiple listeners.
|
||||
syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
}
|
||||
|
@ -251,6 +251,7 @@ func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error {
|
||||
if !c.ok() {
|
||||
return os.EINVAL
|
||||
}
|
||||
setDefaultMulticastSockopts(c.fd)
|
||||
ip := addr.To4()
|
||||
if ip != nil {
|
||||
return joinIPv4GroupUDP(c, ifi, ip)
|
||||
|
Loading…
Reference in New Issue
Block a user