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  }