]> Cypherpunks repositories - gostls13.git/commitdiff
net: add ReadFrom and WriteTo windows version.
authorWei Guangjing <vcc.163@gmail.com>
Mon, 22 Nov 2010 16:01:30 +0000 (11:01 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 22 Nov 2010 16:01:30 +0000 (11:01 -0500)
Fixes #1275.

R=rsc, brainman
CC=golang-dev
https://golang.org/cl/3136042

src/pkg/net/fd_windows.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go

index 1da2ca47ff1eaa9ec88f7cc6a31fd01bb7c31346..75e2e4f2d1fb897e080089b37d5899315b9ec3f6 100644 (file)
@@ -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) {
index 495855cf07e48337d47785b41c9ce62ea9b65683..2811a984296717d4de7faac3bffaf08321f802d6 100644 (file)
@@ -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 }
index 6837de1208af4f017daead7031d5c67545ec5c31..6fcad87c9c9adcccba4d573353e1e3265c66ff9c 100644 (file)
@@ -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))