@@ -7,6 +7,7 @@ package poll
77import (
88 "errors"
99 "internal/race"
10+ "internal/syscall/windows"
1011 "io"
1112 "runtime"
1213 "sync"
@@ -92,6 +93,7 @@ type operation struct {
9293 fd * FD
9394 errc chan error
9495 buf syscall.WSABuf
96+ msg windows.WSAMsg
9597 sa syscall.Sockaddr
9698 rsa * syscall.RawSockaddrAny
9799 rsan int32
@@ -132,6 +134,22 @@ func (o *operation) ClearBufs() {
132134 o .bufs = o .bufs [:0 ]
133135}
134136
137+ func (o * operation ) InitMsg (p []byte , oob []byte ) {
138+ o .InitBuf (p )
139+ o .msg .Buffers = & o .buf
140+ o .msg .BufferCount = 1
141+
142+ o .msg .Name = nil
143+ o .msg .Namelen = 0
144+
145+ o .msg .Flags = 0
146+ o .msg .Control .Len = uint32 (len (oob ))
147+ o .msg .Control .Buf = nil
148+ if len (oob ) != 0 {
149+ o .msg .Control .Buf = & oob [0 ]
150+ }
151+ }
152+
135153// ioSrv executes net IO requests.
136154type ioSrv struct {
137155 req chan ioSrvReq
@@ -898,3 +916,77 @@ func (fd *FD) RawRead(f func(uintptr) bool) error {
898916func (fd * FD ) RawWrite (f func (uintptr ) bool ) error {
899917 return errors .New ("not implemented" )
900918}
919+
920+ func sockaddrToRaw (sa syscall.Sockaddr ) (unsafe.Pointer , int32 , error ) {
921+ switch sa := sa .(type ) {
922+ case * syscall.SockaddrInet4 :
923+ var raw syscall.RawSockaddrInet4
924+ raw .Family = syscall .AF_INET
925+ p := (* [2 ]byte )(unsafe .Pointer (& raw .Port ))
926+ p [0 ] = byte (sa .Port >> 8 )
927+ p [1 ] = byte (sa .Port )
928+ for i := 0 ; i < len (sa .Addr ); i ++ {
929+ raw .Addr [i ] = sa .Addr [i ]
930+ }
931+ return unsafe .Pointer (& raw ), int32 (unsafe .Sizeof (raw )), nil
932+ case * syscall.SockaddrInet6 :
933+ var raw syscall.RawSockaddrInet6
934+ raw .Family = syscall .AF_INET6
935+ p := (* [2 ]byte )(unsafe .Pointer (& raw .Port ))
936+ p [0 ] = byte (sa .Port >> 8 )
937+ p [1 ] = byte (sa .Port )
938+ raw .Scope_id = sa .ZoneId
939+ for i := 0 ; i < len (sa .Addr ); i ++ {
940+ raw .Addr [i ] = sa .Addr [i ]
941+ }
942+ return unsafe .Pointer (& raw ), int32 (unsafe .Sizeof (raw )), nil
943+ default :
944+ return nil , 0 , syscall .EWINDOWS
945+ }
946+ }
947+
948+ // ReadMsg wraps the WSARecvMsg network call.
949+ func (fd * FD ) ReadMsg (p []byte , oob []byte ) (int , int , int , syscall.Sockaddr , error ) {
950+ if err := fd .readLock (); err != nil {
951+ return 0 , 0 , 0 , nil , err
952+ }
953+ defer fd .readUnlock ()
954+
955+ o := & fd .rop
956+ o .InitMsg (p , oob )
957+ o .rsa = new (syscall.RawSockaddrAny )
958+ o .msg .Name = o .rsa
959+ o .msg .Namelen = int32 (unsafe .Sizeof (* o .rsa ))
960+ n , err := rsrv .ExecIO (o , func (o * operation ) error {
961+ return windows .WSARecvMsg (o .fd .Sysfd , & o .msg , & o .qty , & o .o , nil )
962+ })
963+ err = fd .eofError (n , err )
964+ var sa syscall.Sockaddr
965+ if err == nil {
966+ sa , err = o .rsa .Sockaddr ()
967+ }
968+ return n , int (o .msg .Control .Len ), int (o .msg .Flags ), sa , err
969+ }
970+
971+ // WriteMsg wraps the WSASendMsg network call.
972+ func (fd * FD ) WriteMsg (p []byte , oob []byte , sa syscall.Sockaddr ) (int , int , error ) {
973+ if err := fd .writeLock (); err != nil {
974+ return 0 , 0 , err
975+ }
976+ defer fd .writeUnlock ()
977+
978+ o := & fd .wop
979+ o .InitMsg (p , oob )
980+ if sa != nil {
981+ rsa , len , err := sockaddrToRaw (sa )
982+ if err != nil {
983+ return 0 , 0 , err
984+ }
985+ o .msg .Name = (* syscall .RawSockaddrAny )(rsa )
986+ o .msg .Namelen = len
987+ }
988+ n , err := wsrv .ExecIO (o , func (o * operation ) error {
989+ return windows .WSASendMsg (o .fd .Sysfd , & o .msg , 0 , & o .qty , & o .o , nil )
990+ })
991+ return n , int (o .msg .Control .Len ), err
992+ }
0 commit comments