github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/bufio/vectorised_windows.go (about) 1 package bufio 2 3 import ( 4 "sync" 5 6 "github.com/sagernet/sing/common/buf" 7 M "github.com/sagernet/sing/common/metadata" 8 9 "golang.org/x/sys/windows" 10 ) 11 12 type syscallVectorisedWriterFields struct { 13 access sync.Mutex 14 iovecList *[]windows.WSABuf 15 } 16 17 func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error { 18 w.access.Lock() 19 defer w.access.Unlock() 20 defer buf.ReleaseMulti(buffers) 21 var iovecList []windows.WSABuf 22 if w.iovecList != nil { 23 iovecList = *w.iovecList 24 } 25 iovecList = iovecList[:0] 26 for _, buffer := range buffers { 27 iovecList = append(iovecList, windows.WSABuf{ 28 Buf: &buffer.Bytes()[0], 29 Len: uint32(buffer.Len()), 30 }) 31 } 32 if w.iovecList == nil { 33 w.iovecList = new([]windows.WSABuf) 34 } 35 *w.iovecList = iovecList // cache 36 var n uint32 37 var innerErr error 38 err := w.rawConn.Write(func(fd uintptr) (done bool) { 39 innerErr = windows.WSASend(windows.Handle(fd), &iovecList[0], uint32(len(iovecList)), &n, 0, nil, nil) 40 return innerErr != windows.WSAEWOULDBLOCK 41 }) 42 if innerErr != nil { 43 err = innerErr 44 } 45 for index := range iovecList { 46 iovecList[index] = windows.WSABuf{} 47 } 48 return err 49 } 50 51 func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error { 52 w.access.Lock() 53 defer w.access.Unlock() 54 defer buf.ReleaseMulti(buffers) 55 var iovecList []windows.WSABuf 56 if w.iovecList != nil { 57 iovecList = *w.iovecList 58 } 59 iovecList = iovecList[:0] 60 for _, buffer := range buffers { 61 iovecList = append(iovecList, windows.WSABuf{ 62 Buf: &buffer.Bytes()[0], 63 Len: uint32(buffer.Len()), 64 }) 65 } 66 if w.iovecList == nil { 67 w.iovecList = new([]windows.WSABuf) 68 } 69 *w.iovecList = iovecList // cache 70 var n uint32 71 var innerErr error 72 err := w.rawConn.Write(func(fd uintptr) (done bool) { 73 name, nameLen := ToSockaddr(destination.AddrPort()) 74 innerErr = windows.WSASendTo( 75 windows.Handle(fd), 76 &iovecList[0], 77 uint32(len(iovecList)), 78 &n, 79 0, 80 (*windows.RawSockaddrAny)(name), 81 nameLen, 82 nil, 83 nil) 84 return innerErr != windows.WSAEWOULDBLOCK 85 }) 86 if innerErr != nil { 87 err = innerErr 88 } 89 for index := range iovecList { 90 iovecList[index] = windows.WSABuf{} 91 } 92 return err 93 }