rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/net/fd_windows.go (about)

     1  // Copyright 2010 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 net
     6  
     7  import (
     8  	"errors"
     9  	"os"
    10  	"runtime"
    11  	"sync"
    12  	"syscall"
    13  	"time"
    14  	"unsafe"
    15  )
    16  
    17  var (
    18  	initErr error
    19  	ioSync  uint64
    20  )
    21  
    22  // CancelIo Windows API cancels all outstanding IO for a particular
    23  // socket on current thread. To overcome that limitation, we run
    24  // special goroutine, locked to OS single thread, that both starts
    25  // and cancels IO. It means, there are 2 unavoidable thread switches
    26  // for every IO.
    27  // Some newer versions of Windows has new CancelIoEx API, that does
    28  // not have that limitation and can be used from any thread. This
    29  // package uses CancelIoEx API, if present, otherwise it fallback
    30  // to CancelIo.
    31  
    32  var (
    33  	canCancelIO                               bool // determines if CancelIoEx API is present
    34  	skipSyncNotif                             bool
    35  	hasLoadSetFileCompletionNotificationModes bool
    36  )
    37  
    38  func sysInit() {
    39  	var d syscall.WSAData
    40  	e := syscall.WSAStartup(uint32(0x202), &d)
    41  	if e != nil {
    42  		initErr = os.NewSyscallError("WSAStartup", e)
    43  	}
    44  	canCancelIO = syscall.LoadCancelIoEx() == nil
    45  	if syscall.LoadGetAddrInfo() == nil {
    46  		lookupPort = newLookupPort
    47  		lookupIP = newLookupIP
    48  	}
    49  
    50  	hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
    51  	if hasLoadSetFileCompletionNotificationModes {
    52  		// It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
    53  		// http://support.microsoft.com/kb/2568167
    54  		skipSyncNotif = true
    55  		protos := [2]int32{syscall.IPPROTO_TCP, 0}
    56  		var buf [32]syscall.WSAProtocolInfo
    57  		len := uint32(unsafe.Sizeof(buf))
    58  		n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
    59  		if err != nil {
    60  			skipSyncNotif = false
    61  		} else {
    62  			for i := int32(0); i < n; i++ {
    63  				if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
    64  					skipSyncNotif = false
    65  					break
    66  				}
    67  			}
    68  		}
    69  	}
    70  }
    71  
    72  func canUseConnectEx(net string) bool {
    73  	switch net {
    74  	case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
    75  		// ConnectEx windows API does not support connectionless sockets.
    76  		return false
    77  	}
    78  	return syscall.LoadConnectEx() == nil
    79  }
    80  
    81  func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
    82  	if !canUseConnectEx(net) {
    83  		// Use the relatively inefficient goroutine-racing
    84  		// implementation of DialTimeout.
    85  		return dialChannel(net, ra, dialer, deadline)
    86  	}
    87  	return dialer(deadline)
    88  }
    89  
    90  // operation contains superset of data necessary to perform all async IO.
    91  type operation struct {
    92  	// Used by IOCP interface, it must be first field
    93  	// of the struct, as our code rely on it.
    94  	o syscall.Overlapped
    95  
    96  	// fields used by runtime.netpoll
    97  	runtimeCtx uintptr
    98  	mode       int32
    99  	errno      int32
   100  	qty        uint32
   101  
   102  	// fields used only by net package
   103  	fd     *netFD
   104  	errc   chan error
   105  	buf    syscall.WSABuf
   106  	sa     syscall.Sockaddr
   107  	rsa    *syscall.RawSockaddrAny
   108  	rsan   int32
   109  	handle syscall.Handle
   110  	flags  uint32
   111  }
   112  
   113  func (o *operation) InitBuf(buf []byte) {
   114  	o.buf.Len = uint32(len(buf))
   115  	o.buf.Buf = nil
   116  	if len(buf) != 0 {
   117  		o.buf.Buf = &buf[0]
   118  	}
   119  }
   120  
   121  // ioSrv executes net IO requests.
   122  type ioSrv struct {
   123  	req chan ioSrvReq
   124  }
   125  
   126  type ioSrvReq struct {
   127  	o      *operation
   128  	submit func(o *operation) error // if nil, cancel the operation
   129  }
   130  
   131  // ProcessRemoteIO will execute submit IO requests on behalf
   132  // of other goroutines, all on a single os thread, so it can
   133  // cancel them later. Results of all operations will be sent
   134  // back to their requesters via channel supplied in request.
   135  // It is used only when the CancelIoEx API is unavailable.
   136  func (s *ioSrv) ProcessRemoteIO() {
   137  	runtime.LockOSThread()
   138  	defer runtime.UnlockOSThread()
   139  	for r := range s.req {
   140  		if r.submit != nil {
   141  			r.o.errc <- r.submit(r.o)
   142  		} else {
   143  			r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
   144  		}
   145  	}
   146  }
   147  
   148  // ExecIO executes a single IO operation o. It submits and cancels
   149  // IO in the current thread for systems where Windows CancelIoEx API
   150  // is available. Alternatively, it passes the request onto
   151  // runtime netpoll and waits for completion or cancels request.
   152  func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
   153  	fd := o.fd
   154  	// Notify runtime netpoll about starting IO.
   155  	err := fd.pd.Prepare(int(o.mode))
   156  	if err != nil {
   157  		return 0, &OpError{name, fd.net, fd.laddr, err}
   158  	}
   159  	// Start IO.
   160  	if canCancelIO {
   161  		err = submit(o)
   162  	} else {
   163  		// Send request to a special dedicated thread,
   164  		// so it can stop the IO with CancelIO later.
   165  		s.req <- ioSrvReq{o, submit}
   166  		err = <-o.errc
   167  	}
   168  	switch err {
   169  	case nil:
   170  		// IO completed immediately
   171  		if o.fd.skipSyncNotif {
   172  			// No completion message will follow, so return immediately.
   173  			return int(o.qty), nil
   174  		}
   175  		// Need to get our completion message anyway.
   176  	case syscall.ERROR_IO_PENDING:
   177  		// IO started, and we have to wait for its completion.
   178  		err = nil
   179  	default:
   180  		return 0, &OpError{name, fd.net, fd.laddr, err}
   181  	}
   182  	// Wait for our request to complete.
   183  	err = fd.pd.Wait(int(o.mode))
   184  	if err == nil {
   185  		// All is good. Extract our IO results and return.
   186  		if o.errno != 0 {
   187  			err = syscall.Errno(o.errno)
   188  			return 0, &OpError{name, fd.net, fd.laddr, err}
   189  		}
   190  		return int(o.qty), nil
   191  	}
   192  	// IO is interrupted by "close" or "timeout"
   193  	netpollErr := err
   194  	switch netpollErr {
   195  	case errClosing, errTimeout:
   196  		// will deal with those.
   197  	default:
   198  		panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
   199  	}
   200  	// Cancel our request.
   201  	if canCancelIO {
   202  		err := syscall.CancelIoEx(fd.sysfd, &o.o)
   203  		// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
   204  		if err != nil && err != syscall.ERROR_NOT_FOUND {
   205  			// TODO(brainman): maybe do something else, but panic.
   206  			panic(err)
   207  		}
   208  	} else {
   209  		s.req <- ioSrvReq{o, nil}
   210  		<-o.errc
   211  	}
   212  	// Wait for cancellation to complete.
   213  	fd.pd.WaitCanceled(int(o.mode))
   214  	if o.errno != 0 {
   215  		err = syscall.Errno(o.errno)
   216  		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
   217  			err = netpollErr
   218  		}
   219  		return 0, &OpError{name, fd.net, fd.laddr, err}
   220  	}
   221  	// We issued cancellation request. But, it seems, IO operation succeeded
   222  	// before cancellation request run. We need to treat IO operation as
   223  	// succeeded (the bytes are actually sent/recv from network).
   224  	return int(o.qty), nil
   225  }
   226  
   227  // Start helper goroutines.
   228  var rsrv, wsrv *ioSrv
   229  var onceStartServer sync.Once
   230  
   231  func startServer() {
   232  	rsrv = new(ioSrv)
   233  	wsrv = new(ioSrv)
   234  	if !canCancelIO {
   235  		// Only CancelIo API is available. Lets start two special goroutines
   236  		// locked to an OS thread, that both starts and cancels IO. One will
   237  		// process read requests, while other will do writes.
   238  		rsrv.req = make(chan ioSrvReq)
   239  		go rsrv.ProcessRemoteIO()
   240  		wsrv.req = make(chan ioSrvReq)
   241  		go wsrv.ProcessRemoteIO()
   242  	}
   243  }
   244  
   245  // Network file descriptor.
   246  type netFD struct {
   247  	// locking/lifetime of sysfd + serialize access to Read and Write methods
   248  	fdmu fdMutex
   249  
   250  	// immutable until Close
   251  	sysfd         syscall.Handle
   252  	family        int
   253  	sotype        int
   254  	isConnected   bool
   255  	skipSyncNotif bool
   256  	net           string
   257  	laddr         Addr
   258  	raddr         Addr
   259  
   260  	rop operation // read operation
   261  	wop operation // write operation
   262  
   263  	// wait server
   264  	pd pollDesc
   265  }
   266  
   267  func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
   268  	if initErr != nil {
   269  		return nil, initErr
   270  	}
   271  	onceStartServer.Do(startServer)
   272  	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
   273  }
   274  
   275  func (fd *netFD) init() error {
   276  	if err := fd.pd.Init(fd); err != nil {
   277  		return err
   278  	}
   279  	if hasLoadSetFileCompletionNotificationModes {
   280  		// We do not use events, so we can skip them always.
   281  		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
   282  		// It's not safe to skip completion notifications for UDP:
   283  		// http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
   284  		if skipSyncNotif && fd.net == "tcp" {
   285  			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
   286  		}
   287  		err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
   288  		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
   289  			fd.skipSyncNotif = true
   290  		}
   291  	}
   292  	// Disable SIO_UDP_CONNRESET behavior.
   293  	// http://support.microsoft.com/kb/263823
   294  	switch fd.net {
   295  	case "udp", "udp4", "udp6":
   296  		ret := uint32(0)
   297  		flag := uint32(0)
   298  		size := uint32(unsafe.Sizeof(flag))
   299  		err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
   300  		if err != nil {
   301  			return os.NewSyscallError("WSAIoctl", err)
   302  		}
   303  	}
   304  	fd.rop.mode = 'r'
   305  	fd.wop.mode = 'w'
   306  	fd.rop.fd = fd
   307  	fd.wop.fd = fd
   308  	fd.rop.runtimeCtx = fd.pd.runtimeCtx
   309  	fd.wop.runtimeCtx = fd.pd.runtimeCtx
   310  	if !canCancelIO {
   311  		fd.rop.errc = make(chan error)
   312  		fd.wop.errc = make(chan error)
   313  	}
   314  	return nil
   315  }
   316  
   317  func (fd *netFD) setAddr(laddr, raddr Addr) {
   318  	fd.laddr = laddr
   319  	fd.raddr = raddr
   320  	runtime.SetFinalizer(fd, (*netFD).Close)
   321  }
   322  
   323  func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
   324  	// Do not need to call fd.writeLock here,
   325  	// because fd is not yet accessible to user,
   326  	// so no concurrent operations are possible.
   327  	if err := fd.init(); err != nil {
   328  		return err
   329  	}
   330  	if !deadline.IsZero() {
   331  		fd.setWriteDeadline(deadline)
   332  		defer fd.setWriteDeadline(noDeadline)
   333  	}
   334  	if !canUseConnectEx(fd.net) {
   335  		return connectFunc(fd.sysfd, ra)
   336  	}
   337  	// ConnectEx windows API requires an unconnected, previously bound socket.
   338  	if la == nil {
   339  		switch ra.(type) {
   340  		case *syscall.SockaddrInet4:
   341  			la = &syscall.SockaddrInet4{}
   342  		case *syscall.SockaddrInet6:
   343  			la = &syscall.SockaddrInet6{}
   344  		default:
   345  			panic("unexpected type in connect")
   346  		}
   347  		if err := syscall.Bind(fd.sysfd, la); err != nil {
   348  			return err
   349  		}
   350  	}
   351  	// Call ConnectEx API.
   352  	o := &fd.wop
   353  	o.sa = ra
   354  	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
   355  		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
   356  	})
   357  	if err != nil {
   358  		return err
   359  	}
   360  	// Refresh socket properties.
   361  	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
   362  }
   363  
   364  func (fd *netFD) destroy() {
   365  	if fd.sysfd == syscall.InvalidHandle {
   366  		return
   367  	}
   368  	// Poller may want to unregister fd in readiness notification mechanism,
   369  	// so this must be executed before closeFunc.
   370  	fd.pd.Close()
   371  	closeFunc(fd.sysfd)
   372  	fd.sysfd = syscall.InvalidHandle
   373  	// no need for a finalizer anymore
   374  	runtime.SetFinalizer(fd, nil)
   375  }
   376  
   377  // Add a reference to this fd.
   378  // Returns an error if the fd cannot be used.
   379  func (fd *netFD) incref() error {
   380  	if !fd.fdmu.Incref() {
   381  		return errClosing
   382  	}
   383  	return nil
   384  }
   385  
   386  // Remove a reference to this FD and close if we've been asked to do so
   387  // (and there are no references left).
   388  func (fd *netFD) decref() {
   389  	if fd.fdmu.Decref() {
   390  		fd.destroy()
   391  	}
   392  }
   393  
   394  // Add a reference to this fd and lock for reading.
   395  // Returns an error if the fd cannot be used.
   396  func (fd *netFD) readLock() error {
   397  	if !fd.fdmu.RWLock(true) {
   398  		return errClosing
   399  	}
   400  	return nil
   401  }
   402  
   403  // Unlock for reading and remove a reference to this FD.
   404  func (fd *netFD) readUnlock() {
   405  	if fd.fdmu.RWUnlock(true) {
   406  		fd.destroy()
   407  	}
   408  }
   409  
   410  // Add a reference to this fd and lock for writing.
   411  // Returns an error if the fd cannot be used.
   412  func (fd *netFD) writeLock() error {
   413  	if !fd.fdmu.RWLock(false) {
   414  		return errClosing
   415  	}
   416  	return nil
   417  }
   418  
   419  // Unlock for writing and remove a reference to this FD.
   420  func (fd *netFD) writeUnlock() {
   421  	if fd.fdmu.RWUnlock(false) {
   422  		fd.destroy()
   423  	}
   424  }
   425  
   426  func (fd *netFD) Close() error {
   427  	if !fd.fdmu.IncrefAndClose() {
   428  		return errClosing
   429  	}
   430  	// unblock pending reader and writer
   431  	fd.pd.Evict()
   432  	fd.decref()
   433  	return nil
   434  }
   435  
   436  func (fd *netFD) shutdown(how int) error {
   437  	if err := fd.incref(); err != nil {
   438  		return err
   439  	}
   440  	defer fd.decref()
   441  	err := syscall.Shutdown(fd.sysfd, how)
   442  	if err != nil {
   443  		return &OpError{"shutdown", fd.net, fd.laddr, err}
   444  	}
   445  	return nil
   446  }
   447  
   448  func (fd *netFD) closeRead() error {
   449  	return fd.shutdown(syscall.SHUT_RD)
   450  }
   451  
   452  func (fd *netFD) closeWrite() error {
   453  	return fd.shutdown(syscall.SHUT_WR)
   454  }
   455  
   456  func (fd *netFD) Read(buf []byte) (int, error) {
   457  	if err := fd.readLock(); err != nil {
   458  		return 0, err
   459  	}
   460  	defer fd.readUnlock()
   461  	o := &fd.rop
   462  	o.InitBuf(buf)
   463  	n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
   464  		return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
   465  	})
   466  	if raceenabled {
   467  		raceAcquire(unsafe.Pointer(&ioSync))
   468  	}
   469  	err = fd.eofError(n, err)
   470  	return n, err
   471  }
   472  
   473  func (fd *netFD) readFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
   474  	if len(buf) == 0 {
   475  		return 0, nil, nil
   476  	}
   477  	if err := fd.readLock(); err != nil {
   478  		return 0, nil, err
   479  	}
   480  	defer fd.readUnlock()
   481  	o := &fd.rop
   482  	o.InitBuf(buf)
   483  	n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
   484  		if o.rsa == nil {
   485  			o.rsa = new(syscall.RawSockaddrAny)
   486  		}
   487  		o.rsan = int32(unsafe.Sizeof(*o.rsa))
   488  		return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
   489  	})
   490  	err = fd.eofError(n, err)
   491  	if err != nil {
   492  		return 0, nil, err
   493  	}
   494  	sa, _ = o.rsa.Sockaddr()
   495  	return
   496  }
   497  
   498  func (fd *netFD) Write(buf []byte) (int, error) {
   499  	if err := fd.writeLock(); err != nil {
   500  		return 0, err
   501  	}
   502  	defer fd.writeUnlock()
   503  	if raceenabled {
   504  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   505  	}
   506  	o := &fd.wop
   507  	o.InitBuf(buf)
   508  	return wsrv.ExecIO(o, "WSASend", func(o *operation) error {
   509  		return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
   510  	})
   511  }
   512  
   513  func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
   514  	if len(buf) == 0 {
   515  		return 0, nil
   516  	}
   517  	if err := fd.writeLock(); err != nil {
   518  		return 0, err
   519  	}
   520  	defer fd.writeUnlock()
   521  	o := &fd.wop
   522  	o.InitBuf(buf)
   523  	o.sa = sa
   524  	return wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
   525  		return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
   526  	})
   527  }
   528  
   529  func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
   530  	// Get new socket.
   531  	s, err := sysSocket(fd.family, fd.sotype, 0)
   532  	if err != nil {
   533  		return nil, &OpError{"socket", fd.net, fd.laddr, err}
   534  	}
   535  
   536  	// Associate our new socket with IOCP.
   537  	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
   538  	if err != nil {
   539  		closeFunc(s)
   540  		return nil, &OpError{"accept", fd.net, fd.laddr, err}
   541  	}
   542  	if err := netfd.init(); err != nil {
   543  		fd.Close()
   544  		return nil, err
   545  	}
   546  
   547  	// Submit accept request.
   548  	o.handle = s
   549  	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
   550  	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
   551  		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
   552  	})
   553  	if err != nil {
   554  		netfd.Close()
   555  		return nil, err
   556  	}
   557  
   558  	// Inherit properties of the listening socket.
   559  	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
   560  	if err != nil {
   561  		netfd.Close()
   562  		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
   563  	}
   564  
   565  	return netfd, nil
   566  }
   567  
   568  func (fd *netFD) accept() (*netFD, error) {
   569  	if err := fd.readLock(); err != nil {
   570  		return nil, err
   571  	}
   572  	defer fd.readUnlock()
   573  
   574  	o := &fd.rop
   575  	var netfd *netFD
   576  	var err error
   577  	var rawsa [2]syscall.RawSockaddrAny
   578  	for {
   579  		netfd, err = fd.acceptOne(rawsa[:], o)
   580  		if err == nil {
   581  			break
   582  		}
   583  		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
   584  		// returned here. These happen if connection reset is received
   585  		// before AcceptEx could complete. These errors relate to new
   586  		// connection, not to AcceptEx, so ignore broken connection and
   587  		// try AcceptEx again for more connections.
   588  		operr, ok := err.(*OpError)
   589  		if !ok {
   590  			return nil, err
   591  		}
   592  		errno, ok := operr.Err.(syscall.Errno)
   593  		if !ok {
   594  			return nil, err
   595  		}
   596  		switch errno {
   597  		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
   598  			// ignore these and try again
   599  		default:
   600  			return nil, err
   601  		}
   602  	}
   603  
   604  	// Get local and peer addr out of AcceptEx buffer.
   605  	var lrsa, rrsa *syscall.RawSockaddrAny
   606  	var llen, rlen int32
   607  	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
   608  		0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
   609  	lsa, _ := lrsa.Sockaddr()
   610  	rsa, _ := rrsa.Sockaddr()
   611  
   612  	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
   613  	return netfd, nil
   614  }
   615  
   616  // Unimplemented functions.
   617  
   618  func (fd *netFD) dup() (*os.File, error) {
   619  	// TODO: Implement this
   620  	return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
   621  }
   622  
   623  var errNoSupport = errors.New("address family not supported")
   624  
   625  func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
   626  	return 0, 0, 0, nil, errNoSupport
   627  }
   628  
   629  func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   630  	return 0, 0, errNoSupport
   631  }