Source file src/internal/poll/fd_windows.go

     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  	"internal/race"
    10  	"internal/syscall/windows"
    11  	"io"
    12  	"runtime"
    13  	"sync"
    14  	"sync/atomic"
    15  	"syscall"
    16  	"unicode/utf16"
    17  	"unicode/utf8"
    18  	"unsafe"
    19  )
    20  
    21  var (
    22  	initErr error
    23  	ioSync  uint64
    24  )
    25  
    26  // ifsHandlesOnly returns true if the system only has IFS handles for TCP sockets.
    27  // See https://support.microsoft.com/kb/2568167 for details.
    28  var ifsHandlesOnly = sync.OnceValue(func() bool {
    29  	protos := [2]int32{syscall.IPPROTO_TCP, 0}
    30  	var buf [32]syscall.WSAProtocolInfo
    31  	len := uint32(unsafe.Sizeof(buf))
    32  	n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
    33  	if err != nil {
    34  		return false
    35  	}
    36  	for i := range n {
    37  		if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
    38  			return false
    39  		}
    40  	}
    41  	return true
    42  })
    43  
    44  // canSkipCompletionPortOnSuccess returns true if we use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS for the given handle.
    45  // See https://support.microsoft.com/kb/2568167 for details.
    46  func canSkipCompletionPortOnSuccess(h syscall.Handle, isSocket bool) bool {
    47  	if !isSocket {
    48  		// Non-socket handles can use SetFileCompletionNotificationModes without problems.
    49  		return true
    50  	}
    51  	if ifsHandlesOnly() {
    52  		// If the system only has IFS handles for TCP sockets, then there is nothing else to check.
    53  		return true
    54  	}
    55  	var info syscall.WSAProtocolInfo
    56  	size := int32(unsafe.Sizeof(info))
    57  	if syscall.Getsockopt(h, syscall.SOL_SOCKET, windows.SO_PROTOCOL_INFOW, (*byte)(unsafe.Pointer(&info)), &size) != nil {
    58  		return false
    59  	}
    60  	return info.ServiceFlags1&syscall.XP1_IFS_HANDLES != 0
    61  }
    62  
    63  // InitWSA initiates the use of the Winsock DLL by the current process.
    64  // It is called from the net package at init time to avoid
    65  // loading ws2_32.dll when net is not used.
    66  var InitWSA = sync.OnceFunc(func() {
    67  	var d syscall.WSAData
    68  	e := syscall.WSAStartup(uint32(0x202), &d)
    69  	if e != nil {
    70  		initErr = e
    71  	}
    72  })
    73  
    74  // operation contains superset of data necessary to perform all async IO.
    75  type operation struct {
    76  	// Used by IOCP interface, it must be first field
    77  	// of the struct, as our code relies on it.
    78  	o syscall.Overlapped
    79  
    80  	// fields used by runtime.netpoll
    81  	runtimeCtx uintptr
    82  	mode       int32
    83  }
    84  
    85  func (o *operation) setOffset(off int64) {
    86  	o.o.OffsetHigh = uint32(off >> 32)
    87  	o.o.Offset = uint32(off)
    88  }
    89  
    90  func (fd *FD) overlapped(o *operation) *syscall.Overlapped {
    91  	if fd.isBlocking {
    92  		// Don't return the overlapped object if the file handle
    93  		// doesn't use overlapped I/O. It could be used, but
    94  		// that would then use the file pointer stored in the
    95  		// overlapped object rather than the real file pointer.
    96  		return nil
    97  	}
    98  	return &o.o
    99  }
   100  
   101  func newWsaBuf(b []byte) *syscall.WSABuf {
   102  	return &syscall.WSABuf{Buf: unsafe.SliceData(b), Len: uint32(len(b))}
   103  }
   104  
   105  var wsaBufsPool = sync.Pool{
   106  	New: func() any {
   107  		buf := make([]syscall.WSABuf, 0, 16)
   108  		return &buf
   109  	},
   110  }
   111  
   112  func newWSABufs(buf *[][]byte) *[]syscall.WSABuf {
   113  	bufsPtr := wsaBufsPool.Get().(*[]syscall.WSABuf)
   114  	*bufsPtr = (*bufsPtr)[:0]
   115  	for _, b := range *buf {
   116  		if len(b) == 0 {
   117  			*bufsPtr = append(*bufsPtr, syscall.WSABuf{})
   118  			continue
   119  		}
   120  		for len(b) > maxRW {
   121  			*bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
   122  			b = b[maxRW:]
   123  		}
   124  		if len(b) > 0 {
   125  			*bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
   126  		}
   127  	}
   128  	return bufsPtr
   129  }
   130  
   131  func freeWSABufs(bufsPtr *[]syscall.WSABuf) {
   132  	// Clear pointers to buffers so they can be released by garbage collector.
   133  	bufs := *bufsPtr
   134  	for i := range bufs {
   135  		bufs[i].Buf = nil
   136  	}
   137  	// Proper usage of a sync.Pool requires each entry to have approximately
   138  	// the same memory cost. To obtain this property when the stored type
   139  	// contains a variably-sized buffer, we add a hard limit on the maximum buffer
   140  	// to place back in the pool.
   141  	//
   142  	// See https://go.dev/issue/23199
   143  	if cap(*bufsPtr) > 128 {
   144  		*bufsPtr = nil
   145  	}
   146  	wsaBufsPool.Put(bufsPtr)
   147  }
   148  
   149  // wsaMsgPool is a pool of WSAMsg structures that can only hold a single WSABuf.
   150  var wsaMsgPool = sync.Pool{
   151  	New: func() any {
   152  		return &windows.WSAMsg{
   153  			Buffers:     &syscall.WSABuf{},
   154  			BufferCount: 1,
   155  		}
   156  	},
   157  }
   158  
   159  // newWSAMsg creates a new WSAMsg with the provided parameters.
   160  // Use [freeWSAMsg] to free it.
   161  func newWSAMsg(p []byte, oob []byte, flags int, unconnected bool) *windows.WSAMsg {
   162  	// The returned object can't be allocated in the stack because it is accessed asynchronously
   163  	// by Windows in between several system calls. If the stack frame is moved while that happens,
   164  	// then Windows may access invalid memory.
   165  	// TODO(qmuntal): investigate using runtime.Pinner keeping this path allocation-free.
   166  
   167  	// Use a pool to reuse allocations.
   168  	msg := wsaMsgPool.Get().(*windows.WSAMsg)
   169  	msg.Buffers.Len = uint32(len(p))
   170  	msg.Buffers.Buf = unsafe.SliceData(p)
   171  	msg.Control = syscall.WSABuf{
   172  		Len: uint32(len(oob)),
   173  		Buf: unsafe.SliceData(oob),
   174  	}
   175  	msg.Flags = uint32(flags)
   176  	if unconnected {
   177  		msg.Name = wsaRsaPool.Get().(*syscall.RawSockaddrAny)
   178  		msg.Namelen = int32(unsafe.Sizeof(syscall.RawSockaddrAny{}))
   179  	}
   180  	return msg
   181  }
   182  
   183  func freeWSAMsg(msg *windows.WSAMsg) {
   184  	// Clear pointers to buffers so they can be released by garbage collector.
   185  	msg.Buffers.Len = 0
   186  	msg.Buffers.Buf = nil
   187  	msg.Control.Len = 0
   188  	msg.Control.Buf = nil
   189  	if msg.Name != nil {
   190  		*msg.Name = syscall.RawSockaddrAny{}
   191  		wsaRsaPool.Put(msg.Name)
   192  		msg.Name = nil
   193  		msg.Namelen = 0
   194  	}
   195  	wsaMsgPool.Put(msg)
   196  }
   197  
   198  var wsaRsaPool = sync.Pool{
   199  	New: func() any {
   200  		return new(syscall.RawSockaddrAny)
   201  	},
   202  }
   203  
   204  var operationPool = sync.Pool{
   205  	New: func() any {
   206  		return new(operation)
   207  	},
   208  }
   209  
   210  // waitIO waits for the IO operation to complete,
   211  // handling cancellation if necessary.
   212  func (fd *FD) waitIO(o *operation) error {
   213  	if o.o.HEvent != 0 {
   214  		// The overlapped handle is not added to the runtime poller,
   215  		// the only way to wait for the IO to complete is block until
   216  		// the overlapped event is signaled.
   217  		_, err := syscall.WaitForSingleObject(o.o.HEvent, syscall.INFINITE)
   218  		return err
   219  	}
   220  	// Wait for our request to complete.
   221  	err := fd.pd.wait(int(o.mode), fd.isFile)
   222  	switch err {
   223  	case nil:
   224  		// IO completed successfully.
   225  	case ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
   226  		// IO interrupted by "close" or "timeout", cancel our request.
   227  		// ERROR_NOT_FOUND can be returned when the request succeded
   228  		// between the time wait returned and CancelIoEx was executed.
   229  		if err := syscall.CancelIoEx(fd.Sysfd, &o.o); err != nil && err != syscall.ERROR_NOT_FOUND {
   230  			// TODO(brainman): maybe do something else, but panic.
   231  			panic(err)
   232  		}
   233  		fd.pd.waitCanceled(int(o.mode))
   234  	default:
   235  		// No other error is expected.
   236  		panic("unexpected runtime.netpoll error: " + err.Error())
   237  	}
   238  	return err
   239  }
   240  
   241  // execIO executes a single IO operation o.
   242  // It supports both synchronous and asynchronous IO.
   243  // buf, if not nil, will be pinned during the lifetime of the operation.
   244  func (fd *FD) execIO(mode int, submit func(o *operation) (uint32, error), buf []byte) (int, error) {
   245  	// Notify runtime netpoll about starting IO.
   246  	err := fd.pd.prepare(mode, fd.isFile)
   247  	if err != nil {
   248  		return 0, err
   249  	}
   250  	o := operationPool.Get().(*operation)
   251  	defer operationPool.Put(o)
   252  	*o = operation{
   253  		runtimeCtx: fd.pd.runtimeCtx,
   254  		mode:       int32(mode),
   255  	}
   256  	o.setOffset(fd.offset)
   257  	if !fd.isBlocking {
   258  		if len(buf) > 0 {
   259  			ptr := unsafe.SliceData(buf)
   260  			if mode == 'r' {
   261  				fd.readPinner.Pin(ptr)
   262  			} else {
   263  				fd.writePinner.Pin(ptr)
   264  			}
   265  			defer func() {
   266  				if mode == 'r' {
   267  					fd.readPinner.Unpin()
   268  				} else {
   269  					fd.writePinner.Unpin()
   270  				}
   271  			}()
   272  		}
   273  		if !fd.pollable() {
   274  			// If the handle is opened for overlapped IO but we can't
   275  			// use the runtime poller, then we need to use an
   276  			// event to wait for the IO to complete.
   277  			h, err := windows.CreateEvent(nil, 0, 0, nil)
   278  			if err != nil {
   279  				// This shouldn't happen when all CreateEvent arguments are zero.
   280  				panic(err)
   281  			}
   282  			// Set the low bit so that the external IOCP doesn't receive the completion packet.
   283  			o.o.HEvent = h | 1
   284  			defer syscall.CloseHandle(h)
   285  		}
   286  	}
   287  	// Start IO.
   288  	qty, err := submit(o)
   289  	var waitErr error
   290  	// Blocking operations shouldn't return ERROR_IO_PENDING.
   291  	// Continue without waiting if that happens.
   292  	if !fd.isBlocking && (err == syscall.ERROR_IO_PENDING || (err == nil && fd.waitOnSuccess)) {
   293  		// IO started asynchronously or completed synchronously but
   294  		// a sync notification is required. Wait for it to complete.
   295  		waitErr = fd.waitIO(o)
   296  		if fd.isFile {
   297  			err = windows.GetOverlappedResult(fd.Sysfd, &o.o, &qty, false)
   298  		} else {
   299  			var flags uint32
   300  			err = windows.WSAGetOverlappedResult(fd.Sysfd, &o.o, &qty, false, &flags)
   301  		}
   302  	}
   303  	switch err {
   304  	case syscall.ERROR_OPERATION_ABORTED:
   305  		// ERROR_OPERATION_ABORTED may have been caused by us. In that case,
   306  		// map it to our own error. Don't do more than that, each submitted
   307  		// function may have its own meaning for each error.
   308  		if waitErr != nil {
   309  			// IO canceled by the poller while waiting for completion.
   310  			err = waitErr
   311  		} else if fd.kind == kindPipe && fd.closing() {
   312  			// Close uses CancelIoEx to interrupt concurrent I/O for pipes.
   313  			// If the fd is a pipe and the Write was interrupted by CancelIoEx,
   314  			// we assume it is interrupted by Close.
   315  			err = errClosing(fd.isFile)
   316  		}
   317  	case windows.ERROR_IO_INCOMPLETE:
   318  		// waitIO couldn't wait for the IO to complete.
   319  		if waitErr != nil {
   320  			// The wait error will be more informative.
   321  			err = waitErr
   322  		}
   323  	}
   324  	return int(qty), err
   325  }
   326  
   327  // FD is a file descriptor. The net and os packages embed this type in
   328  // a larger type representing a network connection or OS file.
   329  type FD struct {
   330  	// Lock sysfd and serialize access to Read and Write methods.
   331  	fdmu fdMutex
   332  
   333  	// System file descriptor. Immutable until Close.
   334  	Sysfd syscall.Handle
   335  
   336  	// I/O poller.
   337  	pd pollDesc
   338  
   339  	// The file offset for the next read or write.
   340  	// Overlapped IO operations don't use the real file pointer,
   341  	// so we need to keep track of the offset ourselves.
   342  	offset int64
   343  
   344  	// For console I/O.
   345  	lastbits       []byte   // first few bytes of the last incomplete rune in last write
   346  	readuint16     []uint16 // buffer to hold uint16s obtained with ReadConsole
   347  	readbyte       []byte   // buffer to hold decoding of readuint16 from utf16 to utf8
   348  	readbyteOffset int      // readbyte[readOffset:] is yet to be consumed with file.Read
   349  
   350  	// Semaphore signaled when file is closed.
   351  	csema uint32
   352  
   353  	// Don't wait from completion port notifications for successful
   354  	// operations that complete synchronously.
   355  	waitOnSuccess bool
   356  
   357  	// Whether this is a streaming descriptor, as opposed to a
   358  	// packet-based descriptor like a UDP socket.
   359  	IsStream bool
   360  
   361  	// Whether a zero byte read indicates EOF. This is false for a
   362  	// message based socket connection.
   363  	ZeroReadIsEOF bool
   364  
   365  	// Whether the handle is owned by os.File.
   366  	isFile bool
   367  
   368  	// The kind of this file.
   369  	kind fileKind
   370  
   371  	// Whether FILE_FLAG_OVERLAPPED was not set when opening the file.
   372  	isBlocking bool
   373  
   374  	disassociated atomic.Bool
   375  
   376  	// readPinner and writePinner are automatically unpinned
   377  	// before execIO returns.
   378  	readPinner  runtime.Pinner
   379  	writePinner runtime.Pinner
   380  }
   381  
   382  // setOffset sets the offset fields of the overlapped object
   383  // to the given offset. The fd read/write lock must be held.
   384  //
   385  // Overlapped IO operations don't update the offset fields
   386  // of the overlapped object nor the file pointer automatically,
   387  // so we do that manually here.
   388  // Note that this is a best effort that only works if the file
   389  // pointer is completely owned by this operation. We could
   390  // call seek to allow other processes or other operations on the
   391  // same file to see the updated offset. That would be inefficient
   392  // and won't work for concurrent operations anyway. If concurrent
   393  // operations are needed, then the caller should serialize them
   394  // using an external mechanism.
   395  func (fd *FD) setOffset(off int64) {
   396  	fd.offset = off
   397  }
   398  
   399  // addOffset adds the given offset to the current offset.
   400  func (fd *FD) addOffset(off int) {
   401  	fd.offset += int64(off)
   402  }
   403  
   404  // pollable should be used instead of fd.pd.pollable(),
   405  // as it is aware of the disassociated state.
   406  func (fd *FD) pollable() bool {
   407  	return fd.pd.pollable() && !fd.disassociated.Load()
   408  }
   409  
   410  // fileKind describes the kind of file.
   411  type fileKind byte
   412  
   413  const (
   414  	kindNet fileKind = iota
   415  	kindFile
   416  	kindConsole
   417  	kindPipe
   418  )
   419  
   420  // Init initializes the FD. The Sysfd field should already be set.
   421  // This can be called multiple times on a single FD.
   422  // The net argument is a network name from the net package (e.g., "tcp"),
   423  // or "file" or "console" or "dir".
   424  // Set pollable to true if fd should be managed by runtime netpoll.
   425  // Pollable must be set to true for overlapped fds.
   426  func (fd *FD) Init(net string, pollable bool) error {
   427  	if initErr != nil {
   428  		return initErr
   429  	}
   430  
   431  	switch net {
   432  	case "file":
   433  		fd.kind = kindFile
   434  	case "console":
   435  		fd.kind = kindConsole
   436  	case "pipe":
   437  		fd.kind = kindPipe
   438  	default:
   439  		// We don't actually care about the various network types.
   440  		fd.kind = kindNet
   441  	}
   442  	fd.isFile = fd.kind != kindNet
   443  	fd.isBlocking = !pollable
   444  
   445  	if !pollable {
   446  		return nil
   447  	}
   448  
   449  	// The default behavior of the Windows I/O manager is to queue a completion
   450  	// port entry for successful operations that complete synchronously when
   451  	// the handle is opened for overlapped I/O. We will try to disable that
   452  	// behavior below, as it requires an extra syscall.
   453  	fd.waitOnSuccess = true
   454  
   455  	// It is safe to add overlapped handles that also perform I/O
   456  	// outside of the runtime poller. The runtime poller will ignore
   457  	// I/O completion notifications not initiated by us.
   458  	err := fd.pd.init(fd)
   459  	if err != nil {
   460  		return err
   461  	}
   462  
   463  	// FILE_SKIP_SET_EVENT_ON_HANDLE is always safe to use. We don't use that feature
   464  	// and it adds some overhead to the Windows I/O manager.
   465  	// See https://devblogs.microsoft.com/oldnewthing/20200221-00/?p=103466.
   466  	modes := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
   467  	if canSkipCompletionPortOnSuccess(fd.Sysfd, fd.kind == kindNet) {
   468  		modes |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
   469  	}
   470  	if syscall.SetFileCompletionNotificationModes(fd.Sysfd, modes) == nil {
   471  		if modes&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
   472  			fd.waitOnSuccess = false
   473  		}
   474  	}
   475  	return nil
   476  }
   477  
   478  // DisassociateIOCP disassociates the file handle from the IOCP.
   479  // The disassociate operation will not succeed if there is any
   480  // in-progress IO operation on the file handle.
   481  func (fd *FD) DisassociateIOCP() error {
   482  	if err := fd.incref(); err != nil {
   483  		return err
   484  	}
   485  	defer fd.decref()
   486  
   487  	if fd.isBlocking || !fd.pollable() {
   488  		// Nothing to disassociate.
   489  		return nil
   490  	}
   491  
   492  	info := windows.FILE_COMPLETION_INFORMATION{}
   493  	if err := windows.NtSetInformationFile(fd.Sysfd, &windows.IO_STATUS_BLOCK{}, unsafe.Pointer(&info), uint32(unsafe.Sizeof(info)), windows.FileReplaceCompletionInformation); err != nil {
   494  		return err
   495  	}
   496  	fd.disassociated.Store(true)
   497  	// Don't call fd.pd.close(), it would be too racy.
   498  	// There is no harm on leaving fd.pd open until Close is called.
   499  	return nil
   500  }
   501  
   502  func (fd *FD) destroy() error {
   503  	if fd.Sysfd == syscall.InvalidHandle {
   504  		return syscall.EINVAL
   505  	}
   506  	// Poller may want to unregister fd in readiness notification mechanism,
   507  	// so this must be executed before fd.CloseFunc.
   508  	fd.pd.close()
   509  	var err error
   510  	switch fd.kind {
   511  	case kindNet:
   512  		// The net package uses the CloseFunc variable for testing.
   513  		err = CloseFunc(fd.Sysfd)
   514  	default:
   515  		err = syscall.CloseHandle(fd.Sysfd)
   516  	}
   517  	fd.Sysfd = syscall.InvalidHandle
   518  	runtime_Semrelease(&fd.csema)
   519  	return err
   520  }
   521  
   522  // Close closes the FD. The underlying file descriptor is closed by
   523  // the destroy method when there are no remaining references.
   524  func (fd *FD) Close() error {
   525  	if !fd.fdmu.increfAndClose() {
   526  		return errClosing(fd.isFile)
   527  	}
   528  
   529  	if fd.kind == kindPipe {
   530  		syscall.CancelIoEx(fd.Sysfd, nil)
   531  	}
   532  	// unblock pending reader and writer
   533  	fd.pd.evict()
   534  	err := fd.decref()
   535  	// Wait until the descriptor is closed. If this was the only
   536  	// reference, it is already closed.
   537  	runtime_Semacquire(&fd.csema)
   538  	return err
   539  }
   540  
   541  // Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length.
   542  // This prevents us reading blocks larger than 4GB.
   543  // See golang.org/issue/26923.
   544  const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
   545  
   546  // Read implements io.Reader.
   547  func (fd *FD) Read(buf []byte) (int, error) {
   548  	if fd.kind == kindFile {
   549  		if err := fd.readWriteLock(); err != nil {
   550  			return 0, err
   551  		}
   552  		defer fd.readWriteUnlock()
   553  	} else {
   554  		if err := fd.readLock(); err != nil {
   555  			return 0, err
   556  		}
   557  		defer fd.readUnlock()
   558  	}
   559  
   560  	if len(buf) > maxRW {
   561  		buf = buf[:maxRW]
   562  	}
   563  
   564  	var n int
   565  	var err error
   566  	switch fd.kind {
   567  	case kindConsole:
   568  		n, err = fd.readConsole(buf)
   569  	case kindFile, kindPipe:
   570  		n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
   571  			err = syscall.ReadFile(fd.Sysfd, buf, &qty, fd.overlapped(o))
   572  			return qty, err
   573  		}, buf)
   574  		fd.addOffset(n)
   575  		switch err {
   576  		case syscall.ERROR_HANDLE_EOF:
   577  			err = io.EOF
   578  		case syscall.ERROR_BROKEN_PIPE:
   579  			// ReadFile only documents ERROR_BROKEN_PIPE for pipes.
   580  			if fd.kind == kindPipe {
   581  				err = io.EOF
   582  			}
   583  		}
   584  	case kindNet:
   585  		n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
   586  			var flags uint32
   587  			err = syscall.WSARecv(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &o.o, nil)
   588  			return qty, err
   589  		}, buf)
   590  		if race.Enabled {
   591  			race.Acquire(unsafe.Pointer(&ioSync))
   592  		}
   593  	}
   594  	if len(buf) != 0 {
   595  		err = fd.eofError(n, err)
   596  	}
   597  	return n, err
   598  }
   599  
   600  var ReadConsole = syscall.ReadConsole // changed for testing
   601  
   602  // readConsole reads utf16 characters from console File,
   603  // encodes them into utf8 and stores them in buffer b.
   604  // It returns the number of utf8 bytes read and an error, if any.
   605  func (fd *FD) readConsole(b []byte) (int, error) {
   606  	if len(b) == 0 {
   607  		return 0, nil
   608  	}
   609  
   610  	if fd.readuint16 == nil {
   611  		// Note: syscall.ReadConsole fails for very large buffers.
   612  		// The limit is somewhere around (but not exactly) 16384.
   613  		// Stay well below.
   614  		fd.readuint16 = make([]uint16, 0, 10000)
   615  		fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16))
   616  	}
   617  
   618  	for fd.readbyteOffset >= len(fd.readbyte) {
   619  		n := cap(fd.readuint16) - len(fd.readuint16)
   620  		if n > len(b) {
   621  			n = len(b)
   622  		}
   623  		var nw uint32
   624  		err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
   625  		if err != nil {
   626  			return 0, err
   627  		}
   628  		uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
   629  		fd.readuint16 = fd.readuint16[:0]
   630  		buf := fd.readbyte[:0]
   631  		for i := 0; i < len(uint16s); i++ {
   632  			r := rune(uint16s[i])
   633  			if utf16.IsSurrogate(r) {
   634  				if i+1 == len(uint16s) {
   635  					if nw > 0 {
   636  						// Save half surrogate pair for next time.
   637  						fd.readuint16 = fd.readuint16[:1]
   638  						fd.readuint16[0] = uint16(r)
   639  						break
   640  					}
   641  					r = utf8.RuneError
   642  				} else {
   643  					r = utf16.DecodeRune(r, rune(uint16s[i+1]))
   644  					if r != utf8.RuneError {
   645  						i++
   646  					}
   647  				}
   648  			}
   649  			buf = utf8.AppendRune(buf, r)
   650  		}
   651  		fd.readbyte = buf
   652  		fd.readbyteOffset = 0
   653  		if nw == 0 {
   654  			break
   655  		}
   656  	}
   657  
   658  	src := fd.readbyte[fd.readbyteOffset:]
   659  	var i int
   660  	for i = 0; i < len(src) && i < len(b); i++ {
   661  		x := src[i]
   662  		if x == 0x1A { // Ctrl-Z
   663  			if i == 0 {
   664  				fd.readbyteOffset++
   665  			}
   666  			break
   667  		}
   668  		b[i] = x
   669  	}
   670  	fd.readbyteOffset += i
   671  	return i, nil
   672  }
   673  
   674  // Pread emulates the Unix pread system call.
   675  func (fd *FD) Pread(buf []byte, off int64) (int, error) {
   676  	if fd.kind == kindPipe {
   677  		// Pread does not work with pipes
   678  		return 0, syscall.ESPIPE
   679  	}
   680  
   681  	if err := fd.readWriteLock(); err != nil {
   682  		return 0, err
   683  	}
   684  	defer fd.readWriteUnlock()
   685  
   686  	if len(buf) > maxRW {
   687  		buf = buf[:maxRW]
   688  	}
   689  
   690  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
   691  		// Overlapped handles don't have the file pointer updated
   692  		// when performing I/O operations, so there is no need to
   693  		// call Seek to reset the file pointer.
   694  		// Also, some overlapped file handles don't support seeking.
   695  		// See https://go.dev/issues/74951.
   696  		if fd.isBlocking {
   697  			curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
   698  			if err != nil {
   699  				return 0, err
   700  			}
   701  			defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
   702  		}
   703  		o.setOffset(off)
   704  
   705  		err = syscall.ReadFile(fd.Sysfd, buf, &qty, &o.o)
   706  		return qty, err
   707  	}, buf)
   708  	if err == syscall.ERROR_HANDLE_EOF {
   709  		err = io.EOF
   710  	}
   711  	if len(buf) != 0 {
   712  		err = fd.eofError(n, err)
   713  	}
   714  	return n, err
   715  }
   716  
   717  // ReadFrom wraps the recvfrom network call.
   718  func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
   719  	if len(buf) == 0 {
   720  		return 0, nil, nil
   721  	}
   722  	if len(buf) > maxRW {
   723  		buf = buf[:maxRW]
   724  	}
   725  	if err := fd.readLock(); err != nil {
   726  		return 0, nil, err
   727  	}
   728  	defer fd.readUnlock()
   729  
   730  	rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
   731  	defer wsaRsaPool.Put(rsa)
   732  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
   733  		rsan := int32(unsafe.Sizeof(*rsa))
   734  		var flags uint32
   735  		err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
   736  		return qty, err
   737  	}, buf)
   738  	err = fd.eofError(n, err)
   739  	if err != nil {
   740  		return n, nil, err
   741  	}
   742  	sa, _ := rsa.Sockaddr()
   743  	return n, sa, nil
   744  }
   745  
   746  // ReadFromInet4 wraps the recvfrom network call for IPv4.
   747  func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
   748  	if len(buf) == 0 {
   749  		return 0, nil
   750  	}
   751  	if len(buf) > maxRW {
   752  		buf = buf[:maxRW]
   753  	}
   754  	if err := fd.readLock(); err != nil {
   755  		return 0, err
   756  	}
   757  	defer fd.readUnlock()
   758  
   759  	rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
   760  	defer wsaRsaPool.Put(rsa)
   761  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
   762  		rsan := int32(unsafe.Sizeof(*rsa))
   763  		var flags uint32
   764  		err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
   765  		return qty, err
   766  	}, buf)
   767  	err = fd.eofError(n, err)
   768  	if err != nil {
   769  		return n, err
   770  	}
   771  	rawToSockaddrInet4(rsa, sa4)
   772  	return n, err
   773  }
   774  
   775  // ReadFromInet6 wraps the recvfrom network call for IPv6.
   776  func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
   777  	if len(buf) == 0 {
   778  		return 0, nil
   779  	}
   780  	if len(buf) > maxRW {
   781  		buf = buf[:maxRW]
   782  	}
   783  	if err := fd.readLock(); err != nil {
   784  		return 0, err
   785  	}
   786  	defer fd.readUnlock()
   787  
   788  	rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
   789  	defer wsaRsaPool.Put(rsa)
   790  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
   791  		rsan := int32(unsafe.Sizeof(*rsa))
   792  		var flags uint32
   793  		err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
   794  		return qty, err
   795  	}, buf)
   796  	err = fd.eofError(n, err)
   797  	if err != nil {
   798  		return n, err
   799  	}
   800  	rawToSockaddrInet6(rsa, sa6)
   801  	return n, err
   802  }
   803  
   804  // Write implements io.Writer.
   805  func (fd *FD) Write(buf []byte) (int, error) {
   806  	if fd.kind == kindFile {
   807  		if err := fd.readWriteLock(); err != nil {
   808  			return 0, err
   809  		}
   810  		defer fd.readWriteUnlock()
   811  	} else {
   812  		if err := fd.writeLock(); err != nil {
   813  			return 0, err
   814  		}
   815  		defer fd.writeUnlock()
   816  	}
   817  
   818  	var ntotal int
   819  	for {
   820  		max := len(buf)
   821  		if max-ntotal > maxRW {
   822  			max = ntotal + maxRW
   823  		}
   824  		b := buf[ntotal:max]
   825  		var n int
   826  		var err error
   827  		switch fd.kind {
   828  		case kindConsole:
   829  			n, err = fd.writeConsole(b)
   830  		case kindPipe, kindFile:
   831  			n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
   832  				err = syscall.WriteFile(fd.Sysfd, b, &qty, fd.overlapped(o))
   833  				return qty, err
   834  			}, b)
   835  			fd.addOffset(n)
   836  		case kindNet:
   837  			if race.Enabled {
   838  				race.ReleaseMerge(unsafe.Pointer(&ioSync))
   839  			}
   840  			n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
   841  				err = syscall.WSASend(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, &o.o, nil)
   842  				return qty, err
   843  			}, b)
   844  		}
   845  		ntotal += n
   846  		if ntotal == len(buf) || err != nil {
   847  			return ntotal, err
   848  		}
   849  		if n == 0 {
   850  			return ntotal, io.ErrUnexpectedEOF
   851  		}
   852  	}
   853  }
   854  
   855  // writeConsole writes len(b) bytes to the console File.
   856  // It returns the number of bytes written and an error, if any.
   857  func (fd *FD) writeConsole(b []byte) (int, error) {
   858  	n := len(b)
   859  	runes := make([]rune, 0, 256)
   860  	if len(fd.lastbits) > 0 {
   861  		b = append(fd.lastbits, b...)
   862  		fd.lastbits = nil
   863  
   864  	}
   865  	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
   866  		r, l := utf8.DecodeRune(b)
   867  		runes = append(runes, r)
   868  		b = b[l:]
   869  	}
   870  	if len(b) > 0 {
   871  		fd.lastbits = make([]byte, len(b))
   872  		copy(fd.lastbits, b)
   873  	}
   874  	// syscall.WriteConsole seems to fail, if given large buffer.
   875  	// So limit the buffer to 16000 characters. This number was
   876  	// discovered by experimenting with syscall.WriteConsole.
   877  	const maxWrite = 16000
   878  	for len(runes) > 0 {
   879  		m := len(runes)
   880  		if m > maxWrite {
   881  			m = maxWrite
   882  		}
   883  		chunk := runes[:m]
   884  		runes = runes[m:]
   885  		uint16s := utf16.Encode(chunk)
   886  		for len(uint16s) > 0 {
   887  			var written uint32
   888  			err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
   889  			if err != nil {
   890  				return 0, err
   891  			}
   892  			uint16s = uint16s[written:]
   893  		}
   894  	}
   895  	return n, nil
   896  }
   897  
   898  // Pwrite emulates the Unix pwrite system call.
   899  func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
   900  	if fd.kind == kindPipe {
   901  		// Pwrite does not work with pipes
   902  		return 0, syscall.ESPIPE
   903  	}
   904  
   905  	if err := fd.readWriteLock(); err != nil {
   906  		return 0, err
   907  	}
   908  	defer fd.readWriteUnlock()
   909  
   910  	var ntotal int
   911  	for {
   912  		max := len(buf)
   913  		if max-ntotal > maxRW {
   914  			max = ntotal + maxRW
   915  		}
   916  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
   917  			// Overlapped handles don't have the file pointer updated
   918  			// when performing I/O operations, so there is no need to
   919  			// call Seek to reset the file pointer.
   920  			// Also, some overlapped file handles don't support seeking.
   921  			// See https://go.dev/issues/74951.
   922  			if fd.isBlocking {
   923  				curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
   924  				if err != nil {
   925  					return 0, err
   926  				}
   927  				defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
   928  			}
   929  			o.setOffset(off + int64(ntotal))
   930  
   931  			err = syscall.WriteFile(fd.Sysfd, buf[ntotal:max], &qty, &o.o)
   932  			return qty, err
   933  		}, buf[ntotal:max])
   934  		if n > 0 {
   935  			ntotal += n
   936  		}
   937  		if ntotal == len(buf) || err != nil {
   938  			return ntotal, err
   939  		}
   940  		if n == 0 {
   941  			return ntotal, io.ErrUnexpectedEOF
   942  		}
   943  	}
   944  }
   945  
   946  // Writev emulates the Unix writev system call.
   947  func (fd *FD) Writev(buf *[][]byte) (int64, error) {
   948  	if len(*buf) == 0 {
   949  		return 0, nil
   950  	}
   951  	if err := fd.writeLock(); err != nil {
   952  		return 0, err
   953  	}
   954  	defer fd.writeUnlock()
   955  	if race.Enabled {
   956  		race.ReleaseMerge(unsafe.Pointer(&ioSync))
   957  	}
   958  	bufs := newWSABufs(buf)
   959  	defer freeWSABufs(bufs)
   960  	n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
   961  		err = syscall.WSASend(fd.Sysfd, &(*bufs)[0], uint32(len(*bufs)), &qty, 0, &o.o, nil)
   962  		return qty, err
   963  	}, nil)
   964  	TestHookDidWritev(n)
   965  	consume(buf, int64(n))
   966  	return int64(n), err
   967  }
   968  
   969  // WriteTo wraps the sendto network call.
   970  func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
   971  	if err := fd.writeLock(); err != nil {
   972  		return 0, err
   973  	}
   974  	defer fd.writeUnlock()
   975  
   976  	if len(buf) == 0 {
   977  		// handle zero-byte payload
   978  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
   979  			err = syscall.WSASendto(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa, &o.o, nil)
   980  			return qty, err
   981  		}, nil)
   982  		return n, err
   983  	}
   984  
   985  	ntotal := 0
   986  	for len(buf) > 0 {
   987  		b := buf
   988  		if len(b) > maxRW {
   989  			b = b[:maxRW]
   990  		}
   991  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
   992  			err = syscall.WSASendto(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa, &o.o, nil)
   993  			return qty, err
   994  		}, b)
   995  		ntotal += int(n)
   996  		if err != nil {
   997  			return ntotal, err
   998  		}
   999  		buf = buf[n:]
  1000  	}
  1001  	return ntotal, nil
  1002  }
  1003  
  1004  // WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4.
  1005  func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
  1006  	if err := fd.writeLock(); err != nil {
  1007  		return 0, err
  1008  	}
  1009  	defer fd.writeUnlock()
  1010  
  1011  	if len(buf) == 0 {
  1012  		// handle zero-byte payload
  1013  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1014  			err = windows.WSASendtoInet4(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa4, &o.o, nil)
  1015  			return qty, err
  1016  		}, nil)
  1017  		return n, err
  1018  	}
  1019  
  1020  	ntotal := 0
  1021  	for len(buf) > 0 {
  1022  		b := buf
  1023  		if len(b) > maxRW {
  1024  			b = b[:maxRW]
  1025  		}
  1026  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1027  			err = windows.WSASendtoInet4(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa4, &o.o, nil)
  1028  			return qty, err
  1029  		}, b)
  1030  		ntotal += int(n)
  1031  		if err != nil {
  1032  			return ntotal, err
  1033  		}
  1034  		buf = buf[n:]
  1035  	}
  1036  	return ntotal, nil
  1037  }
  1038  
  1039  // WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6.
  1040  func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
  1041  	if err := fd.writeLock(); err != nil {
  1042  		return 0, err
  1043  	}
  1044  	defer fd.writeUnlock()
  1045  
  1046  	if len(buf) == 0 {
  1047  		// handle zero-byte payload
  1048  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1049  			err = windows.WSASendtoInet6(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa6, &o.o, nil)
  1050  			return qty, err
  1051  		}, nil)
  1052  		return n, err
  1053  	}
  1054  
  1055  	ntotal := 0
  1056  	for len(buf) > 0 {
  1057  		b := buf
  1058  		if len(b) > maxRW {
  1059  			b = b[:maxRW]
  1060  		}
  1061  		n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1062  			err = windows.WSASendtoInet6(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa6, &o.o, nil)
  1063  			return qty, err
  1064  		}, b)
  1065  		ntotal += int(n)
  1066  		if err != nil {
  1067  			return ntotal, err
  1068  		}
  1069  		buf = buf[n:]
  1070  	}
  1071  	return ntotal, nil
  1072  }
  1073  
  1074  // Call ConnectEx. This doesn't need any locking, since it is only
  1075  // called when the descriptor is first created. This is here rather
  1076  // than in the net package so that it can use fd.wop.
  1077  func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
  1078  	_, err := fd.execIO('w', func(o *operation) (uint32, error) {
  1079  		return 0, ConnectExFunc(fd.Sysfd, ra, nil, 0, nil, &o.o)
  1080  	}, nil)
  1081  	return err
  1082  }
  1083  
  1084  func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny) (string, error) {
  1085  	// Submit accept request.
  1086  	rsan := uint32(unsafe.Sizeof(rawsa[0]))
  1087  	_, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
  1088  		err = AcceptFunc(fd.Sysfd, s, (*byte)(unsafe.Pointer(&rawsa[0])), 0, rsan, rsan, &qty, &o.o)
  1089  		return qty, err
  1090  
  1091  	}, nil)
  1092  	if err != nil {
  1093  		CloseFunc(s)
  1094  		return "acceptex", err
  1095  	}
  1096  
  1097  	// Inherit properties of the listening socket.
  1098  	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
  1099  	if err != nil {
  1100  		CloseFunc(s)
  1101  		return "setsockopt", err
  1102  	}
  1103  
  1104  	return "", nil
  1105  }
  1106  
  1107  // Accept handles accepting a socket. The sysSocket parameter is used
  1108  // to allocate the net socket.
  1109  func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) {
  1110  	if err := fd.readLock(); err != nil {
  1111  		return syscall.InvalidHandle, nil, 0, "", err
  1112  	}
  1113  	defer fd.readUnlock()
  1114  
  1115  	var rawsa [2]syscall.RawSockaddrAny
  1116  	for {
  1117  		s, err := sysSocket()
  1118  		if err != nil {
  1119  			return syscall.InvalidHandle, nil, 0, "", err
  1120  		}
  1121  
  1122  		errcall, err := fd.acceptOne(s, rawsa[:])
  1123  		if err == nil {
  1124  			return s, rawsa[:], uint32(unsafe.Sizeof(rawsa[0])), "", nil
  1125  		}
  1126  
  1127  		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
  1128  		// returned here. These happen if connection reset is received
  1129  		// before AcceptEx could complete. These errors relate to new
  1130  		// connection, not to AcceptEx, so ignore broken connection and
  1131  		// try AcceptEx again for more connections.
  1132  		errno, ok := err.(syscall.Errno)
  1133  		if !ok {
  1134  			return syscall.InvalidHandle, nil, 0, errcall, err
  1135  		}
  1136  		switch errno {
  1137  		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
  1138  			// ignore these and try again
  1139  		default:
  1140  			return syscall.InvalidHandle, nil, 0, errcall, err
  1141  		}
  1142  	}
  1143  }
  1144  
  1145  // Seek wraps syscall.Seek.
  1146  func (fd *FD) Seek(offset int64, whence int) (int64, error) {
  1147  	if fd.kind == kindPipe {
  1148  		return 0, syscall.ESPIPE
  1149  	}
  1150  	if err := fd.readWriteLock(); err != nil {
  1151  		return 0, err
  1152  	}
  1153  	defer fd.readWriteUnlock()
  1154  
  1155  	if !fd.isBlocking {
  1156  		// Windows doesn't use the file pointer for overlapped file handles,
  1157  		// there is no point on calling syscall.Seek.
  1158  		var newOffset int64
  1159  		switch whence {
  1160  		case io.SeekStart:
  1161  			newOffset = offset
  1162  		case io.SeekCurrent:
  1163  			newOffset = fd.offset + offset
  1164  		case io.SeekEnd:
  1165  			var size int64
  1166  			if err := windows.GetFileSizeEx(fd.Sysfd, &size); err != nil {
  1167  				return 0, err
  1168  			}
  1169  			newOffset = size + offset
  1170  		default:
  1171  			return 0, windows.ERROR_INVALID_PARAMETER
  1172  		}
  1173  		if newOffset < 0 {
  1174  			return 0, windows.ERROR_NEGATIVE_SEEK
  1175  		}
  1176  		fd.setOffset(newOffset)
  1177  		return newOffset, nil
  1178  	}
  1179  	n, err := syscall.Seek(fd.Sysfd, offset, whence)
  1180  	fd.setOffset(n)
  1181  	return n, err
  1182  }
  1183  
  1184  // Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
  1185  func (fd *FD) Fchmod(mode uint32) error {
  1186  	if err := fd.incref(); err != nil {
  1187  		return err
  1188  	}
  1189  	defer fd.decref()
  1190  
  1191  	var d syscall.ByHandleFileInformation
  1192  	if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
  1193  		return err
  1194  	}
  1195  	attrs := d.FileAttributes
  1196  	if mode&syscall.S_IWRITE != 0 {
  1197  		attrs &^= syscall.FILE_ATTRIBUTE_READONLY
  1198  	} else {
  1199  		attrs |= syscall.FILE_ATTRIBUTE_READONLY
  1200  	}
  1201  	if attrs == d.FileAttributes {
  1202  		return nil
  1203  	}
  1204  
  1205  	var du windows.FILE_BASIC_INFO
  1206  	du.FileAttributes = attrs
  1207  	return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du)))
  1208  }
  1209  
  1210  // Fchdir wraps syscall.Fchdir.
  1211  func (fd *FD) Fchdir() error {
  1212  	if err := fd.incref(); err != nil {
  1213  		return err
  1214  	}
  1215  	defer fd.decref()
  1216  	return syscall.Fchdir(fd.Sysfd)
  1217  }
  1218  
  1219  // GetFileType wraps syscall.GetFileType.
  1220  func (fd *FD) GetFileType() (uint32, error) {
  1221  	if err := fd.incref(); err != nil {
  1222  		return 0, err
  1223  	}
  1224  	defer fd.decref()
  1225  	return syscall.GetFileType(fd.Sysfd)
  1226  }
  1227  
  1228  // GetFileInformationByHandle wraps GetFileInformationByHandle.
  1229  func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
  1230  	if err := fd.incref(); err != nil {
  1231  		return err
  1232  	}
  1233  	defer fd.decref()
  1234  	return syscall.GetFileInformationByHandle(fd.Sysfd, data)
  1235  }
  1236  
  1237  // RawRead invokes the user-defined function f for a read operation.
  1238  func (fd *FD) RawRead(f func(uintptr) bool) error {
  1239  	if err := fd.readLock(); err != nil {
  1240  		return err
  1241  	}
  1242  	defer fd.readUnlock()
  1243  	for {
  1244  		if f(uintptr(fd.Sysfd)) {
  1245  			return nil
  1246  		}
  1247  
  1248  		// Use a zero-byte read as a way to get notified when this
  1249  		// socket is readable. h/t https://stackoverflow.com/a/42019668/332798
  1250  		_, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
  1251  			var flags uint32
  1252  			if !fd.IsStream {
  1253  				flags |= windows.MSG_PEEK
  1254  			}
  1255  			err = syscall.WSARecv(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, &flags, &o.o, nil)
  1256  			return qty, err
  1257  		}, nil)
  1258  		if err == windows.WSAEMSGSIZE {
  1259  			// expected with a 0-byte peek, ignore.
  1260  		} else if err != nil {
  1261  			return err
  1262  		}
  1263  	}
  1264  }
  1265  
  1266  // RawWrite invokes the user-defined function f for a write operation.
  1267  func (fd *FD) RawWrite(f func(uintptr) bool) error {
  1268  	if err := fd.writeLock(); err != nil {
  1269  		return err
  1270  	}
  1271  	defer fd.writeUnlock()
  1272  
  1273  	if f(uintptr(fd.Sysfd)) {
  1274  		return nil
  1275  	}
  1276  
  1277  	// TODO(tmm1): find a way to detect socket writability
  1278  	return syscall.EWINDOWS
  1279  }
  1280  
  1281  func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 {
  1282  	*rsa = syscall.RawSockaddrAny{}
  1283  	raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  1284  	raw.Family = syscall.AF_INET
  1285  	p := (*[2]byte)(unsafe.Pointer(&raw.Port))
  1286  	p[0] = byte(sa.Port >> 8)
  1287  	p[1] = byte(sa.Port)
  1288  	raw.Addr = sa.Addr
  1289  	return int32(unsafe.Sizeof(*raw))
  1290  }
  1291  
  1292  func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 {
  1293  	*rsa = syscall.RawSockaddrAny{}
  1294  	raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  1295  	raw.Family = syscall.AF_INET6
  1296  	p := (*[2]byte)(unsafe.Pointer(&raw.Port))
  1297  	p[0] = byte(sa.Port >> 8)
  1298  	p[1] = byte(sa.Port)
  1299  	raw.Scope_id = sa.ZoneId
  1300  	raw.Addr = sa.Addr
  1301  	return int32(unsafe.Sizeof(*raw))
  1302  }
  1303  
  1304  func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
  1305  	pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  1306  	p := (*[2]byte)(unsafe.Pointer(&pp.Port))
  1307  	sa.Port = int(p[0])<<8 + int(p[1])
  1308  	sa.Addr = pp.Addr
  1309  }
  1310  
  1311  func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
  1312  	pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  1313  	p := (*[2]byte)(unsafe.Pointer(&pp.Port))
  1314  	sa.Port = int(p[0])<<8 + int(p[1])
  1315  	sa.ZoneId = pp.Scope_id
  1316  	sa.Addr = pp.Addr
  1317  }
  1318  
  1319  func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) {
  1320  	switch sa := sa.(type) {
  1321  	case *syscall.SockaddrInet4:
  1322  		sz := sockaddrInet4ToRaw(rsa, sa)
  1323  		return sz, nil
  1324  	case *syscall.SockaddrInet6:
  1325  		sz := sockaddrInet6ToRaw(rsa, sa)
  1326  		return sz, nil
  1327  	default:
  1328  		return 0, syscall.EWINDOWS
  1329  	}
  1330  }
  1331  
  1332  // ReadMsg wraps the WSARecvMsg network call.
  1333  func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
  1334  	if err := fd.readLock(); err != nil {
  1335  		return 0, 0, 0, nil, err
  1336  	}
  1337  	defer fd.readUnlock()
  1338  
  1339  	if len(p) > maxRW {
  1340  		p = p[:maxRW]
  1341  	}
  1342  
  1343  	msg := newWSAMsg(p, oob, flags, true)
  1344  	defer freeWSAMsg(msg)
  1345  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
  1346  		err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
  1347  		return qty, err
  1348  	}, nil)
  1349  	err = fd.eofError(n, err)
  1350  	var sa syscall.Sockaddr
  1351  	if err == nil {
  1352  		sa, err = msg.Name.Sockaddr()
  1353  	}
  1354  	return n, int(msg.Control.Len), int(msg.Flags), sa, err
  1355  }
  1356  
  1357  // ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4.
  1358  func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
  1359  	if err := fd.readLock(); err != nil {
  1360  		return 0, 0, 0, err
  1361  	}
  1362  	defer fd.readUnlock()
  1363  
  1364  	if len(p) > maxRW {
  1365  		p = p[:maxRW]
  1366  	}
  1367  
  1368  	msg := newWSAMsg(p, oob, flags, true)
  1369  	defer freeWSAMsg(msg)
  1370  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
  1371  		err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
  1372  		return qty, err
  1373  	}, nil)
  1374  	err = fd.eofError(n, err)
  1375  	if err == nil {
  1376  		rawToSockaddrInet4(msg.Name, sa4)
  1377  	}
  1378  	return n, int(msg.Control.Len), int(msg.Flags), err
  1379  }
  1380  
  1381  // ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6.
  1382  func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
  1383  	if err := fd.readLock(); err != nil {
  1384  		return 0, 0, 0, err
  1385  	}
  1386  	defer fd.readUnlock()
  1387  
  1388  	if len(p) > maxRW {
  1389  		p = p[:maxRW]
  1390  	}
  1391  
  1392  	msg := newWSAMsg(p, oob, flags, true)
  1393  	defer freeWSAMsg(msg)
  1394  	n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
  1395  		err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
  1396  		return qty, err
  1397  	}, nil)
  1398  	err = fd.eofError(n, err)
  1399  	if err == nil {
  1400  		rawToSockaddrInet6(msg.Name, sa6)
  1401  	}
  1402  	return n, int(msg.Control.Len), int(msg.Flags), err
  1403  }
  1404  
  1405  // WriteMsg wraps the WSASendMsg network call.
  1406  func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
  1407  	if len(p) > maxRW {
  1408  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1409  	}
  1410  
  1411  	if err := fd.writeLock(); err != nil {
  1412  		return 0, 0, err
  1413  	}
  1414  	defer fd.writeUnlock()
  1415  
  1416  	msg := newWSAMsg(p, oob, 0, sa != nil)
  1417  	defer freeWSAMsg(msg)
  1418  	if sa != nil {
  1419  		var err error
  1420  		msg.Namelen, err = sockaddrToRaw(msg.Name, sa)
  1421  		if err != nil {
  1422  			return 0, 0, err
  1423  		}
  1424  	}
  1425  	n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1426  		err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
  1427  		return qty, err
  1428  	}, nil)
  1429  	return n, int(msg.Control.Len), err
  1430  }
  1431  
  1432  // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
  1433  func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
  1434  	if len(p) > maxRW {
  1435  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1436  	}
  1437  
  1438  	if err := fd.writeLock(); err != nil {
  1439  		return 0, 0, err
  1440  	}
  1441  	defer fd.writeUnlock()
  1442  
  1443  	msg := newWSAMsg(p, oob, 0, sa != nil)
  1444  	defer freeWSAMsg(msg)
  1445  	if sa != nil {
  1446  		msg.Namelen = sockaddrInet4ToRaw(msg.Name, sa)
  1447  	}
  1448  	n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1449  		err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
  1450  		return qty, err
  1451  	}, nil)
  1452  	return n, int(msg.Control.Len), err
  1453  }
  1454  
  1455  // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
  1456  func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
  1457  	if len(p) > maxRW {
  1458  		return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
  1459  	}
  1460  
  1461  	if err := fd.writeLock(); err != nil {
  1462  		return 0, 0, err
  1463  	}
  1464  	defer fd.writeUnlock()
  1465  
  1466  	msg := newWSAMsg(p, oob, 0, sa != nil)
  1467  	defer freeWSAMsg(msg)
  1468  	if sa != nil {
  1469  		msg.Namelen = sockaddrInet6ToRaw(msg.Name, sa)
  1470  	}
  1471  	n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
  1472  		err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
  1473  		return qty, err
  1474  	}, nil)
  1475  	return n, int(msg.Control.Len), err
  1476  }
  1477  
  1478  func DupCloseOnExec(fd int) (int, string, error) {
  1479  	proc, err := syscall.GetCurrentProcess()
  1480  	if err != nil {
  1481  		return 0, "GetCurrentProcess", err
  1482  	}
  1483  
  1484  	var nfd syscall.Handle
  1485  	const inherit = false // analogous to CLOEXEC
  1486  	if err := syscall.DuplicateHandle(proc, syscall.Handle(fd), proc, &nfd, 0, inherit, syscall.DUPLICATE_SAME_ACCESS); err != nil {
  1487  		return 0, "DuplicateHandle", err
  1488  	}
  1489  	return int(nfd), "", nil
  1490  }
  1491  

View as plain text