summaryrefslogtreecommitdiff
path: root/src/pkg/net
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-06-03 11:31:24 +0200
committerOndřej Surý <ondrej@sury.org>2011-06-03 11:38:02 +0200
commit13f4fcd5bf09c70942b6c85a2b919ffa1ca0c6a8 (patch)
tree717e1ceeef3a60af29e7897c7629d1502b797838 /src/pkg/net
parent6bf52070ef1028f7fcc98fad1e73795a7efd7ce7 (diff)
downloadgolang-13f4fcd5bf09c70942b6c85a2b919ffa1ca0c6a8.tar.gz
Imported Upstream version 2011.06.02
Diffstat (limited to 'src/pkg/net')
-rw-r--r--src/pkg/net/Makefile29
-rw-r--r--src/pkg/net/fd_linux.go11
-rw-r--r--src/pkg/net/fd_windows.go4
-rw-r--r--src/pkg/net/ip.go4
-rw-r--r--src/pkg/net/ipsock.go4
-rw-r--r--src/pkg/net/sendfile_linux.go84
-rw-r--r--src/pkg/net/sendfile_stub.go14
-rw-r--r--src/pkg/net/server_test.go11
-rw-r--r--src/pkg/net/sock.go12
-rw-r--r--src/pkg/net/tcpsock.go9
-rw-r--r--src/pkg/net/textproto/reader.go2
-rw-r--r--src/pkg/net/udpsock.go8
12 files changed, 166 insertions, 26 deletions
diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile
index 376e9c6dc..d4adbffc0 100644
--- a/src/pkg/net/Makefile
+++ b/src/pkg/net/Makefile
@@ -23,12 +23,13 @@ GOFILES=\
unixsock.go\
GOFILES_freebsd=\
- newpollserver.go\
+ dnsclient.go\
+ dnsconfig.go\
fd.go\
file.go\
- dnsconfig.go\
- dnsclient.go\
+ newpollserver.go\
port.go\
+ sendfile_stub.go\
sock_bsd.go\
CGOFILES_freebsd=\
@@ -36,27 +37,32 @@ CGOFILES_freebsd=\
cgo_unix.go\
GOFILES_darwin=\
- newpollserver.go\
+ dnsclient.go\
+ dnsconfig.go\
fd.go\
file.go\
- dnsconfig.go\
- dnsclient.go\
+ newpollserver.go\
port.go\
+ sendfile_stub.go\
sock_bsd.go\
CGOFILES_darwin=\
cgo_bsd.go\
cgo_unix.go\
-
+
GOFILES_linux=\
- newpollserver.go\
+ dnsclient.go\
+ dnsconfig.go\
fd.go\
file.go\
- dnsconfig.go\
- dnsclient.go\
+ newpollserver.go\
port.go\
+ sendfile_linux.go\
sock_linux.go\
+GOFILES_plan9=\
+ sendfile_stub.go\
+
ifeq ($(GOARCH),arm)
# ARM has no cgo, so use the stubs.
GOFILES_linux+=cgo_stub.go
@@ -68,8 +74,9 @@ endif
GOFILES_windows=\
cgo_stub.go\
- resolv_windows.go\
file_windows.go\
+ resolv_windows.go\
+ sendfile_stub.go\
sock_windows.go\
GOFILES+=$(GOFILES_$(GOOS))
diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go
index dcf65c014..70fc344b2 100644
--- a/src/pkg/net/fd_linux.go
+++ b/src/pkg/net/fd_linux.go
@@ -117,6 +117,17 @@ func (p *pollster) DelFD(fd int, mode int) {
} else {
p.StopWaiting(fd, writeFlags)
}
+
+ // Discard any queued up events.
+ i := 0
+ for i < len(p.waitEvents) {
+ if fd == int(p.waitEvents[i].Fd) {
+ copy(p.waitEvents[i:], p.waitEvents[i+1:])
+ p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
+ } else {
+ i++
+ }
+ }
}
func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index c2f736cc1..9ed7801d2 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -84,7 +84,7 @@ func (o *bufOp) Init(fd *netFD, buf []byte) {
}
}
-// resultSrv will retreive all io completion results from
+// resultSrv will retrieve all io completion results from
// iocp and send them to the correspondent waiting client
// goroutine via channel supplied in the request.
type resultSrv struct {
@@ -513,7 +513,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
return nfd, nil
}
-// Not implemeted functions.
+// Unimplemented functions.
func (fd *netFD) dup() (f *os.File, err os.Error) {
// TODO: Implement this
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index a3000af8a..b0e2c4205 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -113,7 +113,7 @@ func (ip IP) IsInterfaceLocalMulticast() bool {
return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01
}
-// IsLinkLinkLocalMulticast returns true if ip is a link-local
+// IsLinkLocalMulticast returns true if ip is a link-local
// multicast address.
func (ip IP) IsLinkLocalMulticast() bool {
if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 {
@@ -122,7 +122,7 @@ func (ip IP) IsLinkLocalMulticast() bool {
return ip[0] == 0xff && ip[1]&0x0f == 0x02
}
-// IsLinkLinkLocalUnicast returns true if ip is a link-local
+// IsLinkLocalUnicast returns true if ip is a link-local
// unicast address.
func (ip IP) IsLinkLocalUnicast() bool {
if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 {
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index b83284d36..0b8c388f1 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -62,7 +62,7 @@ var supportsIPv6, supportsIPv4map = probeIPv6Stack()
// favoriteAddrFamily returns the appropriate address family to
// the given net, raddr, laddr and mode. At first it figures
// address family out from the net. If mode indicates "listen"
-// and laddr.(type).IP is nil, it assuumes that the user wants to
+// and laddr.(type).IP is nil, it assumes that the user wants to
// make a passive connection with wildcard address family, both
// INET and INET6, and wildcard address. Otherwise guess: if the
// addresses are IPv4 then returns INET, or else returns INET6.
@@ -145,7 +145,7 @@ func ipv6only(x IP) IP {
return nil
}
-// TODO(rsc): if syscall.OS == "linux", we're supposd to read
+// 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 }
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
new file mode 100644
index 000000000..6a5a06c8c
--- /dev/null
+++ b/src/pkg/net/sendfile_linux.go
@@ -0,0 +1,84 @@
+// 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 (
+ "io"
+ "os"
+ "syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) {
+ var remain int64 = 1 << 62 // by default, copy until EOF
+
+ lr, ok := r.(*io.LimitedReader)
+ if ok {
+ remain, r = lr.N, lr.R
+ if remain <= 0 {
+ return 0, nil, true
+ }
+ }
+ f, ok := r.(*os.File)
+ if !ok {
+ return 0, nil, false
+ }
+
+ c.wio.Lock()
+ defer c.wio.Unlock()
+ c.incref()
+ defer c.decref()
+ if c.wdeadline_delta > 0 {
+ // This is a little odd that we're setting the timeout
+ // for the entire file but Write has the same issue
+ // (if one slurps the whole file into memory and
+ // do one large Write). At least they're consistent.
+ c.wdeadline = pollserver.Now() + c.wdeadline_delta
+ } else {
+ c.wdeadline = 0
+ }
+
+ dst := c.sysfd
+ src := f.Fd()
+ for remain > 0 {
+ n := maxSendfileSize
+ if int64(n) > remain {
+ n = int(remain)
+ }
+ n, errno := syscall.Sendfile(dst, src, nil, n)
+ if n > 0 {
+ written += int64(n)
+ remain -= int64(n)
+ }
+ if n == 0 && errno == 0 {
+ break
+ }
+ if errno == syscall.EAGAIN && c.wdeadline >= 0 {
+ pollserver.WaitWrite(c)
+ continue
+ }
+ if errno != 0 {
+ // This includes syscall.ENOSYS (no kernel
+ // support) and syscall.EINVAL (fd types which
+ // don't implement sendfile together)
+ err = &OpError{"sendfile", c.net, c.raddr, os.Errno(errno)}
+ break
+ }
+ }
+ if lr != nil {
+ lr.N = remain
+ }
+ return written, err, written > 0
+}
diff --git a/src/pkg/net/sendfile_stub.go b/src/pkg/net/sendfile_stub.go
new file mode 100644
index 000000000..43e8104e9
--- /dev/null
+++ b/src/pkg/net/sendfile_stub.go
@@ -0,0 +1,14 @@
+// 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 (
+ "io"
+ "os"
+)
+
+func sendFile(c *netFD, r io.Reader) (n int64, err os.Error, handled bool) {
+ return 0, nil, false
+}
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 107de3e1c..36780d789 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -92,10 +92,13 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
}
func doTest(t *testing.T, network, listenaddr, dialaddr string) {
- if listenaddr == "" {
- t.Logf("Test %s %s %s\n", network, "<nil>", dialaddr)
- } else {
- t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
+ t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr)
+ switch listenaddr {
+ case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
+ if testing.Short() || avoidMacFirewall {
+ t.Logf("skip wildcard listen during short test")
+ return
+ }
}
listening := make(chan string)
done := make(chan int)
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
index 5c47e4f77..eae7f3711 100644
--- a/src/pkg/net/sock.go
+++ b/src/pkg/net/sock.go
@@ -7,6 +7,7 @@
package net
import (
+ "io"
"os"
"reflect"
"syscall"
@@ -153,3 +154,14 @@ type UnknownSocketError struct {
func (e *UnknownSocketError) String() string {
return "unknown socket address type " + reflect.TypeOf(e.sa).String()
}
+
+type writerOnly struct {
+ io.Writer
+}
+
+// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
+// applicable.
+func genericReadFrom(w io.Writer, r io.Reader) (n int64, err os.Error) {
+ // Use wrapper to hide existing r.ReadFrom from io.Copy.
+ return io.Copy(writerOnly{w}, r)
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index 8aeed4895..9ee6c14f7 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -7,6 +7,7 @@
package net
import (
+ "io"
"os"
"syscall"
)
@@ -95,6 +96,14 @@ func (c *TCPConn) Read(b []byte) (n int, err os.Error) {
return c.fd.Read(b)
}
+// ReadFrom implements the io.ReaderFrom ReadFrom method.
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) {
+ if n, err, handled := sendFile(c.fd, r); handled {
+ return n, err
+ }
+ return genericReadFrom(c, r)
+}
+
// Write implements the net.Conn Write method.
func (c *TCPConn) Write(b []byte) (n int, err os.Error) {
if !c.ok() {
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index ac1278689..e65374903 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -237,7 +237,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.
// to a method on r.
//
// Dot encoding is a common framing used for data blocks
-// in text protcols like SMTP. The data consists of a sequence
+// in text protocols such as SMTP. The data consists of a sequence
// of lines, each of which ends in "\r\n". The sequence itself
// ends at a line containing just a dot: ".\r\n". Lines beginning
// with a dot are escaped with an additional dot to avoid
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 409355667..5469acffa 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -293,10 +293,10 @@ func (c *UDPConn) JoinGroup(addr IP) os.Error {
if ip == nil {
return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast}
}
- mreq := &syscall.IpMreq{
+ mreq := &syscall.IPMreq{
Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
}
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+ err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
if err != nil {
return &OpError{"joingroup", "udp", &IPAddr{ip}, err}
}
@@ -312,10 +312,10 @@ func (c *UDPConn) LeaveGroup(addr IP) os.Error {
if ip == nil {
return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast}
}
- mreq := &syscall.IpMreq{
+ mreq := &syscall.IPMreq{
Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
}
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
+ err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
if err != nil {
return &OpError{"leavegroup", "udp", &IPAddr{ip}, err}
}