// RawRead invokes the user-defined function f for a read operation.
func (fd *FD) RawRead(f func(uintptr) bool) error {
- return errors.New("not implemented")
+ if err := fd.readLock(); err != nil {
+ return err
+ }
+ defer fd.readUnlock()
+ for {
+ if f(uintptr(fd.Sysfd)) {
+ return nil
+ }
+
+ // Use a zero-byte read as a way to get notified when this
+ // socket is readable. h/t https://stackoverflow.com/a/42019668/332798
+ o := &fd.rop
+ o.InitBuf(nil)
+ if !fd.IsStream {
+ o.flags |= windows.MSG_PEEK
+ }
+ _, err := rsrv.ExecIO(o, func(o *operation) error {
+ return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
+ })
+ if err == windows.WSAEMSGSIZE {
+ // expected with a 0-byte peek, ignore.
+ } else if err != nil {
+ return err
+ }
+ }
}
// RawWrite invokes the user-defined function f for a write operation.
func (fd *FD) RawWrite(f func(uintptr) bool) error {
- return errors.New("not implemented")
+ if err := fd.writeLock(); err != nil {
+ return err
+ }
+ defer fd.writeUnlock()
+ for {
+ if f(uintptr(fd.Sysfd)) {
+ return nil
+ }
+ }
}
func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
WSAEMSGSIZE syscall.Errno = 10040
+ MSG_PEEK = 0x2
MSG_TRUNC = 0x0100
MSG_CTRUNC = 0x0200
"syscall"
)
-// BUG(mikio): On Windows, the Read and Write methods of
-// syscall.RawConn are not implemented.
-
// BUG(mikio): On NaCl and Plan 9, the Control, Read and Write methods
// of syscall.RawConn are not implemented.
func TestRawConnReadWrite(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
)
func readRawConn(c syscall.RawConn, b []byte) (int, error) {
- return 0, syscall.EWINDOWS
+ var operr error
+ var n int
+ err := c.Read(func(s uintptr) bool {
+ var read uint32
+ var flags uint32
+ var buf syscall.WSABuf
+ buf.Buf = &b[0]
+ buf.Len = uint32(len(b))
+ operr = syscall.WSARecv(syscall.Handle(s), &buf, 1, &read, &flags, nil, nil)
+ n = int(read)
+ return true
+ })
+ if err != nil {
+ return n, err
+ }
+ if operr != nil {
+ return n, operr
+ }
+ return n, nil
}
func writeRawConn(c syscall.RawConn, b []byte) error {
- return syscall.EWINDOWS
+ var operr error
+ err := c.Write(func(s uintptr) bool {
+ var written uint32
+ var buf syscall.WSABuf
+ buf.Buf = &b[0]
+ buf.Len = uint32(len(b))
+ operr = syscall.WSASend(syscall.Handle(s), &buf, 1, &written, 0, nil, nil)
+ return true
+ })
+ if err != nil {
+ return err
+ }
+ if operr != nil {
+ return operr
+ }
+ return nil
}
func controlRawConn(c syscall.RawConn, addr Addr) error {