github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/poll/fd_windows.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package poll
     6  
     7  import (
     8  	"errors"
     9  	"io"
    10  	"sync"
    11  	"syscall"
    12  	"unicode/utf16"
    13  	"unicode/utf8"
    14  	"unsafe"
    15  
    16  	"github.com/go-asm/go/race"
    17  	"github.com/go-asm/go/syscall/windows"
    18  )
    19  
    20  var (
    21  	initErr error
    22  	ioSync  uint64
    23  )
    24  
    25  // This package uses the SetFileCompletionNotificationModes Windows
    26  // API to skip calling GetQueuedCompletionStatus if an IO operation
    27  // completes synchronously. There is a known bug where
    28  // SetFileCompletionNotificationModes crashes on some systems (see
    29  // https://support.microsoft.com/kb/2568167 for details).
    30  
    31  var useSetFileCompletionNotificationModes bool // determines is SetFileCompletionNotificationModes is present and safe to use
    32  
    33  // checkSetFileCompletionNotificationModes verifies that
    34  // SetFileCompletionNotificationModes Windows API is present
    35  // on the system and is safe to use.
    36  // See https://support.microsoft.com/kb/2568167 for details.
    37  func checkSetFileCompletionNotificationModes() {
    38  	err := syscall.LoadSetFileCompletionNotificationModes()
    39  	if err != nil {
    40  		return
    41  	}
    42  	protos := [2]int32{syscall.IPPROTO_TCP, 0}
    43  	var buf [32]syscall.WSAProtocolInfo
    44  	len := uint32(unsafe.Sizeof(buf))
    45  	n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
    46  	if err != nil {
    47  		return
    48  	}
    49  	for i := int32(0); i < n; i++ {
    50  		if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
    51  			return
    52  		}
    53  	}
    54  	useSetFileCompletionNotificationModes = true
    55  }
    56  
    57  func init() {
    58  	var d syscall.WSAData
    59  	e := syscall.WSAStartup(uint32(0x202), &d)
    60  	if e != nil {
    61  		initErr = e
    62  	}
    63  	checkSetFileCompletionNotificationModes()
    64  }
    65  
    66  // operation contains superset of data necessary to perform all async IO.
    67  type operation struct {
    68  	// Used by IOCP interface, it must be first field
    69  	// of the struct, as our code rely on it.
    70  	o syscall.Overlapped
    71  
    72  	// fields used by runtime.netpoll
    73  	runtimeCtx uintptr
    74  	mode       int32
    75  	errno      int32
    76  	qty        uint32
    77  
    78  	// fields used only by net package
    79  	fd     *FD
    80  	buf    syscall.WSABuf
    81  	msg    windows.WSAMsg
    82  	sa     syscall.Sockaddr
    83  	rsa    *syscall.RawSockaddrAny
    84  	rsan   int32
    85  	handle syscall.Handle
    86  	flags  uint32
    87  	bufs   []syscall.WSABuf
    88  }
    89  
    90  func (o *operation) InitBuf(buf []byte) {
    91  	o.buf.Len = uint32(len(buf))
    92  	o.buf.Buf = nil
    93  	if len(buf) != 0 {
    94  		o.buf.Buf = &buf[0]
    95  	}
    96  }
    97  
    98  func (o *operation) InitBufs(buf *[][]byte) {
    99  	if o.bufs == nil {
   100  		o.bufs = make([]syscall.WSABuf, 0, len(*buf))
   101  	} else {
   102  		o.bufs = o.bufs[:0]
   103  	}
   104  	for _, b := range *buf {
   105  		if len(b) == 0 {
   106  			o.bufs = append(o.bufs, syscall.WSABuf{})
   107  			continue
   108  		}
   109  		for len(b) > maxRW {
   110  			o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
   111  			b = b[maxRW:]
   112  		}
   113  		if len(b) > 0 {
   114  			o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
   115  		}
   116  	}
   117  }
   118  
   119  // ClearBufs clears all pointers to Buffers parameter captured
   120  // by InitBufs, so it can be released by garbage collector.
   121  func (o *operation) ClearBufs() {
   122  	for i := range o.bufs {
   123  		o.bufs[i].Buf = nil
   124  	}
   125  	o.bufs = o.bufs[:0]
   126  }
   127  
   128  func (o *operation) InitMsg(p []byte, oob []byte) {
   129  	o.InitBuf(p)
   130  	o.msg.Buffers = &o.buf
   131  	o.msg.BufferCount = 1
   132  
   133  	o.msg.Name = nil
   134  	o.msg.Namelen = 0
   135  
   136  	o.msg.Flags = 0
   137  	o.msg.Control.Len = uint32(len(oob))
   138  	o.msg.Control.Buf = nil
   139  	if len(oob) != 0 {
   140  		o.msg.Control.Buf = &oob[0]
   141  	}
   142  }
   143  
   144  // execIO executes a single IO operation o. It submits and cancels
   145  // IO in the current thread for systems where Windows CancelIoEx API
   146  // is available. Alternatively, it passes the request onto
   147  // runtime netpoll and waits for completion or cancels request.
   148  func execIO(o *operation, submit func(o *operation) error) (int, error) {
   149  	if o.fd.pd.runtimeCtx == 0 {
   150  		return 0, errors.New("internal error: polling on unsupported descriptor type")
   151  	}
   152  
   153  	fd := o.fd
   154  	// Notify runtime netpoll about starting IO.
   155  	err := fd.pd.prepare(int(o.mode), fd.isFile)
   156  	if err != nil {
   157  		return 0, err
   158  	}
   159  	// Start IO.
   160  	err = submit(o)
   161  	switch err {
   162  	case nil:
   163  		// IO completed immediately
   164  		if o.fd.skipSyncNotif {
   165  			// No completion message will follow, so return immediately.
   166  			return int(o.qty), nil
   167  		}
   168  		// Need to get our completion message anyway.
   169  	case syscall.ERROR_IO_PENDING:
   170  		// IO started, and we have to wait for its completion.
   171  		err = nil
   172  	default:
   173  		return 0, err
   174  	}
   175  	// Wait for our request to complete.
   176  	err = fd.pd.wait(int(o.mode), fd.isFile)
   177  	if err == nil {
   178  		// All is good. Extract our IO results and return.
   179  		if o.errno != 0 {
   180  			err = syscall.Errno(o.errno)
   181  			// More data available. Return back the size of received data.
   182  			if err == syscall.ERROR_MORE_DATA || err == windows.WSAEMSGSIZE {
   183  				return int(o.qty), err
   184  			}
   185  			return 0, err
   186  		}
   187  		return int(o.qty), nil
   188  	}
   189  	// IO is interrupted by "close" or "timeout"
   190  	netpollErr := err
   191  	switch netpollErr {
   192  	case ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
   193  		// will deal with those.
   194  	default:
   195  		panic("unexpected runtime.netpoll error: " + netpollErr.Error())
   196  	}
   197  	// Cancel our request.
   198  	err = syscall.CancelIoEx(fd.Sysfd, &o.o)
   199  	// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
   200  	if err != nil && err != syscall.ERROR_NOT_FOUND {
   201  		// TODO(brainman): maybe do something else, but panic.
   202  		panic(err)
   203  	}
   204  	// Wait for cancellation to complete.
   205  	fd.pd.waitCanceled(int(o.mode))
   206  	if o.errno != 0 {
   207  		err = syscall.Errno(o.errno)
   208  		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
   209  			err = netpollErr
   210  		}
   211  		return 0, err
   212  	}
   213  	// We issued a cancellation request. But, it seems, IO operation succeeded
   214  	// before the cancellation request run. We need to treat the IO operation as
   215  	// succeeded (the bytes are actually sent/recv from network).
   216  	return int(o.qty), nil
   217  }
   218  
   219  // FD is a file descriptor. The net and os packages embed this type in
   220  // a larger type representing a network connection or OS file.
   221  type FD struct {
   222  	// Lock sysfd and serialize access to Read and Write methods.
   223  	fdmu fdMutex
   224  
   225  	// System file descriptor. Immutable until Close.
   226  	Sysfd syscall.Handle
   227  
   228  	// Read operation.
   229  	rop operation
   230  	// Write operation.
   231  	wop operation
   232  
   233  	// I/O poller.
   234  	pd pollDesc
   235  
   236  	// Used to implement pread/pwrite.
   237  	l sync.Mutex
   238  
   239  	// For console I/O.
   240  	lastbits       []byte   // first few bytes of the last incomplete rune in last write
   241  	readuint16     []uint16 // buffer to hold uint16s obtained with ReadConsole
   242  	readbyte       []byte   // buffer to hold decoding of readuint16 from utf16 to utf8
   243  	readbyteOffset int      // readbyte[readOffset:] is yet to be consumed with file.Read
   244  
   245  	// Semaphore signaled when file is closed.
   246  	csema uint32
   247  
   248  	skipSyncNotif bool
   249  
   250  	// Whether this is a streaming descriptor, as opposed to a
   251  	// packet-based descriptor like a UDP socket.
   252  	IsStream bool
   253  
   254  	// Whether a zero byte read indicates EOF. This is false for a
   255  	// message based socket connection.
   256  	ZeroReadIsEOF bool
   257  
   258  	// Whether this is a file rather than a network socket.
   259  	isFile bool
   260  
   261  	// The kind of this file.
   262  	kind fileKind
   263  }
   264  
   265  // fileKind describes the kind of file.
   266  type fileKind byte
   267  
   268  const (
   269  	kindNet fileKind = iota
   270  	kindFile
   271  	kindConsole
   272  	kindPipe
   273  )
   274  
   275  // logInitFD is set by tests to enable file descriptor initialization logging.
   276  var logInitFD func(net string, fd *FD, err error)
   277  
   278  // Init initializes the FD. The Sysfd field should already be set.
   279  // This can be called multiple times on a single FD.
   280  // The net argument is a network name from the net package (e.g., "tcp"),
   281  // or "file" or "console" or "dir".
   282  // Set pollable to true if fd should be managed by runtime netpoll.
   283  func (fd *FD) Init(net string, pollable bool) (string, error) {
   284  	if initErr != nil {
   285  		return "", initErr
   286  	}
   287  
   288  	switch net {
   289  	case "file", "dir":
   290  		fd.kind = kindFile
   291  	case "console":
   292  		fd.kind = kindConsole
   293  	case "pipe":
   294  		fd.kind = kindPipe
   295  	case "tcp", "tcp4", "tcp6",
   296  		"udp", "udp4", "udp6",
   297  		"ip", "ip4", "ip6",
   298  		"unix", "unixgram", "unixpacket":
   299  		fd.kind = kindNet
   300  	default:
   301  		return "", errors.New("internal error: unknown network type " + net)
   302  	}
   303  	fd.isFile = fd.kind != kindNet
   304  
   305  	var err error
   306  	if pollable {
   307  		// Only call init for a network socket.
   308  		// This means that we don't add files to the runtime poller.
   309  		// Adding files to the runtime poller can confuse matters
   310  		// if the user is doing their own overlapped I/O.
   311  		// See issue #21172.
   312  		//
   313  		// In general the code below avoids calling the execIO
   314  		// function for non-network sockets. If some method does
   315  		// somehow call execIO, then execIO, and therefore the
   316  		// calling method, will return an error, because
   317  		// fd.pd.runtimeCtx will be 0.
   318  		err = fd.pd.init(fd)
   319  	}
   320  	if logInitFD != nil {
   321  		logInitFD(net, fd, err)
   322  	}
   323  	if err != nil {
   324  		return "", err
   325  	}
   326  	if pollable && useSetFileCompletionNotificationModes {
   327  		// We do not use events, so we can skip them always.
   328  		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
   329  		switch net {
   330  		case "tcp", "tcp4", "tcp6",
   331  			"udp", "udp4", "udp6":
   332  			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
   333  		}
   334  		err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags)
   335  		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
   336  			fd.skipSyncNotif = true
   337  		}
   338  	}
   339  	// Disable SIO_UDP_CONNRESET behavior.
   340  	// http://support.microsoft.com/kb/263823
   341  	switch net {
   342  	case "udp", "udp4", "udp6":
   343  		ret := uint32(0)
   344  		flag := uint32(0)
   345  		size := uint32(unsafe.Sizeof(flag))
   346  		err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
   347  		if err != nil {
   348  			return "wsaioctl", err
   349  		}
   350  	}
   351  	fd.rop.mode = 'r'
   352  	fd.wop.mode = 'w'
   353  	fd.rop.fd = fd
   354  	fd.wop.fd = fd
   355  	fd.rop.runtimeCtx = fd.pd.runtimeCtx
   356  	fd.wop.runtimeCtx = fd.pd.runtimeCtx
   357  	return "", nil
   358  }
   359  
   360  func (fd *FD) destroy() error {
   361  	if fd.Sysfd == syscall.InvalidHandle {
   362  		return syscall.EINVAL
   363  	}
   364  	// Poller may want to unregister fd in readiness notification mechanism,
   365  	// so this must be executed before fd.CloseFunc.
   366  	fd.pd.close()
   367  	var err error
   368  	switch fd.kind {
   369  	case kindNet:
   370  		// The net package uses the CloseFunc variable for testing.
   371  		err = CloseFunc(fd.Sysfd)
   372  	default:
   373  		err = syscall.CloseHandle(fd.Sysfd)
   374  	}
   375  	fd.Sysfd = syscall.InvalidHandle
   376  	runtime_Semrelease(&fd.csema)
   377  	return err
   378  }
   379  
   380  // Close closes the FD. The underlying file descriptor is closed by
   381  // the destroy method when there are no remaining references.
   382  func (fd *FD) Close() error {
   383  	if !fd.fdmu.increfAndClose() {
   384  		return errClosing(fd.isFile)
   385  	}
   386  	if fd.kind == kindPipe {
   387  		syscall.CancelIoEx(fd.Sysfd, nil)
   388  	}
   389  	// unblock pending reader and writer
   390  	fd.pd.evict()
   391  	err := fd.decref()
   392  	// Wait until the descriptor is closed. If this was the only
   393  	// reference, it is already closed.
   394  	runtime_Semacquire(&fd.csema)
   395  	return err
   396  }
   397  
   398  // Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length.
   399  // This prevents us reading blocks larger than 4GB.
   400  // See golang.org/issue/26923.
   401  const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
   402  
   403  // Read implements io.Reader.
   404  func (fd *FD) Read(buf []byte) (int, error) {
   405  	if err := fd.readLock(); err != nil {
   406  		return 0, err
   407  	}
   408  	defer fd.readUnlock()
   409  
   410  	if len(buf) > maxRW {
   411  		buf = buf[:maxRW]
   412  	}
   413  
   414  	var n int
   415  	var err error
   416  	if fd.isFile {
   417  		fd.l.Lock()
   418  		defer fd.l.Unlock()
   419  		switch fd.kind {
   420  		case kindConsole:
   421  			n, err = fd.readConsole(buf)
   422  		default:
   423  			n, err = syscall.Read(fd.Sysfd, buf)
   424  			if fd.kind == kindPipe && err == syscall.ERROR_OPERATION_ABORTED {
   425  				// Close uses CancelIoEx to interrupt concurrent I/O for pipes.
   426  				// If the fd is a pipe and the Read was interrupted by CancelIoEx,
   427  				// we assume it is interrupted by Close.
   428  				err = ErrFileClosing
   429  			}
   430  		}
   431  		if err != nil {
   432  			n = 0
   433  		}
   434  	} else {
   435  		o := &fd.rop
   436  		o.InitBuf(buf)
   437  		n, err = execIO(o, func(o *operation) error {
   438  			return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
   439  		})
   440  		if race.Enabled {
   441  			race.Acquire(unsafe.Pointer(&ioSync))
   442  		}
   443  	}
   444  	if len(buf) != 0 {
   445  		err = fd.eofError(n, err)
   446  	}
   447  	return n, err
   448  }
   449  
   450  var ReadConsole = syscall.ReadConsole // changed for testing
   451  
   452  // readConsole reads utf16 characters from console File,
   453  // encodes them into utf8 and stores them in buffer b.
   454  // It returns the number of utf8 bytes read and an error, if any.
   455  func (fd *FD) readConsole(b []byte) (int, error) {
   456  	if len(b) == 0 {
   457  		return 0, nil
   458  	}
   459  
   460  	if fd.readuint16 == nil {
   461  		// Note: syscall.ReadConsole fails for very large buffers.
   462  		// The limit is somewhere around (but not exactly) 16384.
   463  		// Stay well below.
   464  		fd.readuint16 = make([]uint16, 0, 10000)
   465  		fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16))
   466  	}
   467  
   468  	for fd.readbyteOffset >= len(fd.readbyte) {
   469  		n := cap(fd.readuint16) - len(fd.readuint16)
   470  		if n > len(b) {
   471  			n = len(b)
   472  		}
   473  		var nw uint32
   474  		err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
   475  		if err != nil {
   476  			return 0, err
   477  		}
   478  		uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
   479  		fd.readuint16 = fd.readuint16[:0]
   480  		buf := fd.readbyte[:0]
   481  		for i := 0; i < len(uint16s); i++ {
   482  			r := rune(uint16s[i])
   483  			if utf16.IsSurrogate(r) {
   484  				if i+1 == len(uint16s) {
   485  					if nw > 0 {
   486  						// Save half surrogate pair for next time.
   487  						fd.readuint16 = fd.readuint16[:1]
   488  						fd.readuint16[0] = uint16(r)
   489  						break
   490  					}
   491  					r = utf8.RuneError
   492  				} else {
   493  					r = utf16.DecodeRune(r, rune(uint16s[i+1]))
   494  					if r != utf8.RuneError {
   495  						i++
   496  					}
   497  				}
   498  			}
   499  			buf = utf8.AppendRune(buf, r)
   500  		}
   501  		fd.readbyte = buf
   502  		fd.readbyteOffset = 0
   503  		if nw == 0 {
   504  			break
   505  		}
   506  	}
   507  
   508  	src := fd.readbyte[fd.readbyteOffset:]
   509  	var i int
   510  	for i = 0; i < len(src) && i < len(b); i++ {
   511  		x := src[i]
   512  		if x == 0x1A { // Ctrl-Z
   513  			if i == 0 {
   514  				fd.readbyteOffset++
   515  			}
   516  			break
   517  		}
   518  		b[i] = x
   519  	}
   520  	fd.readbyteOffset += i
   521  	return i, nil
   522  }
   523  
   524  // Pread emulates the Unix pread system call.
   525  func (fd *FD) Pread(b []byte, off int64) (int, error) {
   526  	if fd.kind == kindPipe {
   527  		// Pread does not work with pipes
   528  		return 0, syscall.ESPIPE
   529  	}
   530  	// Call incref, not readLock, because since pread specifies the
   531  	// offset it is independent from other reads.
   532  	if err := fd.incref(); err != nil {
   533  		return 0, err
   534  	}
   535  	defer fd.decref()
   536  
   537  	if len(b) > maxRW {
   538  		b = b[:maxRW]
   539  	}
   540  
   541  	fd.l.Lock()
   542  	defer fd.l.Unlock()
   543  	curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
   544  	if e != nil {
   545  		return 0, e
   546  	}
   547  	defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
   548  	o := syscall.Overlapped{
   549  		OffsetHigh: uint32(off >> 32),
   550  		Offset:     uint32(off),
   551  	}
   552  	var done uint32
   553  	e = syscall.ReadFile(fd.Sysfd, b, &done, &o)
   554  	if e != nil {
   555  		done = 0
   556  		if e == syscall.ERROR_HANDLE_EOF {
   557  			e = io.EOF
   558  		}
   559  	}
   560  	if len(b) != 0 {
   561  		e = fd.eofError(int(done), e)
   562  	}
   563  	return int(done), e
   564  }
   565  
   566  // ReadFrom wraps the recvfrom network call.
   567  func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
   568  	if len(buf) == 0 {
   569  		return 0, nil, nil
   570  	}
   571  	if len(buf) > maxRW {
   572  		buf = buf[:maxRW]
   573  	}
   574  	if err := fd.readLock(); err != nil {
   575  		return 0, nil, err
   576  	}
   577  	defer fd.readUnlock()
   578  	o := &fd.rop
   579  	o.InitBuf(buf)
   580  	n, err := execIO(o, func(o *operation) error {
   581  		if o.rsa == nil {
   582  			o.rsa = new(syscall.RawSockaddrAny)
   583  		}
   584  		o.rsan = int32(unsafe.Sizeof(*o.rsa))
   585  		return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
   586  	})
   587  	err = fd.eofError(n, err)
   588  	if err != nil {
   589  		return n, nil, err
   590  	}
   591  	sa, _ := o.rsa.Sockaddr()
   592  	return n, sa, nil
   593  }
   594  
   595  // ReadFromInet4 wraps the recvfrom network call for IPv4.
   596  func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
   597  	if len(buf) == 0 {
   598  		return 0, nil
   599  	}
   600  	if len(buf) > maxRW {
   601  		buf = buf[:maxRW]
   602  	}
   603  	if err := fd.readLock(); err != nil {
   604  		return 0, err
   605  	}
   606  	defer fd.readUnlock()
   607  	o := &fd.rop
   608  	o.InitBuf(buf)
   609  	n, err := execIO(o, func(o *operation) error {
   610  		if o.rsa == nil {
   611  			o.rsa = new(syscall.RawSockaddrAny)
   612  		}
   613  		o.rsan = int32(unsafe.Sizeof(*o.rsa))
   614  		return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
   615  	})
   616  	err = fd.eofError(n, err)
   617  	if err != nil {
   618  		return n, err
   619  	}
   620  	rawToSockaddrInet4(o.rsa, sa4)
   621  	return n, err
   622  }
   623  
   624  // ReadFromInet6 wraps the recvfrom network call for IPv6.
   625  func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
   626  	if len(buf) == 0 {
   627  		return 0, nil
   628  	}
   629  	if len(buf) > maxRW {
   630  		buf = buf[:maxRW]
   631  	}
   632  	if err := fd.readLock(); err != nil {
   633  		return 0, err
   634  	}
   635  	defer fd.readUnlock()
   636  	o := &fd.rop
   637  	o.InitBuf(buf)
   638  	n, err := execIO(o, func(o *operation) error {
   639  		if o.rsa == nil {
   640  			o.rsa = new(syscall.RawSockaddrAny)
   641  		}
   642  		o.rsan = int32(unsafe.Sizeof(*o.rsa))
   643  		return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
   644  	})
   645  	err = fd.eofError(n, err)
   646  	if err != nil {
   647  		return n, err
   648  	}
   649  	rawToSockaddrInet6(o.rsa, sa6)
   650  	return n, err
   651  }
   652  
   653  // Write implements io.Writer.
   654  func (fd *FD) Write(buf []byte) (int, error) {
   655  	if err := fd.writeLock(); err != nil {
   656  		return 0, err
   657  	}
   658  	defer fd.writeUnlock()
   659  	if fd.isFile {
   660  		fd.l.Lock()
   661  		defer fd.l.Unlock()
   662  	}
   663  
   664  	ntotal := 0
   665  	for len(buf) > 0 {
   666  		b := buf
   667  		if len(b) > maxRW {
   668  			b = b[:maxRW]
   669  		}
   670  		var n int
   671  		var err error
   672  		if fd.isFile {
   673  			switch fd.kind {
   674  			case kindConsole:
   675  				n, err = fd.writeConsole(b)
   676  			default:
   677  				n, err = syscall.Write(fd.Sysfd, b)
   678  				if fd.kind == kindPipe && err == syscall.ERROR_OPERATION_ABORTED {
   679  					// Close uses CancelIoEx to interrupt concurrent I/O for pipes.
   680  					// If the fd is a pipe and the Write was interrupted by CancelIoEx,
   681  					// we assume it is interrupted by Close.
   682  					err = ErrFileClosing
   683  				}
   684  			}
   685  			if err != nil {
   686  				n = 0
   687  			}
   688  		} else {
   689  			if race.Enabled {
   690  				race.ReleaseMerge(unsafe.Pointer(&ioSync))
   691  			}
   692  			o := &fd.wop
   693  			o.InitBuf(b)
   694  			n, err = execIO(o, func(o *operation) error {
   695  				return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
   696  			})
   697  		}
   698  		ntotal += n
   699  		if err != nil {
   700  			return ntotal, err
   701  		}
   702  		buf = buf[n:]
   703  	}
   704  	return ntotal, nil
   705  }
   706  
   707  // writeConsole writes len(b) bytes to the console File.
   708  // It returns the number of bytes written and an error, if any.
   709  func (fd *FD) writeConsole(b []byte) (int, error) {
   710  	n := len(b)
   711  	runes := make([]rune, 0, 256)
   712  	if len(fd.lastbits) > 0 {
   713  		b = append(fd.lastbits, b...)
   714  		fd.lastbits = nil
   715  
   716  	}
   717  	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
   718  		r, l := utf8.DecodeRune(b)
   719  		runes = append(runes, r)
   720  		b = b[l:]
   721  	}
   722  	if len(b) > 0 {
   723  		fd.lastbits = make([]byte, len(b))
   724  		copy(fd.lastbits, b)
   725  	}
   726  	// syscall.WriteConsole seems to fail, if given large buffer.
   727  	// So limit the buffer to 16000 characters. This number was
   728  	// discovered by experimenting with syscall.WriteConsole.
   729  	const maxWrite = 16000
   730  	for len(runes) > 0 {
   731  		m := len(runes)
   732  		if m > maxWrite {
   733  			m = maxWrite
   734  		}
   735  		chunk := runes[:m]
   736  		runes = runes[m:]
   737  		uint16s := utf16.Encode(chunk)
   738  		for len(uint16s) > 0 {
   739  			var written uint32
   740  			err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
   741  			if err != nil {
   742  				return 0, err
   743  			}
   744  			uint16s = uint16s[written:]
   745  		}
   746  	}
   747  	return n, nil
   748  }
   749  
   750  // Pwrite emulates the Unix pwrite system call.
   751  func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
   752  	if fd.kind == kindPipe {
   753  		// Pwrite does not work with pipes
   754  		return 0, syscall.ESPIPE
   755  	}
   756  	// Call incref, not writeLock, because since pwrite specifies the
   757  	// offset it is independent from other writes.
   758  	if err := fd.incref(); err != nil {
   759  		return 0, err
   760  	}
   761  	defer fd.decref()
   762  
   763  	fd.l.Lock()
   764  	defer fd.l.Unlock()
   765  	curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
   766  	if e != nil {
   767  		return 0, e
   768  	}
   769  	defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
   770  
   771  	ntotal := 0
   772  	for len(buf) > 0 {
   773  		b := buf
   774  		if len(b) > maxRW {
   775  			b = b[:maxRW]
   776  		}
   777  		var n uint32
   778  		o := syscall.Overlapped{
   779  			OffsetHigh: uint32(off >> 32),
   780  			Offset:     uint32(off),
   781  		}
   782  		e = syscall.WriteFile(fd.Sysfd, b, &n, &o)
   783  		ntotal += int(n)
   784  		if e != nil {
   785  			return ntotal, e
   786  		}
   787  		buf = buf[n:]
   788  		off += int64(n)
   789  	}
   790  	return ntotal, nil
   791  }
   792  
   793  // Writev emulates the Unix writev system call.
   794  func (fd *FD) Writev(buf *[][]byte) (int64, error) {
   795  	if len(*buf) == 0 {
   796  		return 0, nil
   797  	}
   798  	if err := fd.writeLock(); err != nil {
   799  		return 0, err
   800  	}
   801  	defer fd.writeUnlock()
   802  	if race.Enabled {
   803  		race.ReleaseMerge(unsafe.Pointer(&ioSync))
   804  	}
   805  	o := &fd.wop
   806  	o.InitBufs(buf)
   807  	n, err := execIO(o, func(o *operation) error {
   808  		return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(o.bufs)), &o.qty, 0, &o.o, nil)
   809  	})
   810  	o.ClearBufs()
   811  	TestHookDidWritev(n)
   812  	consume(buf, int64(n))
   813  	return int64(n), err
   814  }
   815  
   816  // WriteTo wraps the sendto network call.
   817  func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
   818  	if err := fd.writeLock(); err != nil {
   819  		return 0, err
   820  	}
   821  	defer fd.writeUnlock()
   822  
   823  	if len(buf) == 0 {
   824  		// handle zero-byte payload
   825  		o := &fd.wop
   826  		o.InitBuf(buf)
   827  		o.sa = sa
   828  		n, err := execIO(o, func(o *operation) error {
   829  			return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
   830  		})
   831  		return n, err
   832  	}
   833  
   834  	ntotal := 0
   835  	for len(buf) > 0 {
   836  		b := buf
   837  		if len(b) > maxRW {
   838  			b = b[:maxRW]
   839  		}
   840  		o := &fd.wop
   841  		o.InitBuf(b)
   842  		o.sa = sa
   843  		n, err := execIO(o, func(o *operation) error {
   844  			return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
   845  		})
   846  		ntotal += int(n)
   847  		if err != nil {
   848  			return ntotal, err
   849  		}
   850  		buf = buf[n:]
   851  	}
   852  	return ntotal, nil
   853  }
   854  
   855  // WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4.
   856  func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
   857  	if err := fd.writeLock(); err != nil {
   858  		return 0, err
   859  	}
   860  	defer fd.writeUnlock()
   861  
   862  	if len(buf) == 0 {
   863  		// handle zero-byte payload
   864  		o := &fd.wop
   865  		o.InitBuf(buf)
   866  		n, err := execIO(o, func(o *operation) error {
   867  			return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
   868  		})
   869  		return n, err
   870  	}
   871  
   872  	ntotal := 0
   873  	for len(buf) > 0 {
   874  		b := buf
   875  		if len(b) > maxRW {
   876  			b = b[:maxRW]
   877  		}
   878  		o := &fd.wop
   879  		o.InitBuf(b)
   880  		n, err := execIO(o, func(o *operation) error {
   881  			return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
   882  		})
   883  		ntotal += int(n)
   884  		if err != nil {
   885  			return ntotal, err
   886  		}
   887  		buf = buf[n:]
   888  	}
   889  	return ntotal, nil
   890  }
   891  
   892  // WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6.
   893  func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
   894  	if err := fd.writeLock(); err != nil {
   895  		return 0, err
   896  	}
   897  	defer fd.writeUnlock()
   898  
   899  	if len(buf) == 0 {
   900  		// handle zero-byte payload
   901  		o := &fd.wop
   902  		o.InitBuf(buf)
   903  		n, err := execIO(o, func(o *operation) error {
   904  			return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
   905  		})
   906  		return n, err
   907  	}
   908  
   909  	ntotal := 0
   910  	for len(buf) > 0 {
   911  		b := buf
   912  		if len(b) > maxRW {
   913  			b = b[:maxRW]
   914  		}
   915  		o := &fd.wop
   916  		o.InitBuf(b)
   917  		n, err := execIO(o, func(o *operation) error {
   918  			return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
   919  		})
   920  		ntotal += int(n)
   921  		if err != nil {
   922  			return ntotal, err
   923  		}
   924  		buf = buf[n:]
   925  	}
   926  	return ntotal, nil
   927  }
   928  
   929  // Call ConnectEx. This doesn't need any locking, since it is only
   930  // called when the descriptor is first created. This is here rather
   931  // than in the net package so that it can use fd.wop.
   932  func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
   933  	o := &fd.wop
   934  	o.sa = ra
   935  	_, err := execIO(o, func(o *operation) error {
   936  		return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o)
   937  	})
   938  	return err
   939  }
   940  
   941  func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) {
   942  	// Submit accept request.
   943  	o.handle = s
   944  	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
   945  	_, err := execIO(o, func(o *operation) error {
   946  		return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
   947  	})
   948  	if err != nil {
   949  		CloseFunc(s)
   950  		return "acceptex", err
   951  	}
   952  
   953  	// Inherit properties of the listening socket.
   954  	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
   955  	if err != nil {
   956  		CloseFunc(s)
   957  		return "setsockopt", err
   958  	}
   959  
   960  	return "", nil
   961  }
   962  
   963  // Accept handles accepting a socket. The sysSocket parameter is used
   964  // to allocate the net socket.
   965  func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) {
   966  	if err := fd.readLock(); err != nil {
   967  		return syscall.InvalidHandle, nil, 0, "", err
   968  	}
   969  	defer fd.readUnlock()
   970  
   971  	o := &fd.rop
   972  	var rawsa [2]syscall.RawSockaddrAny
   973  	for {
   974  		s, err := sysSocket()
   975  		if err != nil {
   976  			return syscall.InvalidHandle, nil, 0, "", err
   977  		}
   978  
   979  		errcall, err := fd.acceptOne(s, rawsa[:], o)
   980  		if err == nil {
   981  			return s, rawsa[:], uint32(o.rsan), "", nil
   982  		}
   983  
   984  		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
   985  		// returned here. These happen if connection reset is received
   986  		// before AcceptEx could complete. These errors relate to new
   987  		// connection, not to AcceptEx, so ignore broken connection and
   988  		// try AcceptEx again for more connections.
   989  		errno, ok := err.(syscall.Errno)
   990  		if !ok {
   991  			return syscall.InvalidHandle, nil, 0, errcall, err
   992  		}
   993  		switch errno {
   994  		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
   995  			// ignore these and try again
   996  		default:
   997  			return syscall.InvalidHandle, nil, 0, errcall, err
   998  		}
   999  	}
  1000  }
  1001  
  1002  // Seek wraps syscall.Seek.
  1003  func (fd *FD) Seek(offset int64, whence int) (int64, error) {
  1004  	if fd.kind == kindPipe {
  1005  		return 0, syscall.ESPIPE
  1006  	}
  1007  	if err := fd.incref(); err != nil {
  1008  		return 0, err
  1009  	}
  1010  	defer fd.decref()
  1011  
  1012  	fd.l.Lock()
  1013  	defer fd.l.Unlock()
  1014  
  1015  	return syscall.Seek(fd.Sysfd, offset, whence)
  1016  }
  1017  
  1018  // Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
  1019  func (fd *FD) Fchmod(mode uint32) error {
  1020  	if err := fd.incref(); err != nil {
  1021  		return err
  1022  	}
  1023  	defer fd.decref()
  1024  
  1025  	var d syscall.ByHandleFileInformation
  1026  	if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
  1027  		return err
  1028  	}
  1029  	attrs := d.FileAttributes
  1030  	if mode&syscall.S_IWRITE != 0 {
  1031  		attrs &^= syscall.FILE_ATTRIBUTE_READONLY
  1032  	} else {
  1033  		attrs |= syscall.FILE_ATTRIBUTE_READONLY
  1034  	}
  1035  	if attrs == d.FileAttributes {
  1036  		return nil
  1037  	}
  1038  
  1039  	var du windows.FILE_BASIC_INFO
  1040  	du.FileAttributes = attrs
  1041  	return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du)))
  1042  }
  1043  
  1044  // Fchdir wraps syscall.Fchdir.
  1045  func (fd *FD) Fchdir() error {
  1046  	if err := fd.incref(); err != nil {
  1047  		return err
  1048  	}
  1049  	defer fd.decref()
  1050  	return syscall.Fchdir(fd.Sysfd)
  1051  }
  1052  
  1053  // GetFileType wraps syscall.GetFileType.
  1054  func (fd *FD) GetFileType() (uint32, error) {
  1055  	if err := fd.incref(); err != nil {
  1056  		return 0, err
  1057  	}
  1058  	defer fd.decref()
  1059  	return syscall.GetFileType(fd.Sysfd)
  1060  }
  1061  
  1062  // GetFileInformationByHandle wraps GetFileInformationByHandle.
  1063  func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
  1064  	if err := fd.incref(); err != nil {
  1065  		return err
  1066  	}
  1067  	defer fd.decref()
  1068  	return syscall.GetFileInformationByHandle(fd.Sysfd, data)
  1069  }
  1070  
  1071  // RawRead invokes the user-defined function f for a read operation.
  1072  func (fd *FD) RawRead(f func(uintptr) bool) error {
  1073  	if err := fd.readLock(); err != nil {
  1074  		return err
  1075  	}
  1076  	defer fd.readUnlock()
  1077  	for {
  1078  		if f(uintptr(fd.Sysfd)) {
  1079  			return nil
  1080  		}
  1081  
  1082  		// Use a zero-byte read as a way to get notified when this
  1083  		// socket is readable. h/t https://stackoverflow.com/a/42019668/332798
  1084  		o := &fd.rop
  1085  		o.InitBuf(nil)
  1086  		if !fd.IsStream {
  1087  			o.flags |= windows.MSG_PEEK
  1088  		}
  1089  		_, err := execIO(o, func(o *operation) error {
  1090  			return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
  1091  		})
  1092  		if err == windows.WSAEMSGSIZE {
  1093  			// expected with a 0-byte peek, ignore.
  1094  		} else if err != nil {
  1095  			return err
  1096  		}
  1097  	}
  1098  }
  1099  
  1100  // RawWrite invokes the user-defined function f for a write operation.
  1101  func (fd *FD) RawWrite(f func(uintptr) bool) error {
  1102  	if err := fd.writeLock(); err != nil {
  1103  		return err
  1104  	}
  1105  	defer fd.writeUnlock()
  1106  
  1107  	if f(uintptr(fd.Sysfd)) {
  1108  		return nil
  1109  	}
  1110  
  1111  	// TODO(tmm1): find a way to detect socket writability
  1112  	return syscall.EWINDOWS
  1113  }
  1114  
  1115  func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 {
  1116  	*rsa = syscall.RawSockaddrAny{}
  1117  	raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  1118  	raw.Family = syscall.AF_INET
  1119  	p := (*[2]byte)(unsafe.Pointer(&raw.Port))
  1120  	p[0] = byte(sa.Port >> 8)
  1121  	p[1] = byte(sa.Port)
  1122  	raw.Addr = sa.Addr
  1123  	return int32(unsafe.Sizeof(*raw))
  1124  }
  1125  
  1126  func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 {
  1127  	*rsa = syscall.RawSockaddrAny{}
  1128  	raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  1129  	raw.Family = syscall.AF_INET6
  1130  	p := (*[2]byte)(unsafe.Pointer(&raw.Port))
  1131  	p[0] = byte(sa.Port >> 8)
  1132  	p[1] = byte(sa.Port)
  1133  	raw.Scope_id = sa.ZoneId
  1134  	raw.Addr = sa.Addr
  1135  	return int32(unsafe.Sizeof(*raw))
  1136  }
  1137  
  1138  func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
  1139  	pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  1140  	p := (*[2]byte)(unsafe.Pointer(&pp.Port))
  1141  	sa.Port = int(p[0])<<8 + int(p[1])
  1142  	sa.Addr = pp.Addr
  1143  }
  1144  
  1145  func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
  1146  	pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  1147  	p := (*[2]byte)(unsafe.Pointer(&pp.Port))
  1148  	sa.Port = int(p[0])<<8 + int(p[1])
  1149  	sa.ZoneId = pp.Scope_id
  1150  	sa.Addr = pp.Addr
  1151  }
  1152  
  1153  func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) {
  1154  	switch sa := sa.(type) {
  1155  	case *syscall.SockaddrInet4:
  1156  		sz := sockaddrInet4ToRaw(rsa, sa)
  1157  		return sz, nil
  1158  	case *syscall.SockaddrInet6:
  1159  		sz := sockaddrInet6ToRaw(rsa, sa)
  1160  		return sz, nil
  1161  	default:
  1162  		return 0, syscall.EWINDOWS
  1163  	}
  1164  }
  1165  
  1166  // ReadMsg wraps the WSARecvMsg network call.
  1167  func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
  1168  	if err := fd.readLock(); err != nil {
  1169  		return 0, 0, 0, nil, err
  1170  	}
  1171  	defer fd.readUnlock()
  1172  
  1173  	if len(p) > maxRW {
  1174  		p = p[:maxRW]
  1175  	}
  1176  
  1177  	o := &fd.rop
  1178  	o.InitMsg(p, oob)
  1179  	if o.rsa == nil {
  1180  		o.rsa = new(syscall.RawSockaddrAny)
  1181  	}
  1182  	o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1183  	o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
  1184  	o.msg.Flags = uint32(flags)
  1185  	n, err := execIO(o, func(o *operation) error {
  1186  		return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
  1187  	})
  1188  	err = fd.eofError(n, err)
  1189  	var sa syscall.Sockaddr
  1190  	if err == nil {
  1191  		sa, err = o.rsa.Sockaddr()
  1192  	}
  1193  	return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err
  1194  }
  1195  
  1196  // ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4.
  1197  func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
  1198  	if err := fd.readLock(); err != nil {
  1199  		return 0, 0, 0, err
  1200  	}
  1201  	defer fd.readUnlock()
  1202  
  1203  	if len(p) > maxRW {
  1204  		p = p[:maxRW]
  1205  	}
  1206  
  1207  	o := &fd.rop
  1208  	o.InitMsg(p, oob)
  1209  	if o.rsa == nil {
  1210  		o.rsa = new(syscall.RawSockaddrAny)
  1211  	}
  1212  	o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1213  	o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
  1214  	o.msg.Flags = uint32(flags)
  1215  	n, err := execIO(o, func(o *operation) error {
  1216  		return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
  1217  	})
  1218  	err = fd.eofError(n, err)
  1219  	if err == nil {
  1220  		rawToSockaddrInet4(o.rsa, sa4)
  1221  	}
  1222  	return n, int(o.msg.Control.Len), int(o.msg.Flags), err
  1223  }
  1224  
  1225  // ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6.
  1226  func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
  1227  	if err := fd.readLock(); err != nil {
  1228  		return 0, 0, 0, err
  1229  	}
  1230  	defer fd.readUnlock()
  1231  
  1232  	if len(p) > maxRW {
  1233  		p = p[:maxRW]
  1234  	}
  1235  
  1236  	o := &fd.rop
  1237  	o.InitMsg(p, oob)
  1238  	if o.rsa == nil {
  1239  		o.rsa = new(syscall.RawSockaddrAny)
  1240  	}
  1241  	o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1242  	o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
  1243  	o.msg.Flags = uint32(flags)
  1244  	n, err := execIO(o, func(o *operation) error {
  1245  		return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
  1246  	})
  1247  	err = fd.eofError(n, err)
  1248  	if err == nil {
  1249  		rawToSockaddrInet6(o.rsa, sa6)
  1250  	}
  1251  	return n, int(o.msg.Control.Len), int(o.msg.Flags), err
  1252  }
  1253  
  1254  // WriteMsg wraps the WSASendMsg network call.
  1255  func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
  1256  	if len(p) > maxRW {
  1257  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1258  	}
  1259  
  1260  	if err := fd.writeLock(); err != nil {
  1261  		return 0, 0, err
  1262  	}
  1263  	defer fd.writeUnlock()
  1264  
  1265  	o := &fd.wop
  1266  	o.InitMsg(p, oob)
  1267  	if sa != nil {
  1268  		if o.rsa == nil {
  1269  			o.rsa = new(syscall.RawSockaddrAny)
  1270  		}
  1271  		len, err := sockaddrToRaw(o.rsa, sa)
  1272  		if err != nil {
  1273  			return 0, 0, err
  1274  		}
  1275  		o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1276  		o.msg.Namelen = len
  1277  	}
  1278  	n, err := execIO(o, func(o *operation) error {
  1279  		return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
  1280  	})
  1281  	return n, int(o.msg.Control.Len), err
  1282  }
  1283  
  1284  // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
  1285  func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
  1286  	if len(p) > maxRW {
  1287  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1288  	}
  1289  
  1290  	if err := fd.writeLock(); err != nil {
  1291  		return 0, 0, err
  1292  	}
  1293  	defer fd.writeUnlock()
  1294  
  1295  	o := &fd.wop
  1296  	o.InitMsg(p, oob)
  1297  	if o.rsa == nil {
  1298  		o.rsa = new(syscall.RawSockaddrAny)
  1299  	}
  1300  	len := sockaddrInet4ToRaw(o.rsa, sa)
  1301  	o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1302  	o.msg.Namelen = len
  1303  	n, err := execIO(o, func(o *operation) error {
  1304  		return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
  1305  	})
  1306  	return n, int(o.msg.Control.Len), err
  1307  }
  1308  
  1309  // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
  1310  func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
  1311  	if len(p) > maxRW {
  1312  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1313  	}
  1314  
  1315  	if err := fd.writeLock(); err != nil {
  1316  		return 0, 0, err
  1317  	}
  1318  	defer fd.writeUnlock()
  1319  
  1320  	o := &fd.wop
  1321  	o.InitMsg(p, oob)
  1322  	if o.rsa == nil {
  1323  		o.rsa = new(syscall.RawSockaddrAny)
  1324  	}
  1325  	len := sockaddrInet6ToRaw(o.rsa, sa)
  1326  	o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
  1327  	o.msg.Namelen = len
  1328  	n, err := execIO(o, func(o *operation) error {
  1329  		return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
  1330  	})
  1331  	return n, int(o.msg.Control.Len), err
  1332  }