From 95c341fc78b885b265314a678fa6643522ce37f5 Mon Sep 17 00:00:00 2001 From: Wei Guangjing Date: Mon, 22 Nov 2010 11:01:30 -0500 Subject: [PATCH] net: add ReadFrom and WriteTo windows version. Fixes #1275. R=rsc, brainman CC=golang-dev https://golang.org/cl/3136042 --- src/pkg/net/fd_windows.go | 73 ++++++++++++++++++++++++- src/pkg/syscall/syscall_windows.go | 11 ++++ src/pkg/syscall/zsyscall_windows_386.go | 30 ++++++++++ 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go index 1da2ca47ff..75e2e4f2d1 100644 --- a/src/pkg/net/fd_windows.go +++ b/src/pkg/net/fd_windows.go @@ -243,8 +243,43 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) { } func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) { - var r syscall.Sockaddr - return 0, r, nil + if fd == nil { + return 0, nil, os.EINVAL + } + if len(p) == 0 { + return 0, nil, nil + } + fd.rio.Lock() + defer fd.rio.Unlock() + fd.incref() + defer fd.decref() + if fd.sysfile == nil { + return 0, nil, os.EINVAL + } + // Submit receive request. + var pckt ioPacket + pckt.c = fd.cr + var done uint32 + flags := uint32(0) + var rsa syscall.RawSockaddrAny + l := int32(unsafe.Sizeof(rsa)) + e := syscall.WSARecvFrom(uint32(fd.sysfd), newWSABuf(p), 1, &done, &flags, &rsa, &l, &pckt.o, nil) + switch e { + case 0: + // 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 it's completion. + default: + return 0, nil, &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(e)} + } + // Wait for our request to complete. + r := <-pckt.c + if r.errno != 0 { + err = &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(r.errno)} + } + n = int(r.qty) + sa, _ = rsa.Sockaddr() + return } func (fd *netFD) Write(p []byte) (n int, err os.Error) { @@ -281,7 +316,39 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) { } func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) { - return 0, nil + if fd == nil { + return 0, os.EINVAL + } + if len(p) == 0 { + return 0, nil + } + fd.wio.Lock() + defer fd.wio.Unlock() + fd.incref() + defer fd.decref() + if fd.sysfile == nil { + return 0, os.EINVAL + } + // Submit send request. + var pckt ioPacket + pckt.c = fd.cw + var done uint32 + e := syscall.WSASendto(uint32(fd.sysfd), newWSABuf(p), 1, &done, 0, sa, &pckt.o, nil) + switch e { + case 0: + // 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 it's completion. + default: + return 0, &OpError{"WSASendTo", fd.net, fd.laddr, os.Errno(e)} + } + // Wait for our request to complete. + r := <-pckt.c + if r.errno != 0 { + err = &OpError{"WSASendTo", fd.net, fd.laddr, os.Errno(r.errno)} + } + n = int(r.qty) + return } func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go index 495855cf07..2811a98429 100644 --- a/src/pkg/syscall/syscall_windows.go +++ b/src/pkg/syscall/syscall_windows.go @@ -467,6 +467,8 @@ func Utimes(path string, tv []Timeval) (errno int) { //sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = wsock32.GetAcceptExSockaddrs //sys WSARecv(s uint32, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (errno int) [failretval=-1] = ws2_32.WSARecv //sys WSASend(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (errno int) [failretval=-1] = ws2_32.WSASend +//sys WSARecvFrom(s uint32, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (errno int) [failretval=-1] = ws2_32.WSARecvFrom +//sys WSASendTo(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (errno int) [failretval=-1] = ws2_32.WSASendTo //sys GetHostByName(name string) (h *Hostent, errno int) [failretval=nil] = ws2_32.gethostbyname //sys GetServByName(name string, proto string) (s *Servent, errno int) [failretval=nil] = ws2_32.getservbyname //sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs @@ -633,6 +635,15 @@ func GetAcceptIOCPSockaddrs(attrs *byte) (lsa, rsa Sockaddr) { return } +func WSASendto(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (errno int) { + rsa, l, err := to.sockaddr() + if err != 0 { + return err + } + errno = WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) + return +} + // TODO(brainman): fix all needed for net func Accept(fd int) (nfd int, sa Sockaddr, errno int) { return 0, nil, EWINDOWS } diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go index 6837de1208..6fcad87c9c 100644 --- a/src/pkg/syscall/zsyscall_windows_386.go +++ b/src/pkg/syscall/zsyscall_windows_386.go @@ -75,6 +75,8 @@ var ( procGetAcceptExSockaddrs = getSysProcAddr(modwsock32, "GetAcceptExSockaddrs") procWSARecv = getSysProcAddr(modws2_32, "WSARecv") procWSASend = getSysProcAddr(modws2_32, "WSASend") + procWSARecvFrom = getSysProcAddr(modws2_32, "WSARecvFrom") + procWSASendTo = getSysProcAddr(modws2_32, "WSASendTo") procgethostbyname = getSysProcAddr(modws2_32, "gethostbyname") procgetservbyname = getSysProcAddr(modws2_32, "getservbyname") procntohs = getSysProcAddr(modws2_32, "ntohs") @@ -983,6 +985,34 @@ func WSASend(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, return } +func WSARecvFrom(s uint32, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (errno int) { + r1, _, e1 := Syscall9(procWSARecvFrom, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if int(r1) == -1 { + if e1 != 0 { + errno = int(e1) + } else { + errno = EINVAL + } + } else { + errno = 0 + } + return +} + +func WSASendTo(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (errno int) { + r1, _, e1 := Syscall9(procWSASendTo, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if int(r1) == -1 { + if e1 != 0 { + errno = int(e1) + } else { + errno = EINVAL + } + } else { + errno = 0 + } + return +} + func GetHostByName(name string) (h *Hostent, errno int) { r0, _, e1 := Syscall(procgethostbyname, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0) h = (*Hostent)(unsafe.Pointer(r0))