aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net')
-rw-r--r--libgo/go/net/cgo_unix.go2
-rw-r--r--libgo/go/net/fd.go204
-rw-r--r--libgo/go/net/fd_linux.go16
-rw-r--r--libgo/go/net/fd_openbsd.go11
-rw-r--r--libgo/go/net/fd_windows.go76
-rw-r--r--libgo/go/net/file.go4
-rw-r--r--libgo/go/net/hosts.go6
-rw-r--r--libgo/go/net/http/cgi/host_test.go15
-rw-r--r--libgo/go/net/http/chunked.go125
-rw-r--r--libgo/go/net/http/chunked_test.go39
-rw-r--r--libgo/go/net/http/client_test.go27
-rw-r--r--libgo/go/net/http/fcgi/child.go143
-rw-r--r--libgo/go/net/http/fcgi/fcgi.go41
-rw-r--r--libgo/go/net/http/fcgi/fcgi_test.go47
-rw-r--r--libgo/go/net/http/fs.go8
-rw-r--r--libgo/go/net/http/fs_test.go28
-rw-r--r--libgo/go/net/http/httputil/chunked.go140
-rw-r--r--libgo/go/net/http/httputil/chunked_test.go8
-rw-r--r--libgo/go/net/http/httputil/persist.go10
-rw-r--r--libgo/go/net/http/readrequest_test.go6
-rw-r--r--libgo/go/net/http/request.go90
-rw-r--r--libgo/go/net/http/response_test.go4
-rw-r--r--libgo/go/net/http/serve_test.go27
-rw-r--r--libgo/go/net/http/server.go10
-rw-r--r--libgo/go/net/http/sniff_test.go33
-rw-r--r--libgo/go/net/http/transfer.go4
-rw-r--r--libgo/go/net/http/transport.go2
-rw-r--r--libgo/go/net/http/transport_windows.go6
-rw-r--r--libgo/go/net/interface_bsd.go16
-rw-r--r--libgo/go/net/interface_darwin.go8
-rw-r--r--libgo/go/net/interface_freebsd.go8
-rw-r--r--libgo/go/net/interface_linux.go32
-rw-r--r--libgo/go/net/interface_windows.go4
-rw-r--r--libgo/go/net/ipsock.go4
-rw-r--r--libgo/go/net/ipsock_posix.go8
-rw-r--r--libgo/go/net/lookup_windows.go16
-rw-r--r--libgo/go/net/newpollserver.go7
-rw-r--r--libgo/go/net/pipe.go4
-rw-r--r--libgo/go/net/sendfile_linux.go6
-rw-r--r--libgo/go/net/sendfile_windows.go2
-rw-r--r--libgo/go/net/sock.go8
-rw-r--r--libgo/go/net/tcpsock_posix.go4
-rw-r--r--libgo/go/net/unixsock_posix.go4
43 files changed, 796 insertions, 467 deletions
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index 680d3e7..1a0f406 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -109,7 +109,7 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, complet
if gerrno == syscall.EAI_NONAME {
str = noSuchHost
} else if gerrno == syscall.EAI_SYSTEM {
- str = syscall.Errstr(syscall.GetErrno())
+ str = syscall.GetErrno().Error()
} else {
str = bytePtrToString(libc_gai_strerror(gerrno))
}
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index 025075d..70e04a2 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -278,8 +278,8 @@ func startServer() {
func newFD(fd, family, proto int, net string) (f *netFD, err error) {
onceStartServer.Do(startServer)
- if e := syscall.SetNonblock(fd, true); e != 0 {
- return nil, os.Errno(e)
+ if e := syscall.SetNonblock(fd, true); e != nil {
+ return nil, e
}
f = &netFD{
sysfd: fd,
@@ -306,19 +306,19 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
}
func (fd *netFD) connect(ra syscall.Sockaddr) (err error) {
- e := syscall.Connect(fd.sysfd, ra)
- if e == syscall.EINPROGRESS {
- var errno int
+ err = syscall.Connect(fd.sysfd, ra)
+ if err == syscall.EINPROGRESS {
pollserver.WaitWrite(fd)
- e, errno = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
- if errno != 0 {
- return os.NewSyscallError("getsockopt", errno)
+ var e int
+ e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+ if err != nil {
+ return os.NewSyscallError("getsockopt", err)
+ }
+ if e != 0 {
+ err = syscall.Errno(e)
}
}
- if e != 0 {
- return os.Errno(e)
- }
- return nil
+ return err
}
// Add a reference to this fd.
@@ -362,9 +362,9 @@ func (fd *netFD) shutdown(how int) error {
if fd == nil || fd.sysfile == nil {
return os.EINVAL
}
- errno := syscall.Shutdown(fd.sysfd, how)
- if errno != 0 {
- return &OpError{"shutdown", fd.net, fd.laddr, os.Errno(errno)}
+ err := syscall.Shutdown(fd.sysfd, how)
+ if err != nil {
+ return &OpError{"shutdown", fd.net, fd.laddr, err}
}
return nil
}
@@ -377,6 +377,14 @@ func (fd *netFD) CloseWrite() error {
return fd.shutdown(syscall.SHUT_WR)
}
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool { return true }
+func (e *timeoutError) Temporary() bool { return true }
+
+var errTimeout error = &timeoutError{}
+
func (fd *netFD) Read(p []byte) (n int, err error) {
if fd == nil {
return 0, os.EINVAL
@@ -393,24 +401,24 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
} else {
fd.rdeadline = 0
}
- var oserr error
for {
- var errno int
- n, errno = syscall.Read(fd.sysfile.Fd(), p)
- if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ n, err = syscall.Read(fd.sysfile.Fd(), p)
+ if err == syscall.EAGAIN {
+ if fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd)
+ continue
+ }
+ err = errTimeout
}
- if errno != 0 {
+ if err != nil {
n = 0
- oserr = os.Errno(errno)
- } else if n == 0 && errno == 0 && fd.proto != syscall.SOCK_DGRAM {
+ } else if n == 0 && err == nil && fd.proto != syscall.SOCK_DGRAM {
err = io.EOF
}
break
}
- if oserr != nil {
- err = &OpError{"read", fd.net, fd.raddr, oserr}
+ if err != nil && err != io.EOF {
+ err = &OpError{"read", fd.net, fd.raddr, err}
}
return
}
@@ -428,22 +436,22 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
} else {
fd.rdeadline = 0
}
- var oserr error
for {
- var errno int
- n, sa, errno = syscall.Recvfrom(fd.sysfd, p, 0)
- if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
+ if err == syscall.EAGAIN {
+ if fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd)
+ continue
+ }
+ err = errTimeout
}
- if errno != 0 {
+ if err != nil {
n = 0
- oserr = os.Errno(errno)
}
break
}
- if oserr != nil {
- err = &OpError{"read", fd.net, fd.laddr, oserr}
+ if err != nil {
+ err = &OpError{"read", fd.net, fd.laddr, err}
}
return
}
@@ -461,24 +469,22 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
} else {
fd.rdeadline = 0
}
- var oserr error
for {
- var errno int
- n, oobn, flags, sa, errno = syscall.Recvmsg(fd.sysfd, p, oob, 0)
- if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
- }
- if errno != 0 {
- oserr = os.Errno(errno)
+ n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
+ if err == syscall.EAGAIN {
+ if fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd)
+ continue
+ }
+ err = errTimeout
}
- if n == 0 {
- oserr = io.EOF
+ if err == nil && n == 0 {
+ err = io.EOF
}
break
}
- if oserr != nil {
- err = &OpError{"read", fd.net, fd.laddr, oserr}
+ if err != nil && err != io.EOF {
+ err = &OpError{"read", fd.net, fd.laddr, err}
return
}
return
@@ -501,32 +507,34 @@ func (fd *netFD) Write(p []byte) (n int, err error) {
fd.wdeadline = 0
}
nn := 0
- var oserr error
for {
- n, errno := syscall.Write(fd.sysfile.Fd(), p[nn:])
+ var n int
+ n, err = syscall.Write(fd.sysfile.Fd(), p[nn:])
if n > 0 {
nn += n
}
if nn == len(p) {
break
}
- if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
+ if err == syscall.EAGAIN {
+ if fd.wdeadline >= 0 {
+ pollserver.WaitWrite(fd)
+ continue
+ }
+ err = errTimeout
}
- if errno != 0 {
+ if err != nil {
n = 0
- oserr = os.Errno(errno)
break
}
if n == 0 {
- oserr = io.ErrUnexpectedEOF
+ err = io.ErrUnexpectedEOF
break
}
}
- if oserr != nil {
- err = &OpError{"write", fd.net, fd.raddr, oserr}
+ if err != nil {
+ err = &OpError{"write", fd.net, fd.raddr, err}
}
return nn, err
}
@@ -544,22 +552,21 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
} else {
fd.wdeadline = 0
}
- var oserr error
for {
- errno := syscall.Sendto(fd.sysfd, p, 0, sa)
- if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
- }
- if errno != 0 {
- oserr = os.Errno(errno)
+ err = syscall.Sendto(fd.sysfd, p, 0, sa)
+ if err == syscall.EAGAIN {
+ if fd.wdeadline >= 0 {
+ pollserver.WaitWrite(fd)
+ continue
+ }
+ err = errTimeout
}
break
}
- if oserr == nil {
+ if err == nil {
n = len(p)
} else {
- err = &OpError{"write", fd.net, fd.raddr, oserr}
+ err = &OpError{"write", fd.net, fd.raddr, err}
}
return
}
@@ -577,24 +584,22 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
} else {
fd.wdeadline = 0
}
- var oserr error
for {
- var errno int
- errno = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
- if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
- }
- if errno != 0 {
- oserr = os.Errno(errno)
+ err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
+ if err == syscall.EAGAIN {
+ if fd.wdeadline >= 0 {
+ pollserver.WaitWrite(fd)
+ continue
+ }
+ err = errTimeout
}
break
}
- if oserr == nil {
+ if err == nil {
n = len(p)
oobn = len(oob)
} else {
- err = &OpError{"write", fd.net, fd.raddr, oserr}
+ err = &OpError{"write", fd.net, fd.raddr, err}
}
return
}
@@ -615,25 +620,26 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
// See ../syscall/exec.go for description of ForkLock.
// It is okay to hold the lock across syscall.Accept
// because we have put fd.sysfd into non-blocking mode.
- syscall.ForkLock.RLock()
- var s, e int
+ var s int
var rsa syscall.Sockaddr
for {
if fd.closing {
- syscall.ForkLock.RUnlock()
return nil, os.EINVAL
}
- s, rsa, e = syscall.Accept(fd.sysfd)
- if e != syscall.EAGAIN || fd.rdeadline < 0 {
- break
- }
- syscall.ForkLock.RUnlock()
- pollserver.WaitRead(fd)
syscall.ForkLock.RLock()
- }
- if e != 0 {
- syscall.ForkLock.RUnlock()
- return nil, &OpError{"accept", fd.net, fd.laddr, os.Errno(e)}
+ s, rsa, err = syscall.Accept(fd.sysfd)
+ if err != nil {
+ syscall.ForkLock.RUnlock()
+ if err == syscall.EAGAIN {
+ if fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd)
+ continue
+ }
+ err = errTimeout
+ }
+ return nil, &OpError{"accept", fd.net, fd.laddr, err}
+ }
+ break
}
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
@@ -648,19 +654,19 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
}
func (fd *netFD) dup() (f *os.File, err error) {
- ns, e := syscall.Dup(fd.sysfd)
- if e != 0 {
- return nil, &OpError{"dup", fd.net, fd.laddr, os.Errno(e)}
+ ns, err := syscall.Dup(fd.sysfd)
+ if err != nil {
+ return nil, &OpError{"dup", fd.net, fd.laddr, err}
}
// We want blocking mode for the new fd, hence the double negative.
- if e = syscall.SetNonblock(ns, false); e != 0 {
- return nil, &OpError{"setnonblock", fd.net, fd.laddr, os.Errno(e)}
+ if err = syscall.SetNonblock(ns, false); err != nil {
+ return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
}
return os.NewFile(ns, fd.sysfile.Name()), nil
}
-func closesocket(s int) (errno int) {
+func closesocket(s int) error {
return syscall.Close(s)
}
diff --git a/libgo/go/net/fd_linux.go b/libgo/go/net/fd_linux.go
index cce74cd..8e07833 100644
--- a/libgo/go/net/fd_linux.go
+++ b/libgo/go/net/fd_linux.go
@@ -35,12 +35,12 @@ type pollster struct {
func newpollster() (p *pollster, err error) {
p = new(pollster)
- var e int
+ var e error
// The arg to epoll_create is a hint to the kernel
// about the number of FDs we will care about.
// We don't know, and since 2.6.8 the kernel ignores it anyhow.
- if p.epfd, e = syscall.EpollCreate(16); e != 0 {
+ if p.epfd, e = syscall.EpollCreate(16); e != nil {
return nil, os.NewSyscallError("epoll_create", e)
}
p.events = make(map[int]uint32)
@@ -68,7 +68,7 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
} else {
op = syscall.EPOLL_CTL_ADD
}
- if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
+ if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != nil {
return false, os.NewSyscallError("epoll_ctl", e)
}
p.events[fd] = p.ctlEvent.Events
@@ -97,13 +97,13 @@ func (p *pollster) StopWaiting(fd int, bits uint) {
if int32(events)&^syscall.EPOLLONESHOT != 0 {
p.ctlEvent.Fd = int32(fd)
p.ctlEvent.Events = events
- if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != 0 {
- print("Epoll modify fd=", fd, ": ", os.Errno(e).Error(), "\n")
+ if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != nil {
+ print("Epoll modify fd=", fd, ": ", e.Error(), "\n")
}
p.events[fd] = events
} else {
- if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
- print("Epoll delete fd=", fd, ": ", os.Errno(e).Error(), "\n")
+ if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != nil {
+ print("Epoll delete fd=", fd, ": ", e.Error(), "\n")
}
delete(p.events, fd)
}
@@ -141,7 +141,7 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro
n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
s.Lock()
- if e != 0 {
+ if e != nil {
if e == syscall.EAGAIN || e == syscall.EINTR {
continue
}
diff --git a/libgo/go/net/fd_openbsd.go b/libgo/go/net/fd_openbsd.go
index f61008a..e52ac35 100644
--- a/libgo/go/net/fd_openbsd.go
+++ b/libgo/go/net/fd_openbsd.go
@@ -23,9 +23,8 @@ type pollster struct {
func newpollster() (p *pollster, err error) {
p = new(pollster)
- var e int
- if p.kq, e = syscall.Kqueue(); e != 0 {
- return nil, os.NewSyscallError("kqueue", e)
+ if p.kq, err = syscall.Kqueue(); err != nil {
+ return nil, os.NewSyscallError("kqueue", err)
}
p.events = p.eventbuf[0:0]
return p, nil
@@ -50,14 +49,14 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
syscall.SetKevent(ev, fd, kmode, flags)
n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
- if e != 0 {
+ if e != nil {
return false, os.NewSyscallError("kevent", e)
}
if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
return false, os.NewSyscallError("kqueue phase error", e)
}
if ev.Data != 0 {
- return false, os.Errno(int(ev.Data))
+ return false, syscall.Errno(int(ev.Data))
}
return false, nil
}
@@ -91,7 +90,7 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro
nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
s.Lock()
- if e != 0 {
+ if e != nil {
if e == syscall.EINTR {
continue
}
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index ce228e9..7a16023 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -26,11 +26,11 @@ func init() {
var d syscall.WSAData
e := syscall.WSAStartup(uint32(0x202), &d)
if e != 0 {
- initErr = os.NewSyscallError("WSAStartup", e)
+ initErr = os.NewSyscallError("WSAStartup", syscall.Errno(e))
}
}
-func closesocket(s syscall.Handle) (errno int) {
+func closesocket(s syscall.Handle) (err error) {
return syscall.Closesocket(s)
}
@@ -38,13 +38,13 @@ func closesocket(s syscall.Handle) (errno int) {
type anOpIface interface {
Op() *anOp
Name() string
- Submit() (errno int)
+ Submit() (err error)
}
// IO completion result parameters.
type ioResult struct {
qty uint32
- err int
+ err error
}
// anOp implements functionality common to all io operations.
@@ -54,7 +54,7 @@ type anOp struct {
o syscall.Overlapped
resultc chan ioResult
- errnoc chan int
+ errnoc chan error
fd *netFD
}
@@ -71,7 +71,7 @@ func (o *anOp) Init(fd *netFD, mode int) {
}
o.resultc = fd.resultc[i]
if fd.errnoc[i] == nil {
- fd.errnoc[i] = make(chan int)
+ fd.errnoc[i] = make(chan error)
}
o.errnoc = fd.errnoc[i]
}
@@ -111,14 +111,14 @@ func (s *resultSrv) Run() {
for {
r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
switch {
- case r.err == 0:
+ case r.err == nil:
// Dequeued successfully completed io packet.
- case r.err == syscall.WAIT_TIMEOUT && o == nil:
+ case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
// Wait has timed out (should not happen now, but might be used in the future).
panic("GetQueuedCompletionStatus timed out")
case o == nil:
// Failed to dequeue anything -> report the error.
- panic("GetQueuedCompletionStatus failed " + syscall.Errstr(r.err))
+ panic("GetQueuedCompletionStatus failed " + r.err.Error())
default:
// Dequeued failed io packet.
}
@@ -153,7 +153,7 @@ func (s *ioSrv) ProcessRemoteIO() {
// inline, or, if timeouts are employed, passes the request onto
// a special goroutine and waits for completion or cancels request.
func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
- var e int
+ var e error
o := oi.Op()
if deadline_delta > 0 {
// Send request to a special dedicated thread,
@@ -164,12 +164,12 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
e = oi.Submit()
}
switch e {
- case 0:
+ case nil:
// IO completed immediately, but we need to get our completion message anyway.
case syscall.ERROR_IO_PENDING:
// IO started, and we have to wait for its completion.
default:
- return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, os.Errno(e)}
+ return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, e}
}
// Wait for our request to complete.
var r ioResult
@@ -187,8 +187,8 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
} else {
r = <-o.resultc
}
- if r.err != 0 {
- err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, os.Errno(r.err)}
+ if r.err != nil {
+ err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
}
return int(r.qty), err
}
@@ -200,10 +200,10 @@ var onceStartServer sync.Once
func startServer() {
resultsrv = new(resultSrv)
- var errno int
- resultsrv.iocp, errno = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
- if errno != 0 {
- panic("CreateIoCompletionPort failed " + syscall.Errstr(errno))
+ var err error
+ resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
+ if err != nil {
+ panic("CreateIoCompletionPort: " + err.Error())
}
go resultsrv.Run()
@@ -228,7 +228,7 @@ type netFD struct {
laddr Addr
raddr Addr
resultc [2]chan ioResult // read/write completion results
- errnoc [2]chan int // read/write submit or cancel operation errors
+ errnoc [2]chan error // read/write submit or cancel operation errors
// owned by client
rdeadline_delta int64
@@ -256,8 +256,8 @@ func newFD(fd syscall.Handle, family, proto int, net string) (f *netFD, err erro
}
onceStartServer.Do(startServer)
// Associate our socket with resultsrv.iocp.
- if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != 0 {
- return nil, os.Errno(e)
+ if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != nil {
+ return nil, e
}
return allocFD(fd, family, proto, net), nil
}
@@ -268,11 +268,7 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
}
func (fd *netFD) connect(ra syscall.Sockaddr) (err error) {
- e := syscall.Connect(fd.sysfd, ra)
- if e != 0 {
- return os.Errno(e)
- }
- return nil
+ return syscall.Connect(fd.sysfd, ra)
}
// Add a reference to this fd.
@@ -317,9 +313,9 @@ func (fd *netFD) shutdown(how int) error {
if fd == nil || fd.sysfd == syscall.InvalidHandle {
return os.EINVAL
}
- errno := syscall.Shutdown(fd.sysfd, how)
- if errno != 0 {
- return &OpError{"shutdown", fd.net, fd.laddr, os.Errno(errno)}
+ err := syscall.Shutdown(fd.sysfd, how)
+ if err != nil {
+ return &OpError{"shutdown", fd.net, fd.laddr, err}
}
return nil
}
@@ -338,7 +334,7 @@ type readOp struct {
bufOp
}
-func (o *readOp) Submit() (errno int) {
+func (o *readOp) Submit() (err error) {
var d, f uint32
return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
}
@@ -375,7 +371,7 @@ type readFromOp struct {
rsan int32
}
-func (o *readFromOp) Submit() (errno int) {
+func (o *readFromOp) Submit() (err error) {
var d, f uint32
return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil)
}
@@ -415,7 +411,7 @@ type writeOp struct {
bufOp
}
-func (o *writeOp) Submit() (errno int) {
+func (o *writeOp) Submit() (err error) {
var d uint32
return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
}
@@ -447,7 +443,7 @@ type writeToOp struct {
sa syscall.Sockaddr
}
-func (o *writeToOp) Submit() (errno int) {
+func (o *writeToOp) Submit() (err error) {
var d uint32
return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
}
@@ -484,7 +480,7 @@ type acceptOp struct {
attrs [2]syscall.RawSockaddrAny // space for local and remote address only
}
-func (o *acceptOp) Submit() (errno int) {
+func (o *acceptOp) Submit() (err error) {
var d uint32
l := uint32(unsafe.Sizeof(o.attrs[0]))
return syscall.AcceptEx(o.fd.sysfd, o.newsock,
@@ -506,17 +502,17 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
// See ../syscall/exec.go for description of ForkLock.
syscall.ForkLock.RLock()
s, e := syscall.Socket(fd.family, fd.proto, 0)
- if e != 0 {
+ if e != nil {
syscall.ForkLock.RUnlock()
- return nil, os.Errno(e)
+ return nil, e
}
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
// Associate our new socket with IOCP.
onceStartServer.Do(startServer)
- if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 {
- return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)}
+ if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != nil {
+ return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, e}
}
// Submit accept request.
@@ -531,9 +527,9 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
// Inherit properties of the listening socket.
e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
- if e != 0 {
+ if e != nil {
closesocket(s)
- return nil, err
+ return nil, e
}
// Get local and peer addr out of AcceptEx buffer.
diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go
index 0ad869d..bf8cd9d 100644
--- a/libgo/go/net/file.go
+++ b/libgo/go/net/file.go
@@ -13,12 +13,12 @@ import (
func newFileFD(f *os.File) (nfd *netFD, err error) {
fd, errno := syscall.Dup(f.Fd())
- if errno != 0 {
+ if errno != nil {
return nil, os.NewSyscallError("dup", errno)
}
proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
- if errno != 0 {
+ if errno != nil {
return nil, os.NewSyscallError("getsockopt", errno)
}
diff --git a/libgo/go/net/hosts.go b/libgo/go/net/hosts.go
index d75e9e0..ddfb074 100644
--- a/libgo/go/net/hosts.go
+++ b/libgo/go/net/hosts.go
@@ -7,8 +7,8 @@
package net
import (
- "os"
"sync"
+ "time"
)
const cacheMaxAge = int64(300) // 5 minutes.
@@ -26,7 +26,7 @@ var hosts struct {
}
func readHosts() {
- now, _, _ := os.Time()
+ now := time.Seconds()
hp := hostsPath
if len(hosts.byName) == 0 || hosts.time+cacheMaxAge <= now || hosts.path != hp {
hs := make(map[string][]string)
@@ -51,7 +51,7 @@ func readHosts() {
}
}
// Update the data cache.
- hosts.time, _, _ = os.Time()
+ hosts.time = time.Seconds()
hosts.path = hp
hosts.byName = hs
hosts.byAddr = is
diff --git a/libgo/go/net/http/cgi/host_test.go b/libgo/go/net/http/cgi/host_test.go
index 2bc913a..e6e85e8 100644
--- a/libgo/go/net/http/cgi/host_test.go
+++ b/libgo/go/net/http/cgi/host_test.go
@@ -363,14 +363,13 @@ func TestCopyError(t *testing.T) {
}
conn.Close()
- if tries := 0; childRunning() {
- for tries < 15 && childRunning() {
- time.Sleep(50e6 * int64(tries))
- tries++
- }
- if childRunning() {
- t.Fatalf("post-conn.Close, expected child to be gone")
- }
+ tries := 0
+ for tries < 15 && childRunning() {
+ time.Sleep(50e6 * int64(tries))
+ tries++
+ }
+ if childRunning() {
+ t.Fatalf("post-conn.Close, expected child to be gone")
}
}
diff --git a/libgo/go/net/http/chunked.go b/libgo/go/net/http/chunked.go
index b012dd1..74c41aa 100644
--- a/libgo/go/net/http/chunked.go
+++ b/libgo/go/net/http/chunked.go
@@ -2,20 +2,137 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is duplicated in httputil/chunked.go.
+// Please make any changes in both files.
+
package http
import (
"bufio"
+ "bytes"
+ "errors"
"io"
"strconv"
)
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// newChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it.
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// newChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func newChunkedReader(r io.Reader) io.Reader {
+ br, ok := r.(*bufio.Reader)
+ if !ok {
+ br = bufio.NewReader(r)
+ }
+ return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+ r *bufio.Reader
+ n uint64 // unread bytes in chunk
+ err error
+}
+
+func (cr *chunkedReader) beginChunk() {
+ // chunk-size CRLF
+ var line string
+ line, cr.err = readLine(cr.r)
+ if cr.err != nil {
+ return
+ }
+ cr.n, cr.err = strconv.Btoui64(line, 16)
+ if cr.err != nil {
+ return
+ }
+ if cr.n == 0 {
+ cr.err = io.EOF
+ }
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+ if cr.err != nil {
+ return 0, cr.err
+ }
+ if cr.n == 0 {
+ cr.beginChunk()
+ if cr.err != nil {
+ return 0, cr.err
+ }
+ }
+ if uint64(len(b)) > cr.n {
+ b = b[0:cr.n]
+ }
+ n, cr.err = cr.r.Read(b)
+ cr.n -= uint64(n)
+ if cr.n == 0 && cr.err == nil {
+ // end of chunk (CRLF)
+ b := make([]byte, 2)
+ if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
+ if b[0] != '\r' || b[1] != '\n' {
+ cr.err = errors.New("malformed chunked encoding")
+ }
+ }
+ }
+ return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLineBytes(b *bufio.Reader) (p []byte, err error) {
+ if p, err = b.ReadSlice('\n'); err != nil {
+ // We always know when EOF is coming.
+ // If the caller asked for a line, there should be a line.
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ } else if err == bufio.ErrBufferFull {
+ err = ErrLineTooLong
+ }
+ return nil, err
+ }
+ if len(p) >= maxLineLength {
+ return nil, ErrLineTooLong
+ }
+
+ // Chop off trailing white space.
+ p = bytes.TrimRight(p, " \r\t\n")
+
+ return p, nil
+}
+
+// readLineBytes, but convert the bytes into a string.
+func readLine(b *bufio.Reader) (s string, err error) {
+ p, e := readLineBytes(b)
+ if e != nil {
+ return "", e
+ }
+ return string(p), nil
+}
+
+// newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// newChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using newChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
func newChunkedWriter(w io.Writer) io.WriteCloser {
return &chunkedWriter{w}
}
-// Writing to ChunkedWriter translates to writing in HTTP chunked Transfer
-// Encoding wire format to the underlying Wire writer.
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
type chunkedWriter struct {
Wire io.Writer
}
@@ -51,7 +168,3 @@ func (cw *chunkedWriter) Close() error {
_, err := io.WriteString(cw.Wire, "0\r\n")
return err
}
-
-func newChunkedReader(r *bufio.Reader) io.Reader {
- return &chunkedReader{r: r}
-}
diff --git a/libgo/go/net/http/chunked_test.go b/libgo/go/net/http/chunked_test.go
new file mode 100644
index 0000000..b77ee2f
--- /dev/null
+++ b/libgo/go/net/http/chunked_test.go
@@ -0,0 +1,39 @@
+// 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.
+
+// This code is duplicated in httputil/chunked_test.go.
+// Please make any changes in both files.
+
+package http
+
+import (
+ "bytes"
+ "io/ioutil"
+ "testing"
+)
+
+func TestChunk(t *testing.T) {
+ var b bytes.Buffer
+
+ w := newChunkedWriter(&b)
+ const chunk1 = "hello, "
+ const chunk2 = "world! 0123456789abcdef"
+ w.Write([]byte(chunk1))
+ w.Write([]byte(chunk2))
+ w.Close()
+
+ if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
+ t.Fatalf("chunk writer wrote %q; want %q", g, e)
+ }
+
+ r := newChunkedReader(&b)
+ data, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Logf(`data: "%s"`, data)
+ t.Fatalf("ReadAll from reader: %v", err)
+ }
+ if g, e := string(data), chunk1+chunk2; g != e {
+ t.Errorf("chunk reader read %q; want %q", g, e)
+ }
+}
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index d224380..57a9dd9 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -26,6 +26,31 @@ var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "User-agent: go\nDisallow: /something/")
})
+// pedanticReadAll works like ioutil.ReadAll but additionally
+// verifies that r obeys the documented io.Reader contract.
+func pedanticReadAll(r io.Reader) (b []byte, err error) {
+ var bufa [64]byte
+ buf := bufa[:]
+ for {
+ n, err := r.Read(buf)
+ if n == 0 && err == nil {
+ return nil, fmt.Errorf("Read: n=0 with err=nil")
+ }
+ b = append(b, buf[:n]...)
+ if err == io.EOF {
+ n, err := r.Read(buf)
+ if n != 0 || err != io.EOF {
+ return nil, fmt.Errorf("Read: n=%d err=%#v after EOF", n, err)
+ }
+ return b, nil
+ }
+ if err != nil {
+ return b, err
+ }
+ }
+ panic("unreachable")
+}
+
func TestClient(t *testing.T) {
ts := httptest.NewServer(robotsTxtHandler)
defer ts.Close()
@@ -33,7 +58,7 @@ func TestClient(t *testing.T) {
r, err := Get(ts.URL)
var b []byte
if err == nil {
- b, err = ioutil.ReadAll(r.Body)
+ b, err = pedanticReadAll(r.Body)
r.Body.Close()
}
if err != nil {
diff --git a/libgo/go/net/http/fcgi/child.go b/libgo/go/net/http/fcgi/child.go
index 7b56395..529440c 100644
--- a/libgo/go/net/http/fcgi/child.go
+++ b/libgo/go/net/http/fcgi/child.go
@@ -7,6 +7,7 @@ package fcgi
// This file implements FastCGI from the perspective of a child process.
import (
+ "errors"
"fmt"
"io"
"net"
@@ -123,89 +124,101 @@ func (r *response) Close() error {
}
type child struct {
- conn *conn
- handler http.Handler
+ conn *conn
+ handler http.Handler
+ requests map[uint16]*request // keyed by request ID
}
-func newChild(rwc net.Conn, handler http.Handler) *child {
- return &child{newConn(rwc), handler}
+func newChild(rwc io.ReadWriteCloser, handler http.Handler) *child {
+ return &child{
+ conn: newConn(rwc),
+ handler: handler,
+ requests: make(map[uint16]*request),
+ }
}
func (c *child) serve() {
- requests := map[uint16]*request{}
defer c.conn.Close()
var rec record
- var br beginRequest
for {
if err := rec.read(c.conn.rwc); err != nil {
return
}
-
- req, ok := requests[rec.h.Id]
- if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
- // The spec says to ignore unknown request IDs.
- continue
- }
- if ok && rec.h.Type == typeBeginRequest {
- // The server is trying to begin a request with the same ID
- // as an in-progress request. This is an error.
+ if err := c.handleRecord(&rec); err != nil {
return
}
+ }
+}
- switch rec.h.Type {
- case typeBeginRequest:
- if err := br.read(rec.content()); err != nil {
- return
- }
- if br.role != roleResponder {
- c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
- break
- }
- requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
- case typeParams:
- // NOTE(eds): Technically a key-value pair can straddle the boundary
- // between two packets. We buffer until we've received all parameters.
- if len(rec.content()) > 0 {
- req.rawParams = append(req.rawParams, rec.content()...)
- break
- }
- req.parseParams()
- case typeStdin:
- content := rec.content()
- if req.pw == nil {
- var body io.ReadCloser
- if len(content) > 0 {
- // body could be an io.LimitReader, but it shouldn't matter
- // as long as both sides are behaving.
- body, req.pw = io.Pipe()
- }
- go c.serveRequest(req, body)
- }
+var errCloseConn = errors.New("fcgi: connection should be closed")
+
+func (c *child) handleRecord(rec *record) error {
+ req, ok := c.requests[rec.h.Id]
+ if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
+ // The spec says to ignore unknown request IDs.
+ return nil
+ }
+ if ok && rec.h.Type == typeBeginRequest {
+ // The server is trying to begin a request with the same ID
+ // as an in-progress request. This is an error.
+ return errors.New("fcgi: received ID that is already in-flight")
+ }
+
+ switch rec.h.Type {
+ case typeBeginRequest:
+ var br beginRequest
+ if err := br.read(rec.content()); err != nil {
+ return err
+ }
+ if br.role != roleResponder {
+ c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
+ return nil
+ }
+ c.requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
+ case typeParams:
+ // NOTE(eds): Technically a key-value pair can straddle the boundary
+ // between two packets. We buffer until we've received all parameters.
+ if len(rec.content()) > 0 {
+ req.rawParams = append(req.rawParams, rec.content()...)
+ return nil
+ }
+ req.parseParams()
+ case typeStdin:
+ content := rec.content()
+ if req.pw == nil {
+ var body io.ReadCloser
if len(content) > 0 {
- // TODO(eds): This blocks until the handler reads from the pipe.
- // If the handler takes a long time, it might be a problem.
- req.pw.Write(content)
- } else if req.pw != nil {
- req.pw.Close()
- }
- case typeGetValues:
- values := map[string]string{"FCGI_MPXS_CONNS": "1"}
- c.conn.writePairs(0, typeGetValuesResult, values)
- case typeData:
- // If the filter role is implemented, read the data stream here.
- case typeAbortRequest:
- delete(requests, rec.h.Id)
- c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
- if !req.keepConn {
- // connection will close upon return
- return
+ // body could be an io.LimitReader, but it shouldn't matter
+ // as long as both sides are behaving.
+ body, req.pw = io.Pipe()
}
- default:
- b := make([]byte, 8)
- b[0] = rec.h.Type
- c.conn.writeRecord(typeUnknownType, 0, b)
+ go c.serveRequest(req, body)
+ }
+ if len(content) > 0 {
+ // TODO(eds): This blocks until the handler reads from the pipe.
+ // If the handler takes a long time, it might be a problem.
+ req.pw.Write(content)
+ } else if req.pw != nil {
+ req.pw.Close()
+ }
+ case typeGetValues:
+ values := map[string]string{"FCGI_MPXS_CONNS": "1"}
+ c.conn.writePairs(typeGetValuesResult, 0, values)
+ case typeData:
+ // If the filter role is implemented, read the data stream here.
+ case typeAbortRequest:
+ delete(c.requests, rec.h.Id)
+ c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
+ if !req.keepConn {
+ // connection will close upon return
+ return errCloseConn
}
+ default:
+ b := make([]byte, 8)
+ b[0] = byte(rec.h.Type)
+ c.conn.writeRecord(typeUnknownType, 0, b)
}
+ return nil
}
func (c *child) serveRequest(req *request, body io.ReadCloser) {
diff --git a/libgo/go/net/http/fcgi/fcgi.go b/libgo/go/net/http/fcgi/fcgi.go
index 70cf781..d35aa84 100644
--- a/libgo/go/net/http/fcgi/fcgi.go
+++ b/libgo/go/net/http/fcgi/fcgi.go
@@ -19,19 +19,22 @@ import (
"sync"
)
+// recType is a record type, as defined by
+// http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
+type recType uint8
+
const (
- // Packet Types
- typeBeginRequest = iota + 1
- typeAbortRequest
- typeEndRequest
- typeParams
- typeStdin
- typeStdout
- typeStderr
- typeData
- typeGetValues
- typeGetValuesResult
- typeUnknownType
+ typeBeginRequest recType = 1
+ typeAbortRequest recType = 2
+ typeEndRequest recType = 3
+ typeParams recType = 4
+ typeStdin recType = 5
+ typeStdout recType = 6
+ typeStderr recType = 7
+ typeData recType = 8
+ typeGetValues recType = 9
+ typeGetValuesResult recType = 10
+ typeUnknownType recType = 11
)
// keep the connection between web-server and responder open after request
@@ -59,7 +62,7 @@ const headerLen = 8
type header struct {
Version uint8
- Type uint8
+ Type recType
Id uint16
ContentLength uint16
PaddingLength uint8
@@ -85,7 +88,7 @@ func (br *beginRequest) read(content []byte) error {
// not synchronized because we don't care what the contents are
var pad [maxPad]byte
-func (h *header) init(recType uint8, reqId uint16, contentLength int) {
+func (h *header) init(recType recType, reqId uint16, contentLength int) {
h.Version = 1
h.Type = recType
h.Id = reqId
@@ -137,7 +140,7 @@ func (r *record) content() []byte {
}
// writeRecord writes and sends a single record.
-func (c *conn) writeRecord(recType uint8, reqId uint16, b []byte) error {
+func (c *conn) writeRecord(recType recType, reqId uint16, b []byte) error {
c.mutex.Lock()
defer c.mutex.Unlock()
c.buf.Reset()
@@ -167,12 +170,12 @@ func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8
return c.writeRecord(typeEndRequest, reqId, b)
}
-func (c *conn) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
+func (c *conn) writePairs(recType recType, reqId uint16, pairs map[string]string) error {
w := newWriter(c, recType, reqId)
b := make([]byte, 8)
for k, v := range pairs {
n := encodeSize(b, uint32(len(k)))
- n += encodeSize(b[n:], uint32(len(k)))
+ n += encodeSize(b[n:], uint32(len(v)))
if _, err := w.Write(b[:n]); err != nil {
return err
}
@@ -235,7 +238,7 @@ func (w *bufWriter) Close() error {
return w.closer.Close()
}
-func newWriter(c *conn, recType uint8, reqId uint16) *bufWriter {
+func newWriter(c *conn, recType recType, reqId uint16) *bufWriter {
s := &streamWriter{c: c, recType: recType, reqId: reqId}
w, _ := bufio.NewWriterSize(s, maxWrite)
return &bufWriter{s, w}
@@ -245,7 +248,7 @@ func newWriter(c *conn, recType uint8, reqId uint16) *bufWriter {
// It only writes maxWrite bytes at a time.
type streamWriter struct {
c *conn
- recType uint8
+ recType recType
reqId uint16
}
diff --git a/libgo/go/net/http/fcgi/fcgi_test.go b/libgo/go/net/http/fcgi/fcgi_test.go
index e42f8ef..6c7e1a9 100644
--- a/libgo/go/net/http/fcgi/fcgi_test.go
+++ b/libgo/go/net/http/fcgi/fcgi_test.go
@@ -6,6 +6,7 @@ package fcgi
import (
"bytes"
+ "errors"
"io"
"testing"
)
@@ -40,25 +41,25 @@ func TestSize(t *testing.T) {
var streamTests = []struct {
desc string
- recType uint8
+ recType recType
reqId uint16
content []byte
raw []byte
}{
{"single record", typeStdout, 1, nil,
- []byte{1, typeStdout, 0, 1, 0, 0, 0, 0},
+ []byte{1, byte(typeStdout), 0, 1, 0, 0, 0, 0},
},
// this data will have to be split into two records
{"two records", typeStdin, 300, make([]byte, 66000),
bytes.Join([][]byte{
// header for the first record
- {1, typeStdin, 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
+ {1, byte(typeStdin), 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
make([]byte, 65536),
// header for the second
- {1, typeStdin, 0x01, 0x2C, 0x01, 0xD1, 7, 0},
+ {1, byte(typeStdin), 0x01, 0x2C, 0x01, 0xD1, 7, 0},
make([]byte, 472),
// header for the empty record
- {1, typeStdin, 0x01, 0x2C, 0, 0, 0, 0},
+ {1, byte(typeStdin), 0x01, 0x2C, 0, 0, 0, 0},
},
nil),
},
@@ -111,3 +112,39 @@ outer:
}
}
}
+
+type writeOnlyConn struct {
+ buf []byte
+}
+
+func (c *writeOnlyConn) Write(p []byte) (int, error) {
+ c.buf = append(c.buf, p...)
+ return len(p), nil
+}
+
+func (c *writeOnlyConn) Read(p []byte) (int, error) {
+ return 0, errors.New("conn is write-only")
+}
+
+func (c *writeOnlyConn) Close() error {
+ return nil
+}
+
+func TestGetValues(t *testing.T) {
+ var rec record
+ rec.h.Type = typeGetValues
+
+ wc := new(writeOnlyConn)
+ c := newChild(wc, nil)
+ err := c.handleRecord(&rec)
+ if err != nil {
+ t.Fatalf("handleRecord: %v", err)
+ }
+
+ const want = "\x01\n\x00\x00\x00\x12\x06\x00" +
+ "\x0f\x01FCGI_MPXS_CONNS1" +
+ "\x00\x00\x00\x00\x00\x00\x01\n\x00\x00\x00\x00\x00\x00"
+ if got := string(wc.buf); got != want {
+ t.Errorf(" got: %q\nwant: %q\n", got, want)
+ }
+}
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index 5f91ff5..5aadac1 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -22,13 +22,19 @@ import (
// A Dir implements http.FileSystem using the native file
// system restricted to a specific directory tree.
+//
+// An empty Dir is treated as ".".
type Dir string
func (d Dir) Open(name string) (File, error) {
if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
return nil, errors.New("http: invalid character in file path")
}
- f, err := os.Open(filepath.Join(string(d), filepath.FromSlash(path.Clean("/"+name))))
+ dir := string(d)
+ if dir == "" {
+ dir = "."
+ }
+ f, err := os.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))))
if err != nil {
return nil, err
}
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index e1a784c..6697189 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -208,6 +208,20 @@ func TestDirJoin(t *testing.T) {
test(Dir("/etc/hosts"), "../")
}
+func TestEmptyDirOpenCWD(t *testing.T) {
+ test := func(d Dir) {
+ name := "fs_test.go"
+ f, err := d.Open(name)
+ if err != nil {
+ t.Fatalf("open of %s: %v", name, err)
+ }
+ defer f.Close()
+ }
+ test(Dir(""))
+ test(Dir("."))
+ test(Dir("./"))
+}
+
func TestServeFileContentType(t *testing.T) {
const ctype = "icecream/chocolate"
override := false
@@ -247,6 +261,20 @@ func TestServeFileMimeType(t *testing.T) {
}
}
+func TestServeFileFromCWD(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ ServeFile(w, r, "fs_test.go")
+ }))
+ defer ts.Close()
+ r, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if r.StatusCode != 200 {
+ t.Fatalf("expected 200 OK, got %s", r.Status)
+ }
+}
+
func TestServeFileWithContentEncoding(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Content-Encoding", "foo")
diff --git a/libgo/go/net/http/httputil/chunked.go b/libgo/go/net/http/httputil/chunked.go
index 34e47c7..69bcc0e 100644
--- a/libgo/go/net/http/httputil/chunked.go
+++ b/libgo/go/net/http/httputil/chunked.go
@@ -2,18 +2,126 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is a duplicate of ../chunked.go with these edits:
+// s/newChunked/NewChunked/g
+// s/package http/package httputil/
+// Please make any changes in both files.
+
package httputil
import (
"bufio"
+ "bytes"
+ "errors"
"io"
- "net/http"
"strconv"
- "strings"
)
-// NewChunkedWriter returns a new writer that translates writes into HTTP
-// "chunked" format before writing them to w. Closing the returned writer
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// NewChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it.
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// NewChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func NewChunkedReader(r io.Reader) io.Reader {
+ br, ok := r.(*bufio.Reader)
+ if !ok {
+ br = bufio.NewReader(r)
+ }
+ return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+ r *bufio.Reader
+ n uint64 // unread bytes in chunk
+ err error
+}
+
+func (cr *chunkedReader) beginChunk() {
+ // chunk-size CRLF
+ var line string
+ line, cr.err = readLine(cr.r)
+ if cr.err != nil {
+ return
+ }
+ cr.n, cr.err = strconv.Btoui64(line, 16)
+ if cr.err != nil {
+ return
+ }
+ if cr.n == 0 {
+ cr.err = io.EOF
+ }
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+ if cr.err != nil {
+ return 0, cr.err
+ }
+ if cr.n == 0 {
+ cr.beginChunk()
+ if cr.err != nil {
+ return 0, cr.err
+ }
+ }
+ if uint64(len(b)) > cr.n {
+ b = b[0:cr.n]
+ }
+ n, cr.err = cr.r.Read(b)
+ cr.n -= uint64(n)
+ if cr.n == 0 && cr.err == nil {
+ // end of chunk (CRLF)
+ b := make([]byte, 2)
+ if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
+ if b[0] != '\r' || b[1] != '\n' {
+ cr.err = errors.New("malformed chunked encoding")
+ }
+ }
+ }
+ return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLineBytes(b *bufio.Reader) (p []byte, err error) {
+ if p, err = b.ReadSlice('\n'); err != nil {
+ // We always know when EOF is coming.
+ // If the caller asked for a line, there should be a line.
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ } else if err == bufio.ErrBufferFull {
+ err = ErrLineTooLong
+ }
+ return nil, err
+ }
+ if len(p) >= maxLineLength {
+ return nil, ErrLineTooLong
+ }
+
+ // Chop off trailing white space.
+ p = bytes.TrimRight(p, " \r\t\n")
+
+ return p, nil
+}
+
+// readLineBytes, but convert the bytes into a string.
+func readLine(b *bufio.Reader) (s string, err error) {
+ p, e := readLineBytes(b)
+ if e != nil {
+ return "", e
+ }
+ return string(p), nil
+}
+
+// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
// sends the final 0-length chunk that marks the end of the stream.
//
// NewChunkedWriter is not needed by normal applications. The http
@@ -25,8 +133,8 @@ func NewChunkedWriter(w io.Writer) io.WriteCloser {
return &chunkedWriter{w}
}
-// Writing to ChunkedWriter translates to writing in HTTP chunked Transfer
-// Encoding wire format to the underlying Wire writer.
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
type chunkedWriter struct {
Wire io.Writer
}
@@ -62,23 +170,3 @@ func (cw *chunkedWriter) Close() error {
_, err := io.WriteString(cw.Wire, "0\r\n")
return err
}
-
-// NewChunkedReader returns a new reader that translates the data read from r
-// out of HTTP "chunked" format before returning it.
-// The reader returns io.EOF when the final 0-length chunk is read.
-//
-// NewChunkedReader is not needed by normal applications. The http package
-// automatically decodes chunking when reading response bodies.
-func NewChunkedReader(r io.Reader) io.Reader {
- // This is a bit of a hack so we don't have to copy chunkedReader into
- // httputil. It's a bit more complex than chunkedWriter, which is copied
- // above.
- req, err := http.ReadRequest(bufio.NewReader(io.MultiReader(
- strings.NewReader("POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"),
- r,
- strings.NewReader("\r\n"))))
- if err != nil {
- panic("bad fake request: " + err.Error())
- }
- return req.Body
-}
diff --git a/libgo/go/net/http/httputil/chunked_test.go b/libgo/go/net/http/httputil/chunked_test.go
index 258d39b9..155a32b 100644
--- a/libgo/go/net/http/httputil/chunked_test.go
+++ b/libgo/go/net/http/httputil/chunked_test.go
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// This code is a duplicate of ../chunked_test.go with these edits:
+// s/newChunked/NewChunked/g
+// s/package http/package httputil/
+// Please make any changes in both files.
+
package httputil
import (
@@ -27,7 +32,8 @@ func TestChunk(t *testing.T) {
r := NewChunkedReader(&b)
data, err := ioutil.ReadAll(r)
if err != nil {
- t.Fatalf("ReadAll from NewChunkedReader: %v", err)
+ t.Logf(`data: "%s"`, data)
+ t.Fatalf("ReadAll from reader: %v", err)
}
if g, e := string(data), chunk1+chunk2; g != e {
t.Errorf("chunk reader read %q; want %q", g, e)
diff --git a/libgo/go/net/http/httputil/persist.go b/libgo/go/net/http/httputil/persist.go
index d7b67011..1266bd3 100644
--- a/libgo/go/net/http/httputil/persist.go
+++ b/libgo/go/net/http/httputil/persist.go
@@ -22,6 +22,10 @@ var (
ErrPipeline = &http.ProtocolError{"pipeline error"}
)
+// This is an API usage error - the local side is closed.
+// ErrPersistEOF (above) reports that the remote side is closed.
+var errClosed = errors.New("i/o operation on closed connection")
+
// A ServerConn reads requests and sends responses over an underlying
// connection, until the HTTP keepalive logic commands an end. ServerConn
// also allows hijacking the underlying connection by calling Hijack
@@ -108,7 +112,7 @@ func (sc *ServerConn) Read() (req *http.Request, err error) {
}
if sc.r == nil { // connection closed by user in the meantime
defer sc.lk.Unlock()
- return nil, os.EBADF
+ return nil, errClosed
}
r := sc.r
lastbody := sc.lastbody
@@ -313,7 +317,7 @@ func (cc *ClientConn) Write(req *http.Request) (err error) {
}
if cc.c == nil { // connection closed by user in the meantime
defer cc.lk.Unlock()
- return os.EBADF
+ return errClosed
}
c := cc.c
if req.Close {
@@ -369,7 +373,7 @@ func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
}
if cc.r == nil { // connection closed by user in the meantime
defer cc.lk.Unlock()
- return nil, os.EBADF
+ return nil, errClosed
}
r := cc.r
lastbody := cc.lastbody
diff --git a/libgo/go/net/http/readrequest_test.go b/libgo/go/net/http/readrequest_test.go
index 2219d43..c64fff6 100644
--- a/libgo/go/net/http/readrequest_test.go
+++ b/libgo/go/net/http/readrequest_test.go
@@ -70,7 +70,6 @@ var reqTests = []reqTest{
Close: false,
ContentLength: 7,
Host: "www.techcrunch.com",
- Form: url.Values{},
},
"abcdef\n",
@@ -94,10 +93,10 @@ var reqTests = []reqTest{
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
+ Header: Header{},
Close: false,
ContentLength: 0,
Host: "foo.com",
- Form: url.Values{},
},
noBody,
@@ -131,7 +130,6 @@ var reqTests = []reqTest{
Close: false,
ContentLength: 0,
Host: "test",
- Form: url.Values{},
},
noBody,
@@ -180,9 +178,9 @@ var reqTests = []reqTest{
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
+ Header: Header{},
ContentLength: -1,
Host: "foo.com",
- Form: url.Values{},
},
"foobar",
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 4410ca1..6617849 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -19,12 +19,10 @@ import (
"mime/multipart"
"net/textproto"
"net/url"
- "strconv"
"strings"
)
const (
- maxLineLength = 4096 // assumed <= bufio.defaultBufSize
maxValueLength = 4096
maxHeaderLines = 1024
chunkSize = 4 << 10 // 4 KB chunks
@@ -43,7 +41,6 @@ type ProtocolError struct {
func (err *ProtocolError) Error() string { return err.ErrorString }
var (
- ErrLineTooLong = &ProtocolError{"header line too long"}
ErrHeaderTooLong = &ProtocolError{"header too long"}
ErrShortBody = &ProtocolError{"entity body too short"}
ErrNotSupported = &ProtocolError{"feature not supported"}
@@ -375,44 +372,6 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
return nil
}
-// Read a line of bytes (up to \n) from b.
-// Give up if the line exceeds maxLineLength.
-// The returned bytes are a pointer into storage in
-// the bufio, so they are only valid until the next bufio read.
-func readLineBytes(b *bufio.Reader) (p []byte, err error) {
- if p, err = b.ReadSlice('\n'); err != nil {
- // We always know when EOF is coming.
- // If the caller asked for a line, there should be a line.
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- } else if err == bufio.ErrBufferFull {
- err = ErrLineTooLong
- }
- return nil, err
- }
- if len(p) >= maxLineLength {
- return nil, ErrLineTooLong
- }
-
- // Chop off trailing white space.
- var i int
- for i = len(p); i > 0; i-- {
- if c := p[i-1]; c != ' ' && c != '\r' && c != '\t' && c != '\n' {
- break
- }
- }
- return p[0:i], nil
-}
-
-// readLineBytes, but convert the bytes into a string.
-func readLine(b *bufio.Reader) (s string, err error) {
- p, e := readLineBytes(b)
- if e != nil {
- return "", e
- }
- return string(p), nil
-}
-
// Convert decimal at s[i:len(s)] to integer,
// returning value, string position where the digits stopped,
// and whether there was a valid number (digits, not too big).
@@ -448,55 +407,6 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
return major, minor, true
}
-type chunkedReader struct {
- r *bufio.Reader
- n uint64 // unread bytes in chunk
- err error
-}
-
-func (cr *chunkedReader) beginChunk() {
- // chunk-size CRLF
- var line string
- line, cr.err = readLine(cr.r)
- if cr.err != nil {
- return
- }
- cr.n, cr.err = strconv.Btoui64(line, 16)
- if cr.err != nil {
- return
- }
- if cr.n == 0 {
- cr.err = io.EOF
- }
-}
-
-func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
- if cr.err != nil {
- return 0, cr.err
- }
- if cr.n == 0 {
- cr.beginChunk()
- if cr.err != nil {
- return 0, cr.err
- }
- }
- if uint64(len(b)) > cr.n {
- b = b[0:cr.n]
- }
- n, cr.err = cr.r.Read(b)
- cr.n -= uint64(n)
- if cr.n == 0 && cr.err == nil {
- // end of chunk (CRLF)
- b := make([]byte, 2)
- if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
- if b[0] != '\r' || b[1] != '\n' {
- cr.err = errors.New("malformed chunked encoding")
- }
- }
- }
- return n, cr.err
-}
-
// NewRequest returns a new Request given a method, URL, and optional body.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
u, err := url.Parse(urlStr)
diff --git a/libgo/go/net/http/response_test.go b/libgo/go/net/http/response_test.go
index be717aa..e5d0169 100644
--- a/libgo/go/net/http/response_test.go
+++ b/libgo/go/net/http/response_test.go
@@ -65,6 +65,7 @@ var respTests = []respTest{
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
+ Header: Header{},
Request: dummyReq("GET"),
Close: true,
ContentLength: -1,
@@ -85,6 +86,7 @@ var respTests = []respTest{
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
+ Header: Header{},
Request: dummyReq("GET"),
Close: false,
ContentLength: 0,
@@ -315,7 +317,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) {
}
var wr io.Writer = &buf
if test.chunked {
- wr = &chunkedWriter{wr}
+ wr = newChunkedWriter(wr)
}
if test.compressed {
buf.WriteString("Content-Encoding: gzip\r\n")
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index e278396..97a0b13 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -1077,6 +1077,31 @@ func TestClientWriteShutdown(t *testing.T) {
}
}
+// Tests that chunked server responses that write 1 byte at a time are
+// buffered before chunk headers are added, not after chunk headers.
+func TestServerBufferedChunking(t *testing.T) {
+ if true {
+ t.Logf("Skipping known broken test; see Issue 2357")
+ return
+ }
+ conn := new(testConn)
+ conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
+ done := make(chan bool)
+ ls := &oneConnListener{conn}
+ go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ defer close(done)
+ rw.Header().Set("Content-Type", "text/plain") // prevent sniffing, which buffers
+ rw.Write([]byte{'x'})
+ rw.Write([]byte{'y'})
+ rw.Write([]byte{'z'})
+ }))
+ <-done
+ if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
+ t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
+ conn.writeBuf.Bytes())
+ }
+}
+
// goTimeout runs f, failing t if f takes more than ns to complete.
func goTimeout(t *testing.T, ns int64, f func()) {
ch := make(chan bool, 2)
@@ -1120,7 +1145,7 @@ func TestAcceptMaxFds(t *testing.T) {
ln := &errorListener{[]error{
&net.OpError{
Op: "accept",
- Err: os.Errno(syscall.EMFILE),
+ Err: syscall.EMFILE,
}}}
err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
if err != io.EOF {
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index 8c48894..7221d25 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -149,11 +149,13 @@ type writerOnly struct {
}
func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
- // Flush before checking w.chunking, as Flush will call
- // WriteHeader if it hasn't been called yet, and WriteHeader
- // is what sets w.chunking.
- w.Flush()
+ // Call WriteHeader before checking w.chunking if it hasn't
+ // been called yet, since WriteHeader is what sets w.chunking.
+ if !w.wroteHeader {
+ w.WriteHeader(StatusOK)
+ }
if !w.chunking && w.bodyAllowed() && !w.needSniff {
+ w.Flush()
if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
n, err = rf.ReadFrom(src)
w.written += n
diff --git a/libgo/go/net/http/sniff_test.go b/libgo/go/net/http/sniff_test.go
index a414e64..86744ee 100644
--- a/libgo/go/net/http/sniff_test.go
+++ b/libgo/go/net/http/sniff_test.go
@@ -6,6 +6,7 @@ package http_test
import (
"bytes"
+ "io"
"io/ioutil"
"log"
. "net/http"
@@ -79,3 +80,35 @@ func TestServerContentType(t *testing.T) {
resp.Body.Close()
}
}
+
+func TestContentTypeWithCopy(t *testing.T) {
+ const (
+ input = "\n<html>\n\t<head>\n"
+ expected = "text/html; charset=utf-8"
+ )
+
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ // Use io.Copy from a bytes.Buffer to trigger ReadFrom.
+ buf := bytes.NewBuffer([]byte(input))
+ n, err := io.Copy(w, buf)
+ if int(n) != len(input) || err != nil {
+ t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+ }
+ }))
+ defer ts.Close()
+
+ resp, err := Get(ts.URL)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ if ct := resp.Header.Get("Content-Type"); ct != expected {
+ t.Errorf("Content-Type = %q, want %q", ct, expected)
+ }
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ t.Errorf("reading body: %v", err)
+ } else if !bytes.Equal(data, []byte(input)) {
+ t.Errorf("data is %q, want %q", data, input)
+ }
+ resp.Body.Close()
+}
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go
index 2670d77..d25c8fc 100644
--- a/libgo/go/net/http/transfer.go
+++ b/libgo/go/net/http/transfer.go
@@ -537,7 +537,9 @@ func (b *body) Read(p []byte) (n int, err error) {
// Read the final trailer once we hit EOF.
if err == io.EOF && b.hdr != nil {
- err = b.readTrailer()
+ if e := b.readTrailer(); e != nil {
+ err = e
+ }
b.hdr = nil
}
return n, err
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index da5244b..e622e41 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -504,7 +504,7 @@ func (pc *persistConn) expectingResponse() bool {
var remoteSideClosedFunc func(error) bool // or nil to use default
func remoteSideClosed(err error) bool {
- if err == io.EOF || err == os.EINVAL {
+ if err == io.EOF {
return true
}
if remoteSideClosedFunc != nil {
diff --git a/libgo/go/net/http/transport_windows.go b/libgo/go/net/http/transport_windows.go
index 2a20d22..c9ef2c2 100644
--- a/libgo/go/net/http/transport_windows.go
+++ b/libgo/go/net/http/transport_windows.go
@@ -6,14 +6,14 @@ package http
import (
"net"
- "os"
+ "syscall"
)
func init() {
remoteSideClosedFunc = func(err error) (out bool) {
op, ok := err.(*net.OpError)
- if ok && op.Op == "WSARecv" && op.Net == "tcp" && op.Err == os.Errno(10058) {
- // TODO(bradfitz): find the symbol for 10058
+ if ok && op.Op == "WSARecv" && op.Net == "tcp" && op.Err == syscall.Errno(10058) {
+ // TODO(brainman,rsc): Fix whatever is generating this.
return true
}
return false
diff --git a/libgo/go/net/interface_bsd.go b/libgo/go/net/interface_bsd.go
index b026e01..e896d43 100644
--- a/libgo/go/net/interface_bsd.go
+++ b/libgo/go/net/interface_bsd.go
@@ -20,18 +20,18 @@ import (
func interfaceTable(ifindex int) ([]Interface, error) {
var (
tab []byte
- e int
+ e error
msgs []syscall.RoutingMessage
ift []Interface
)
tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route rib", e)
}
msgs, e = syscall.ParseRoutingMessage(tab)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route message", e)
}
@@ -55,7 +55,7 @@ func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
var ift []Interface
sas, e := syscall.ParseRoutingSockaddr(m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route sockaddr", e)
}
@@ -110,18 +110,18 @@ func linkFlags(rawFlags int32) Flags {
func interfaceAddrTable(ifindex int) ([]Addr, error) {
var (
tab []byte
- e int
+ e error
msgs []syscall.RoutingMessage
ifat []Addr
)
tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route rib", e)
}
msgs, e = syscall.ParseRoutingMessage(tab)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route message", e)
}
@@ -145,7 +145,7 @@ func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, error) {
var ifat []Addr
sas, e := syscall.ParseRoutingSockaddr(m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route sockaddr", e)
}
diff --git a/libgo/go/net/interface_darwin.go b/libgo/go/net/interface_darwin.go
index 1472afb..2da447a 100644
--- a/libgo/go/net/interface_darwin.go
+++ b/libgo/go/net/interface_darwin.go
@@ -17,18 +17,18 @@ import (
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
var (
tab []byte
- e int
+ e error
msgs []syscall.RoutingMessage
ifmat []Addr
)
tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route rib", e)
}
msgs, e = syscall.ParseRoutingMessage(tab)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route message", e)
}
@@ -52,7 +52,7 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
var ifmat []Addr
sas, e := syscall.ParseRoutingSockaddr(m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route sockaddr", e)
}
diff --git a/libgo/go/net/interface_freebsd.go b/libgo/go/net/interface_freebsd.go
index b0274f6..a12877e 100644
--- a/libgo/go/net/interface_freebsd.go
+++ b/libgo/go/net/interface_freebsd.go
@@ -17,18 +17,18 @@ import (
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
var (
tab []byte
- e int
+ e error
msgs []syscall.RoutingMessage
ifmat []Addr
)
tab, e = syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route rib", e)
}
msgs, e = syscall.ParseRoutingMessage(tab)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route message", e)
}
@@ -52,7 +52,7 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
var ifmat []Addr
sas, e := syscall.ParseRoutingSockaddr(m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("route sockaddr", e)
}
diff --git a/libgo/go/net/interface_linux.go b/libgo/go/net/interface_linux.go
index cd0339d..96db718 100644
--- a/libgo/go/net/interface_linux.go
+++ b/libgo/go/net/interface_linux.go
@@ -21,16 +21,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
ift []Interface
tab []byte
msgs []syscall.NetlinkMessage
- e int
+ e error
)
tab, e = syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("netlink rib", e)
}
msgs, e = syscall.ParseNetlinkMessage(tab)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("netlink message", e)
}
@@ -42,7 +42,7 @@ func interfaceTable(ifindex int) ([]Interface, error) {
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifim.Index) {
attrs, e := syscall.ParseNetlinkRouteAttr(&m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("netlink routeattr", e)
}
ifi := newLink(attrs, ifim)
@@ -102,27 +102,19 @@ func linkFlags(rawFlags uint32) Flags {
// for all network interfaces. Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, error) {
- var (
- tab []byte
- e int
- err error
- ifat []Addr
- msgs []syscall.NetlinkMessage
- )
-
- tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
- if e != 0 {
+ tab, e := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
+ if e != nil {
return nil, os.NewSyscallError("netlink rib", e)
}
- msgs, e = syscall.ParseNetlinkMessage(tab)
- if e != 0 {
+ msgs, e := syscall.ParseNetlinkMessage(tab)
+ if e != nil {
return nil, os.NewSyscallError("netlink message", e)
}
- ifat, err = addrTable(msgs, ifindex)
- if err != nil {
- return nil, err
+ ifat, e := addrTable(msgs, ifindex)
+ if e != nil {
+ return nil, e
}
return ifat, nil
@@ -139,7 +131,7 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifam.Index) {
attrs, e := syscall.ParseNetlinkRouteAttr(&m)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("netlink routeattr", e)
}
ifat = append(ifat, newAddr(attrs, int(ifam.Family))...)
diff --git a/libgo/go/net/interface_windows.go b/libgo/go/net/interface_windows.go
index a1c8d95..2ed66cd 100644
--- a/libgo/go/net/interface_windows.go
+++ b/libgo/go/net/interface_windows.go
@@ -39,7 +39,7 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
func getInterfaceList() ([]syscall.InterfaceInfo, error) {
s, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("Socket", e)
}
defer syscall.Closesocket(s)
@@ -48,7 +48,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, error) {
ret := uint32(0)
size := uint32(unsafe.Sizeof(ii))
e = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("WSAIoctl", e)
}
c := ret / uint32(unsafe.Sizeof(ii[0]))
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index 716454d..9234f5a 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -9,7 +9,7 @@ package net
var supportsIPv6, supportsIPv4map = probeIPv6Stack()
func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
- if filter == anyaddr {
+ if filter == nil {
// We'll take any IP address, but since the dialing code
// does not yet try multiple addresses, prefer to use
// an IPv4 address if possible. This is especially relevant
@@ -113,7 +113,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
// Try as an IP address.
addr = ParseIP(host)
if addr == nil {
- filter := anyaddr
+ var filter func(IP) IP
if net != "" && net[len(net)-1] == '4' {
filter = ipv4only
}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index d5b8f21..f0ca7da 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -33,8 +33,8 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
}
for i := range probes {
- s, errno := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
- if errno != 0 {
+ s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+ if err != nil {
continue
}
defer closesocket(s)
@@ -42,8 +42,8 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
if err != nil {
continue
}
- errno = syscall.Bind(s, sa)
- if errno != 0 {
+ err = syscall.Bind(s, sa)
+ if err != nil {
continue
}
probes[i].ok = true
diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go
index 61d8a88..020871b 100644
--- a/libgo/go/net/lookup_windows.go
+++ b/libgo/go/net/lookup_windows.go
@@ -22,7 +22,7 @@ func lookupProtocol(name string) (proto int, err error) {
protoentLock.Lock()
defer protoentLock.Unlock()
p, e := syscall.GetProtoByName(name)
- if e != 0 {
+ if e != nil {
return 0, os.NewSyscallError("GetProtoByName", e)
}
return int(p.Proto), nil
@@ -44,7 +44,7 @@ func LookupIP(name string) (addrs []IP, err error) {
hostentLock.Lock()
defer hostentLock.Unlock()
h, e := syscall.GetHostByName(name)
- if e != 0 {
+ if e != nil {
return nil, os.NewSyscallError("GetHostByName", e)
}
switch h.AddrType {
@@ -71,7 +71,7 @@ func LookupPort(network, service string) (port int, err error) {
serventLock.Lock()
defer serventLock.Unlock()
s, e := syscall.GetServByName(service, network)
- if e != 0 {
+ if e != nil {
return 0, os.NewSyscallError("GetServByName", e)
}
return int(syscall.Ntohs(s.Port)), nil
@@ -81,7 +81,7 @@ func LookupCNAME(name string) (cname string, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
if e != 0 {
- return "", os.NewSyscallError("LookupCNAME", int(e))
+ return "", os.NewSyscallError("LookupCNAME", e)
}
defer syscall.DnsRecordListFree(r, 1)
if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
@@ -110,7 +110,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
var r *syscall.DNSRecord
e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
if e != 0 {
- return "", nil, os.NewSyscallError("LookupSRV", int(e))
+ return "", nil, os.NewSyscallError("LookupSRV", e)
}
defer syscall.DnsRecordListFree(r, 1)
addrs = make([]*SRV, 0, 10)
@@ -126,7 +126,7 @@ func LookupMX(name string) (mx []*MX, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
if e != 0 {
- return nil, os.NewSyscallError("LookupMX", int(e))
+ return nil, os.NewSyscallError("LookupMX", e)
}
defer syscall.DnsRecordListFree(r, 1)
mx = make([]*MX, 0, 10)
@@ -142,7 +142,7 @@ func LookupTXT(name string) (txt []string, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
if e != 0 {
- return nil, os.NewSyscallError("LookupTXT", int(e))
+ return nil, os.NewSyscallError("LookupTXT", e)
}
defer syscall.DnsRecordListFree(r, 1)
txt = make([]string, 0, 10)
@@ -164,7 +164,7 @@ func LookupAddr(addr string) (name []string, err error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
if e != 0 {
- return nil, os.NewSyscallError("LookupAddr", int(e))
+ return nil, os.NewSyscallError("LookupAddr", e)
}
defer syscall.DnsRecordListFree(r, 1)
name = make([]string, 0, 10)
diff --git a/libgo/go/net/newpollserver.go b/libgo/go/net/newpollserver.go
index 9ad6f7b..035df4a 100644
--- a/libgo/go/net/newpollserver.go
+++ b/libgo/go/net/newpollserver.go
@@ -18,11 +18,10 @@ func newPollServer() (s *pollServer, err error) {
if s.pr, s.pw, err = os.Pipe(); err != nil {
return nil, err
}
- var e int
- if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
+ if err = syscall.SetNonblock(s.pr.Fd(), true); err != nil {
goto Errno
}
- if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 {
+ if err = syscall.SetNonblock(s.pw.Fd(), true); err != nil {
goto Errno
}
if s.poll, err = newpollster(); err != nil {
@@ -37,7 +36,7 @@ func newPollServer() (s *pollServer, err error) {
return s, nil
Errno:
- err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
+ err = &os.PathError{"setnonblock", s.pr.Name(), err}
Error:
s.pr.Close()
s.pw.Close()
diff --git a/libgo/go/net/pipe.go b/libgo/go/net/pipe.go
index b99e6e6..0ce7ccb 100644
--- a/libgo/go/net/pipe.go
+++ b/libgo/go/net/pipe.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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 (
diff --git a/libgo/go/net/sendfile_linux.go b/libgo/go/net/sendfile_linux.go
index 36c7578..350abe4 100644
--- a/libgo/go/net/sendfile_linux.go
+++ b/libgo/go/net/sendfile_linux.go
@@ -62,18 +62,18 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
written += int64(n)
remain -= int64(n)
}
- if n == 0 && errno == 0 {
+ if n == 0 && errno == nil {
break
}
if errno == syscall.EAGAIN && c.wdeadline >= 0 {
pollserver.WaitWrite(c)
continue
}
- if errno != 0 {
+ if errno != nil {
// 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)}
+ err = &OpError{"sendfile", c.net, c.raddr, errno}
break
}
}
diff --git a/libgo/go/net/sendfile_windows.go b/libgo/go/net/sendfile_windows.go
index 0b31572..ee7ff8b 100644
--- a/libgo/go/net/sendfile_windows.go
+++ b/libgo/go/net/sendfile_windows.go
@@ -16,7 +16,7 @@ type sendfileOp struct {
n uint32
}
-func (o *sendfileOp) Submit() (errno int) {
+func (o *sendfileOp) Submit() (err error) {
return syscall.TransmitFile(o.fd.sysfd, o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
}
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index d9df02c..33f11f2 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -28,9 +28,9 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
// See ../syscall/exec.go for description of ForkLock.
syscall.ForkLock.RLock()
s, e := syscall.Socket(f, p, t)
- if e != 0 {
+ if err != nil {
syscall.ForkLock.RUnlock()
- return nil, os.Errno(e)
+ return nil, err
}
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
@@ -39,9 +39,9 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
if la != nil {
e = syscall.Bind(s, la)
- if e != 0 {
+ if e != nil {
closesocket(s)
- return nil, os.Errno(e)
+ return nil, e
}
}
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index a726b45..44890ba 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -250,9 +250,9 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
return nil, err
}
errno := syscall.Listen(fd.sysfd, listenBacklog())
- if errno != 0 {
+ if errno != nil {
closesocket(fd.sysfd)
- return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)}
+ return nil, &OpError{"listen", "tcp", laddr, errno}
}
l = new(TCPListener)
l.fd = fd
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 6ba692e..929f640 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -327,9 +327,9 @@ func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
return nil, err
}
e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
- if e1 != 0 {
+ if e1 != nil {
closesocket(fd.sysfd)
- return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: os.Errno(e1)}
+ return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: e1}
}
return &UnixListener{fd, laddr.Name}, nil
}