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