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