aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net')
-rw-r--r--libgo/go/net/file_test.go5
-rw-r--r--libgo/go/net/http/cookie.go2
-rw-r--r--libgo/go/net/http/request.go4
-rw-r--r--libgo/go/net/interface.go20
-rw-r--r--libgo/go/net/iprawsock_plan9.go4
-rw-r--r--libgo/go/net/iprawsock_posix.go6
-rw-r--r--libgo/go/net/ipsock_posix.go5
-rw-r--r--libgo/go/net/multicast_test.go130
-rw-r--r--libgo/go/net/rpc/server_test.go5
-rw-r--r--libgo/go/net/server_test.go7
-rw-r--r--libgo/go/net/sock.go88
-rw-r--r--libgo/go/net/sock_bsd.go36
-rw-r--r--libgo/go/net/sock_linux.go32
-rw-r--r--libgo/go/net/sock_windows.go25
-rw-r--r--libgo/go/net/sockopt.go171
-rw-r--r--libgo/go/net/sockopt_bsd.go44
-rw-r--r--libgo/go/net/sockopt_linux.go36
-rw-r--r--libgo/go/net/sockopt_windows.go38
-rw-r--r--libgo/go/net/sockoptip.go187
-rw-r--r--libgo/go/net/sockoptip_bsd.go54
-rw-r--r--libgo/go/net/sockoptip_darwin.go78
-rw-r--r--libgo/go/net/sockoptip_freebsd.go80
-rw-r--r--libgo/go/net/sockoptip_linux.go120
-rw-r--r--libgo/go/net/sockoptip_openbsd.go78
-rw-r--r--libgo/go/net/sockoptip_windows.go61
-rw-r--r--libgo/go/net/tcpsock_posix.go6
-rw-r--r--libgo/go/net/textproto/reader.go71
-rw-r--r--libgo/go/net/textproto/reader_test.go9
-rw-r--r--libgo/go/net/udpsock_posix.go54
-rw-r--r--libgo/go/net/unicast_test.go99
-rw-r--r--libgo/go/net/unixsock_posix.go8
31 files changed, 1285 insertions, 278 deletions
diff --git a/libgo/go/net/file_test.go b/libgo/go/net/file_test.go
index 7867fa8..868388e 100644
--- a/libgo/go/net/file_test.go
+++ b/libgo/go/net/file_test.go
@@ -8,7 +8,6 @@ import (
"os"
"reflect"
"runtime"
- "syscall"
"testing"
)
@@ -67,7 +66,7 @@ func TestFileListener(t *testing.T) {
testFileListener(t, "tcp", "127.0.0.1")
testFileListener(t, "tcp", "[::ffff:127.0.0.1]")
}
- if syscall.OS == "linux" {
+ if runtime.GOOS == "linux" {
testFileListener(t, "unix", "@gotest/net")
testFileListener(t, "unixpacket", "@gotest/net")
}
@@ -132,7 +131,7 @@ func TestFilePacketConn(t *testing.T) {
if supportsIPv6 && supportsIPv4map {
testFilePacketConnDial(t, "udp", "[::ffff:127.0.0.1]:12345")
}
- if syscall.OS == "linux" {
+ if runtime.GOOS == "linux" {
testFilePacketConnListen(t, "unixgram", "@gotest1/net")
}
}
diff --git a/libgo/go/net/http/cookie.go b/libgo/go/net/http/cookie.go
index cad8522..2e30bbf 100644
--- a/libgo/go/net/http/cookie.go
+++ b/libgo/go/net/http/cookie.go
@@ -96,7 +96,7 @@ func readSetCookies(h Header) []*Cookie {
continue
case "max-age":
secs, err := strconv.Atoi(val)
- if err != nil || secs < 0 || secs != 0 && val[0] == '0' {
+ if err != nil || secs != 0 && val[0] == '0' {
break
}
if secs <= 0 {
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 6617849..2603010 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -368,8 +368,8 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
if err != nil {
return err
}
- bw.Flush()
- return nil
+
+ return bw.Flush()
}
// Convert decimal at s[i:len(s)] to integer,
diff --git a/libgo/go/net/interface.go b/libgo/go/net/interface.go
index 95486a6..5e7b352 100644
--- a/libgo/go/net/interface.go
+++ b/libgo/go/net/interface.go
@@ -12,6 +12,14 @@ import (
"fmt"
)
+var (
+ errInvalidInterface = errors.New("net: invalid interface")
+ errInvalidInterfaceIndex = errors.New("net: invalid interface index")
+ errInvalidInterfaceName = errors.New("net: invalid interface name")
+ errNoSuchInterface = errors.New("net: no such interface")
+ errNoSuchMulticastInterface = errors.New("net: no such multicast interface")
+)
+
// A HardwareAddr represents a physical hardware address.
type HardwareAddr []byte
@@ -131,7 +139,7 @@ func (f Flags) String() string {
// Addrs returns interface addresses for a specific interface.
func (ifi *Interface) Addrs() ([]Addr, error) {
if ifi == nil {
- return nil, errors.New("net: invalid interface")
+ return nil, errInvalidInterface
}
return interfaceAddrTable(ifi.Index)
}
@@ -140,7 +148,7 @@ func (ifi *Interface) Addrs() ([]Addr, error) {
// a specific interface.
func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
if ifi == nil {
- return nil, errors.New("net: invalid interface")
+ return nil, errInvalidInterface
}
return interfaceMulticastAddrTable(ifi.Index)
}
@@ -159,7 +167,7 @@ func InterfaceAddrs() ([]Addr, error) {
// InterfaceByIndex returns the interface specified by index.
func InterfaceByIndex(index int) (*Interface, error) {
if index <= 0 {
- return nil, errors.New("net: invalid interface index")
+ return nil, errInvalidInterfaceIndex
}
ift, err := interfaceTable(index)
if err != nil {
@@ -168,13 +176,13 @@ func InterfaceByIndex(index int) (*Interface, error) {
for _, ifi := range ift {
return &ifi, nil
}
- return nil, errors.New("net: no such interface")
+ return nil, errNoSuchInterface
}
// InterfaceByName returns the interface specified by name.
func InterfaceByName(name string) (*Interface, error) {
if name == "" {
- return nil, errors.New("net: invalid interface name")
+ return nil, errInvalidInterfaceName
}
ift, err := interfaceTable(0)
if err != nil {
@@ -185,5 +193,5 @@ func InterfaceByName(name string) (*Interface, error) {
return &ifi, nil
}
}
- return nil, errors.New("net: no such interface")
+ return nil, errNoSuchInterface
}
diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go
index 7e4bc56..3fd9dce 100644
--- a/libgo/go/net/iprawsock_plan9.go
+++ b/libgo/go/net/iprawsock_plan9.go
@@ -84,8 +84,8 @@ func splitNetProto(netProto string) (net string, proto int, err error) {
return
}
-// DialIP connects to the remote address raddr on the network net,
-// which must be "ip", "ip4", or "ip6".
+// DialIP connects to the remote address raddr on the network protocol netProto,
+// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
return nil, os.EPLAN9
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index 7bb4c7d..103c4f6 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -224,8 +224,8 @@ func splitNetProto(netProto string) (net string, proto int, err error) {
return net, proto, nil
}
-// DialIP connects to the remote address raddr on the network net,
-// which must be "ip", "ip4", or "ip6".
+// DialIP connects to the remote address raddr on the network protocol netProto,
+// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
net, proto, err := splitNetProto(netProto)
if err != nil {
@@ -260,7 +260,7 @@ func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
default:
return nil, UnknownNetworkError(net)
}
- fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+ fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
if e != nil {
return nil, e
}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index d141c05..45fe0d9 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -91,11 +91,6 @@ func favoriteAddrFamily(net string, raddr, laddr sockaddr, mode string) int {
return syscall.AF_INET6
}
-// TODO(rsc): if syscall.OS == "linux", we're supposed to read
-// /proc/sys/net/core/somaxconn,
-// to take advantage of kernels that have raised the limit.
-func listenBacklog() int { return syscall.SOMAXCONN }
-
// Internet sockets (TCP, UDP)
// A sockaddr represents a TCP or UDP network address that can
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go
index a66250c..183d5a8 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_test.go
@@ -13,7 +13,7 @@ import (
var multicast = flag.Bool("multicast", false, "enable multicast tests")
-var joinAndLeaveGroupUDPTests = []struct {
+var multicastUDPTests = []struct {
net string
laddr IP
gaddr IP
@@ -32,8 +32,8 @@ var joinAndLeaveGroupUDPTests = []struct {
{"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
}
-func TestJoinAndLeaveGroupUDP(t *testing.T) {
- if runtime.GOOS == "windows" {
+func TestMulticastUDP(t *testing.T) {
+ if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
return
}
if !*multicast {
@@ -41,7 +41,7 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
return
}
- for _, tt := range joinAndLeaveGroupUDPTests {
+ for _, tt := range multicastUDPTests {
var (
ifi *Interface
found bool
@@ -51,7 +51,7 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
}
ift, err := Interfaces()
if err != nil {
- t.Fatalf("Interfaces() failed: %v", err)
+ t.Fatalf("Interfaces failed: %v", err)
}
for _, x := range ift {
if x.Flags&tt.flags == tt.flags {
@@ -65,15 +65,20 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
}
c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
if err != nil {
- t.Fatal(err)
+ t.Fatalf("ListenUDP failed: %v", err)
}
defer c.Close()
if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
- t.Fatal(err)
+ t.Fatalf("JoinGroup failed: %v", err)
+ }
+ if !tt.ipv6 {
+ testIPv4MulticastSocketOptions(t, c.fd, ifi)
+ } else {
+ testIPv6MulticastSocketOptions(t, c.fd, ifi)
}
ifmat, err := ifi.MulticastAddrs()
if err != nil {
- t.Fatalf("MulticastAddrs() failed: %v", err)
+ t.Fatalf("MulticastAddrs failed: %v", err)
}
for _, ifma := range ifmat {
if ifma.(*IPAddr).IP.Equal(tt.gaddr) {
@@ -85,7 +90,114 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
t.Fatalf("%q not found in RIB", tt.gaddr.String())
}
if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
- t.Fatal(err)
+ t.Fatalf("LeaveGroup failed: %v", err)
+ }
+ }
+}
+
+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 {
+ t.Fatalf("ipv4MulticastInterface failed: %v", err)
+ }
+ t.Logf("IPv4 multicast interface: %v", ifmc)
+ err = setIPv4MulticastInterface(fd, ifi)
+ if err != nil {
+ t.Fatalf("setIPv4MulticastInterface failed: %v", err)
+ }
+
+ ttl, err := ipv4MulticastTTL(fd)
+ if err != nil {
+ t.Fatalf("ipv4MulticastTTL failed: %v", err)
+ }
+ t.Logf("IPv4 multicast TTL: %v", ttl)
+ err = setIPv4MulticastTTL(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv4MulticastTTL failed: %v", err)
+ }
+
+ loop, err := ipv4MulticastLoopback(fd)
+ if err != nil {
+ t.Fatalf("ipv4MulticastLoopback failed: %v", err)
+ }
+ t.Logf("IPv4 multicast loopback: %v", loop)
+ err = setIPv4MulticastLoopback(fd, false)
+ if err != nil {
+ t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
+ }
+}
+
+func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
+ ifmc, err := ipv6MulticastInterface(fd)
+ if err != nil {
+ t.Fatalf("ipv6MulticastInterface failed: %v", err)
+ }
+ t.Logf("IPv6 multicast interface: %v", ifmc)
+ err = setIPv6MulticastInterface(fd, ifi)
+ if err != nil {
+ t.Fatalf("setIPv6MulticastInterface failed: %v", err)
+ }
+
+ hoplim, err := ipv6MulticastHopLimit(fd)
+ if err != nil {
+ t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
+ }
+ t.Logf("IPv6 multicast hop limit: %v", hoplim)
+ err = setIPv6MulticastHopLimit(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
+ }
+
+ loop, err := ipv6MulticastLoopback(fd)
+ if err != nil {
+ t.Fatalf("ipv6MulticastLoopback failed: %v", err)
+ }
+ t.Logf("IPv6 multicast loopback: %v", loop)
+ err = setIPv6MulticastLoopback(fd, false)
+ if err != nil {
+ t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
+ }
+}
diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go
index c1845fa..ae688c0 100644
--- a/libgo/go/net/rpc/server_test.go
+++ b/libgo/go/net/rpc/server_test.go
@@ -498,8 +498,7 @@ func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
once.Do(startServer)
client, err := dial()
if err != nil {
- fmt.Println("error dialing", err)
- return
+ b.Fatal("error dialing:", err)
}
// Synchronous calls
@@ -534,7 +533,7 @@ func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) {
once.Do(startServer)
client, err := dial()
if err != nil {
- b.Fatalf("error dialing:", err)
+ b.Fatal("error dialing:", err)
}
// Asynchronous calls
diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go
index 7d17ccd..5475d38 100644
--- a/libgo/go/net/server_test.go
+++ b/libgo/go/net/server_test.go
@@ -10,7 +10,6 @@ import (
"os"
"runtime"
"strings"
- "syscall"
"testing"
)
@@ -115,7 +114,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
}
func TestTCPServer(t *testing.T) {
- if syscall.OS != "openbsd" {
+ if runtime.GOOS != "openbsd" {
doTest(t, "tcp", "", "127.0.0.1")
}
doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
@@ -155,7 +154,7 @@ func TestUnixServer(t *testing.T) {
os.Remove("/tmp/gotest.net")
doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
os.Remove("/tmp/gotest.net")
- if syscall.OS == "linux" {
+ if runtime.GOOS == "linux" {
doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
os.Remove("/tmp/gotest.net")
// Test abstract unix domain socket, a Linux-ism
@@ -237,7 +236,7 @@ func TestUnixDatagramServer(t *testing.T) {
doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
os.Remove("/tmp/gotest1.net")
os.Remove("/tmp/gotest1.net.local")
- if syscall.OS == "linux" {
+ if runtime.GOOS == "linux" {
// Test abstract unix domain socket, a Linux-ism
doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
}
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index dc07392..881c922 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -10,18 +10,11 @@ package net
import (
"io"
- "os"
"reflect"
"syscall"
)
-// Boolean to int.
-func boolint(b bool) int {
- if b {
- return 1
- }
- return 0
-}
+var listenerBacklog = maxListenerBacklog()
// Generic socket creation.
func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
@@ -35,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)
@@ -67,83 +60,6 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
return fd, nil
}
-func setsockoptInt(fd *netFD, level, opt int, value int) error {
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, level, opt, value))
-}
-
-func setsockoptNsec(fd *netFD, level, opt int, nsec int64) error {
- var tv = syscall.NsecToTimeval(nsec)
- return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd.sysfd, level, opt, &tv))
-}
-
-func setReadBuffer(fd *netFD, bytes int) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
-}
-
-func setWriteBuffer(fd *netFD, bytes int) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
-}
-
-func setReadTimeout(fd *netFD, nsec int64) error {
- fd.rdeadline_delta = nsec
- return nil
-}
-
-func setWriteTimeout(fd *netFD, nsec int64) error {
- fd.wdeadline_delta = nsec
- return nil
-}
-
-func setTimeout(fd *netFD, nsec int64) error {
- if e := setReadTimeout(fd, nsec); e != nil {
- return e
- }
- return setWriteTimeout(fd, nsec)
-}
-
-func setReuseAddr(fd *netFD, reuse bool) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
-}
-
-func setDontRoute(fd *netFD, dontroute bool) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
-}
-
-func setKeepAlive(fd *netFD, keepalive bool) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
-}
-
-func setNoDelay(fd *netFD, noDelay bool) error {
- fd.incref()
- defer fd.decref()
- return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
-}
-
-func setLinger(fd *netFD, sec int) error {
- var l syscall.Linger
- if sec >= 0 {
- l.Onoff = 1
- l.Linger = int32(sec)
- } else {
- l.Onoff = 0
- l.Linger = 0
- }
- fd.incref()
- defer fd.decref()
- e := syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
- return os.NewSyscallError("setsockopt", e)
-}
-
type UnknownSocketError struct {
sa syscall.Sockaddr
}
diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go
index 816e4fc..630a91e 100644
--- a/libgo/go/net/sock_bsd.go
+++ b/libgo/go/net/sock_bsd.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,25 +9,25 @@
package net
import (
+ "runtime"
"syscall"
)
-func setKernelSpecificSockopt(s, f int) {
- // 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 maxListenerBacklog() int {
+ var (
+ n uint32
+ err error
+ )
+ switch runtime.GOOS {
+ case "darwin", "freebsd":
+ n, err = syscall.SysctlUint32("kern.ipc.somaxconn")
+ case "netbsd":
+ // NOTE: NetBSD has no somaxconn-like kernel state so far
+ case "openbsd":
+ n, err = syscall.SysctlUint32("kern.somaxconn")
+ }
+ if n == 0 || err != nil {
+ return syscall.SOMAXCONN
}
+ return int(n)
}
diff --git a/libgo/go/net/sock_linux.go b/libgo/go/net/sock_linux.go
index ec31e80..2cbc34f 100644
--- a/libgo/go/net/sock_linux.go
+++ b/libgo/go/net/sock_linux.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -6,20 +6,22 @@
package net
-import (
- "syscall"
-)
+import "syscall"
-func setKernelSpecificSockopt(s, f int) {
- // 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 maxListenerBacklog() int {
+ fd, err := open("/proc/sys/net/core/somaxconn")
+ if err != nil {
+ return syscall.SOMAXCONN
+ }
+ defer fd.close()
+ l, ok := fd.readLine()
+ if !ok {
+ return syscall.SOMAXCONN
+ }
+ f := getFields(l)
+ n, _, ok := dtoi(f[0], 0)
+ if n == 0 || !ok {
+ return syscall.SOMAXCONN
}
+ return n
}
diff --git a/libgo/go/net/sock_windows.go b/libgo/go/net/sock_windows.go
index 9b9cd9e..2d803de 100644
--- a/libgo/go/net/sock_windows.go
+++ b/libgo/go/net/sock_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -6,24 +6,9 @@
package net
-import (
- "syscall"
-)
+import "syscall"
-func setKernelSpecificSockopt(s syscall.Handle, f int) {
- // 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.
- // This could lead to a non-deterministic behavior, where
- // connection requests over the port cannot be guaranteed
- // to be handled by the correct socket.
-
- // 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 maxListenerBacklog() int {
+ // TODO: Implement this
+ return syscall.SOMAXCONN
}
diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt.go
new file mode 100644
index 0000000..7fa1052
--- /dev/null
+++ b/libgo/go/net/sockopt.go
@@ -0,0 +1,171 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd windows
+
+// Socket options
+
+package net
+
+import (
+ "bytes"
+ "os"
+ "syscall"
+)
+
+// Boolean to int.
+func boolint(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+func ipv4AddrToInterface(ip IP) (*Interface, error) {
+ ift, err := Interfaces()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifi := range ift {
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifa := range ifat {
+ switch v := ifa.(type) {
+ case *IPAddr:
+ if ip.Equal(v.IP) {
+ return &ifi, nil
+ }
+ case *IPNet:
+ if ip.Equal(v.IP) {
+ return &ifi, nil
+ }
+ }
+ }
+ }
+ if ip.Equal(IPv4zero) {
+ return nil, nil
+ }
+ return nil, errNoSuchInterface
+}
+
+func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
+ if ifi == nil {
+ return IPv4zero, nil
+ }
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifa := range ifat {
+ switch v := ifa.(type) {
+ case *IPAddr:
+ if v.IP.To4() != nil {
+ return v.IP, nil
+ }
+ case *IPNet:
+ if v.IP.To4() != nil {
+ return v.IP, nil
+ }
+ }
+ }
+ return nil, errNoSuchInterface
+}
+
+func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
+ if ifi == nil {
+ return nil
+ }
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return err
+ }
+ for _, ifa := range ifat {
+ switch v := ifa.(type) {
+ case *IPAddr:
+ if a := v.IP.To4(); a != nil {
+ copy(mreq.Interface[:], a)
+ goto done
+ }
+ case *IPNet:
+ if a := v.IP.To4(); a != nil {
+ copy(mreq.Interface[:], a)
+ goto done
+ }
+ }
+ }
+done:
+ if bytes.Equal(mreq.Multiaddr[:], IPv4zero.To4()) {
+ return errNoSuchMulticastInterface
+ }
+ return nil
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
+}
+
+func setReadTimeout(fd *netFD, nsec int64) error {
+ fd.rdeadline_delta = nsec
+ return nil
+}
+
+func setWriteTimeout(fd *netFD, nsec int64) error {
+ fd.wdeadline_delta = nsec
+ return nil
+}
+
+func setTimeout(fd *netFD, nsec int64) error {
+ if e := setReadTimeout(fd, nsec); e != nil {
+ return e
+ }
+ return setWriteTimeout(fd, nsec)
+}
+
+func setReuseAddr(fd *netFD, reuse bool) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
+}
+
+func setDontRoute(fd *netFD, dontroute bool) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
+}
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
+}
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+}
+
+func setLinger(fd *netFD, sec int) error {
+ var l syscall.Linger
+ if sec >= 0 {
+ l.Onoff = 1
+ l.Linger = int32(sec)
+ } else {
+ l.Onoff = 0
+ l.Linger = 0
+ }
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
+}
diff --git a/libgo/go/net/sockopt_bsd.go b/libgo/go/net/sockopt_bsd.go
new file mode 100644
index 0000000..e99fb41
--- /dev/null
+++ b/libgo/go/net/sockopt_bsd.go
@@ -0,0 +1,44 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd netbsd openbsd
+
+// Socket options for BSD variants
+
+package net
+
+import (
+ "syscall"
+)
+
+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 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)
+}
+
+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)
+}
diff --git a/libgo/go/net/sockopt_linux.go b/libgo/go/net/sockopt_linux.go
new file mode 100644
index 0000000..5158384
--- /dev/null
+++ b/libgo/go/net/sockopt_linux.go
@@ -0,0 +1,36 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Socket options for Linux
+
+package net
+
+import (
+ "syscall"
+)
+
+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)
+
+}
+
+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)
+}
diff --git a/libgo/go/net/sockopt_windows.go b/libgo/go/net/sockopt_windows.go
new file mode 100644
index 0000000..485c14a
--- /dev/null
+++ b/libgo/go/net/sockopt_windows.go
@@ -0,0 +1,38 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Socket options for Windows
+
+package net
+
+import (
+ "syscall"
+)
+
+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.
+ // This could lead to a non-deterministic behavior, where
+ // connection requests over the port cannot be guaranteed
+ // to be handled by the correct socket.
+
+ // Allow broadcast.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+}
+
+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)
+}
diff --git a/libgo/go/net/sockoptip.go b/libgo/go/net/sockoptip.go
new file mode 100644
index 0000000..90b6f75
--- /dev/null
+++ b/libgo/go/net/sockoptip.go
@@ -0,0 +1,187 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd windows
+
+// IP-level socket options
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4TOS(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv4TOS(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4TTL(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv4TTL(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+ if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+ return err
+ }
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+}
+
+func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+ if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+ return err
+ }
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
+}
+
+func ipv6HopLimit(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv6HopLimit(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ if v == 0 {
+ return nil, nil
+ }
+ ifi, err := InterfaceByIndex(v)
+ if err != nil {
+ return nil, err
+ }
+ return ifi, nil
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+ var v int
+ if ifi != nil {
+ v = ifi.Index
+ }
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv6MulticastHopLimit(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv6MulticastHopLimit(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv6MulticastLoopback(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPv6Mreq{}
+ copy(mreq.Multiaddr[:], ip)
+ if ifi != nil {
+ mreq.Interface = uint32(ifi.Index)
+ }
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
+}
+
+func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+ mreq := &syscall.IPv6Mreq{}
+ copy(mreq.Multiaddr[:], ip)
+ if ifi != nil {
+ mreq.Interface = uint32(ifi.Index)
+ }
+ fd.incref()
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
+}
diff --git a/libgo/go/net/sockoptip_bsd.go b/libgo/go/net/sockoptip_bsd.go
new file mode 100644
index 0000000..5f7dff2
--- /dev/null
+++ b/libgo/go/net/sockoptip_bsd.go
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd netbsd openbsd
+
+// IP-level socket options for BSD variants
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return int(v), nil
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_darwin.go b/libgo/go/net/sockoptip_darwin.go
new file mode 100644
index 0000000..dedfd6f
--- /dev/null
+++ b/libgo/go/net/sockoptip_darwin.go
@@ -0,0 +1,78 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for Darwin
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+ fd.incref()
+ defer fd.decref()
+ a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ ip, err := interfaceToIPv4Addr(ifi)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ var x [4]byte
+ copy(x[:], ip.To4())
+ fd.incref()
+ defer fd.decref()
+ err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_freebsd.go b/libgo/go/net/sockoptip_freebsd.go
new file mode 100644
index 0000000..55f7b1a
--- /dev/null
+++ b/libgo/go/net/sockoptip_freebsd.go
@@ -0,0 +1,80 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for FreeBSD
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+ fd.incref()
+ defer fd.decref()
+ mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ if int(mreq.Ifindex) == 0 {
+ return nil, nil
+ }
+ return InterfaceByIndex(int(mreq.Ifindex))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ var v int32
+ if ifi != nil {
+ v = int32(ifi.Index)
+ }
+ mreq := &syscall.IPMreqn{Ifindex: v}
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_linux.go b/libgo/go/net/sockoptip_linux.go
new file mode 100644
index 0000000..360f8de
--- /dev/null
+++ b/libgo/go/net/sockoptip_linux.go
@@ -0,0 +1,120 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for Linux
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+ fd.incref()
+ defer fd.decref()
+ mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ if int(mreq.Ifindex) == 0 {
+ return nil, nil
+ }
+ return InterfaceByIndex(int(mreq.Ifindex))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ var v int32
+ if ifi != nil {
+ v = int32(ifi.Index)
+ }
+ mreq := &syscall.IPMreqn{Ifindex: v}
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
+ if err != nil {
+ return -1, os.NewSyscallError("getsockopt", err)
+ }
+ return v, nil
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_openbsd.go b/libgo/go/net/sockoptip_openbsd.go
new file mode 100644
index 0000000..89b8e45
--- /dev/null
+++ b/libgo/go/net/sockoptip_openbsd.go
@@ -0,0 +1,78 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for OpenBSD
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+ fd.incref()
+ defer fd.decref()
+ a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+ if err != nil {
+ return nil, os.NewSyscallError("getsockopt", err)
+ }
+ return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ ip, err := interfaceToIPv4Addr(ifi)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ var x [4]byte
+ copy(x[:], ip.To4())
+ fd.incref()
+ defer fd.decref()
+ err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+ fd.incref()
+ defer fd.decref()
+ v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+ if err != nil {
+ return false, os.NewSyscallError("getsockopt", err)
+ }
+ return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+ fd.incref()
+ defer fd.decref()
+ err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+ if err != nil {
+ return os.NewSyscallError("setsockopt", err)
+ }
+ return nil
+}
diff --git a/libgo/go/net/sockoptip_windows.go b/libgo/go/net/sockoptip_windows.go
new file mode 100644
index 0000000..3320e76
--- /dev/null
+++ b/libgo/go/net/sockoptip_windows.go
@@ -0,0 +1,61 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for Windows
+
+package net
+
+import (
+ "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+ // TODO: Implement this
+ return nil, syscall.EWINDOWS
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+ // TODO: Implement this
+ return syscall.EWINDOWS
+}
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+ // TODO: Implement this
+ return -1, syscall.EWINDOWS
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+ // TODO: Implement this
+ return syscall.EWINDOWS
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+ // TODO: Implement this
+ return false, syscall.EWINDOWS
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+ // TODO: Implement this
+ return syscall.EWINDOWS
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+ // TODO: Implement this
+ return false, syscall.EWINDOWS
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+ // TODO: Implement this
+ return syscall.EWINDOWS
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+ // TODO: Implement this
+ return 0, syscall.EWINDOWS
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+ // TODO: Implement this
+ return syscall.EWINDOWS
+}
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index a7c09c7..a492e61 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -249,10 +249,10 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
if err != nil {
return nil, err
}
- errno := syscall.Listen(fd.sysfd, listenBacklog())
- if errno != nil {
+ err = syscall.Listen(fd.sysfd, listenerBacklog)
+ if err != nil {
closesocket(fd.sysfd)
- return nil, &OpError{"listen", "tcp", laddr, errno}
+ return nil, &OpError{"listen", "tcp", laddr, err}
}
l = new(TCPListener)
l.fd = fd
diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go
index 793c6c2..862cd53 100644
--- a/libgo/go/net/textproto/reader.go
+++ b/libgo/go/net/textproto/reader.go
@@ -22,6 +22,7 @@ import (
type Reader struct {
R *bufio.Reader
dot *dotReader
+ buf []byte // a re-usable buffer for readContinuedLineSlice
}
// NewReader returns a new Reader reading from r.
@@ -121,74 +122,44 @@ func (r *Reader) readContinuedLineSlice() ([]byte, error) {
// Read the first line.
line, err := r.readLineSlice()
if err != nil {
- return line, err
+ return nil, err
}
if len(line) == 0 { // blank line - no continuation
return line, nil
}
- line = trim(line)
- copied := false
- if r.R.Buffered() < 1 {
- // ReadByte will flush the buffer; make a copy of the slice.
- copied = true
- line = append([]byte(nil), line...)
- }
-
- // Look for a continuation line.
- c, err := r.R.ReadByte()
- if err != nil {
- // Delay err until we read the byte next time.
- return line, nil
- }
- if c != ' ' && c != '\t' {
- // Not a continuation.
- r.R.UnreadByte()
- return line, nil
- }
-
- if !copied {
- // The next readLineSlice will invalidate the previous one.
- line = append(make([]byte, 0, len(line)*2), line...)
- }
+ // ReadByte or the next readLineSlice will flush the read buffer;
+ // copy the slice into buf.
+ r.buf = append(r.buf[:0], trim(line)...)
// Read continuation lines.
- for {
- // Consume leading spaces; one already gone.
- for {
- c, err = r.R.ReadByte()
- if err != nil {
- break
- }
- if c != ' ' && c != '\t' {
- r.R.UnreadByte()
- break
- }
- }
- var cont []byte
- cont, err = r.readLineSlice()
- cont = trim(cont)
- line = append(line, ' ')
- line = append(line, cont...)
+ for r.skipSpace() > 0 {
+ line, err := r.readLineSlice()
if err != nil {
break
}
+ r.buf = append(r.buf, ' ')
+ r.buf = append(r.buf, line...)
+ }
+ return r.buf, nil
+}
- // Check for leading space on next line.
- if c, err = r.R.ReadByte(); err != nil {
+// skipSpace skips R over all spaces and returns the number of bytes skipped.
+func (r *Reader) skipSpace() int {
+ n := 0
+ for {
+ c, err := r.R.ReadByte()
+ if err != nil {
+ // Bufio will keep err until next read.
break
}
if c != ' ' && c != '\t' {
r.R.UnreadByte()
break
}
+ n++
}
-
- // Delay error until next call.
- if len(line) > 0 {
- err = nil
- }
- return line, err
+ return n
}
func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err error) {
diff --git a/libgo/go/net/textproto/reader_test.go b/libgo/go/net/textproto/reader_test.go
index 0460c1c..4d03691 100644
--- a/libgo/go/net/textproto/reader_test.go
+++ b/libgo/go/net/textproto/reader_test.go
@@ -138,6 +138,15 @@ func TestReadMIMEHeader(t *testing.T) {
}
}
+func TestReadMIMEHeaderSingle(t *testing.T) {
+ r := reader("Foo: bar\n\n")
+ m, err := r.ReadMIMEHeader()
+ want := MIMEHeader{"Foo": {"bar"}}
+ if !reflect.DeepEqual(m, want) || err != nil {
+ t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
+ }
+}
+
func TestLargeReadMIMEHeader(t *testing.T) {
data := make([]byte, 16*1024)
for i := 0; i < len(data); i++ {
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index 6bb1571..d0bdb14 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -9,7 +9,6 @@
package net
import (
- "bytes"
"os"
"syscall"
)
@@ -233,7 +232,7 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
if laddr == nil {
return nil, &OpError{"listen", "udp", nil, errMissingAddress}
}
- fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
+ fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
if e != nil {
return nil, e
}
@@ -252,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)
@@ -272,66 +272,32 @@ func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
}
func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
- if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
- return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
- }
- if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)); err != nil {
+ err := joinIPv4Group(c.fd, ifi, ip)
+ if err != nil {
return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
}
return nil
}
func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
- if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
- return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
- }
- if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)); err != nil {
- return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
- }
- return nil
-}
-
-func setIPv4InterfaceToJoin(mreq *syscall.IPMreq, ifi *Interface) error {
- if ifi == nil {
- return nil
- }
- ifat, err := ifi.Addrs()
+ err := leaveIPv4Group(c.fd, ifi, ip)
if err != nil {
- return err
- }
- for _, ifa := range ifat {
- if x := ifa.(*IPAddr).IP.To4(); x != nil {
- copy(mreq.Interface[:], x)
- break
- }
- }
- if bytes.Equal(mreq.Multiaddr[:], IPv4zero) {
- return os.EINVAL
+ return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
}
return nil
}
func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- mreq := &syscall.IPv6Mreq{}
- copy(mreq.Multiaddr[:], ip)
- if ifi != nil {
- mreq.Interface = uint32(ifi.Index)
- }
- if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)); err != nil {
+ err := joinIPv6Group(c.fd, ifi, ip)
+ if err != nil {
return &OpError{"joinipv6group", "udp", &IPAddr{ip}, err}
}
return nil
}
func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
- mreq := &syscall.IPv6Mreq{}
- copy(mreq.Multiaddr[:], ip)
- if ifi != nil {
- mreq.Interface = uint32(ifi.Index)
- }
- if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq)); err != nil {
+ err := leaveIPv6Group(c.fd, ifi, ip)
+ if err != nil {
return &OpError{"leaveipv6group", "udp", &IPAddr{ip}, err}
}
return nil
diff --git a/libgo/go/net/unicast_test.go b/libgo/go/net/unicast_test.go
new file mode 100644
index 0000000..6ed6f59
--- /dev/null
+++ b/libgo/go/net/unicast_test.go
@@ -0,0 +1,99 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "runtime"
+ "testing"
+)
+
+var unicastTests = []struct {
+ net string
+ laddr string
+ ipv6 bool
+ packet bool
+}{
+ {"tcp4", "127.0.0.1:0", false, false},
+ {"tcp6", "[::1]:0", true, false},
+ {"udp4", "127.0.0.1:0", false, true},
+ {"udp6", "[::1]:0", true, true},
+}
+
+func TestUnicastTCPAndUDP(t *testing.T) {
+ if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
+ return
+ }
+
+ for _, tt := range unicastTests {
+ if tt.ipv6 && !supportsIPv6 {
+ continue
+ }
+ var fd *netFD
+ if !tt.packet {
+ c, err := Listen(tt.net, tt.laddr)
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+ defer c.Close()
+ fd = c.(*TCPListener).fd
+ } else {
+ c, err := ListenPacket(tt.net, tt.laddr)
+ if err != nil {
+ t.Fatalf("ListenPacket failed: %v", err)
+ }
+ defer c.Close()
+ fd = c.(*UDPConn).fd
+ }
+ if !tt.ipv6 {
+ testIPv4UnicastSocketOptions(t, fd)
+ } else {
+ testIPv6UnicastSocketOptions(t, fd)
+ }
+ }
+}
+
+func testIPv4UnicastSocketOptions(t *testing.T, fd *netFD) {
+ tos, err := ipv4TOS(fd)
+ if err != nil {
+ t.Fatalf("ipv4TOS failed: %v", err)
+ }
+ t.Logf("IPv4 TOS: %v", tos)
+ err = setIPv4TOS(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv4TOS failed: %v", err)
+ }
+
+ ttl, err := ipv4TTL(fd)
+ if err != nil {
+ t.Fatalf("ipv4TTL failed: %v", err)
+ }
+ t.Logf("IPv4 TTL: %v", ttl)
+ err = setIPv4TTL(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv4TTL failed: %v", err)
+ }
+}
+
+func testIPv6UnicastSocketOptions(t *testing.T, fd *netFD) {
+ tos, err := ipv6TrafficClass(fd)
+ if err != nil {
+ t.Fatalf("ipv6TrafficClass failed: %v", err)
+ }
+ t.Logf("IPv6 TrafficClass: %v", tos)
+ err = setIPv6TrafficClass(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv6TrafficClass failed: %v", err)
+ }
+
+ hoplim, err := ipv6HopLimit(fd)
+ if err != nil {
+ t.Fatalf("ipv6HopLimit failed: %v", err)
+ }
+ t.Logf("IPv6 HopLimit: %v", hoplim)
+ err = setIPv6HopLimit(fd, 1)
+ if err != nil {
+ t.Fatalf("setIPv6HopLimit failed: %v", err)
+ }
+}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 10632c1..00ee016 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -315,7 +315,7 @@ type UnixListener struct {
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
// Net must be "unix" (stream sockets).
-func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
if net != "unix" && net != "unixgram" && net != "unixpacket" {
return nil, UnknownNetworkError(net)
}
@@ -326,10 +326,10 @@ func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
if err != nil {
return nil, err
}
- e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
- if e1 != nil {
+ err = syscall.Listen(fd.sysfd, listenerBacklog)
+ if err != nil {
closesocket(fd.sysfd)
- return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: e1}
+ return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: err}
}
return &UnixListener{fd, laddr.Name}, nil
}