...
Run Format

Source file src/net/fd_windows.go

Documentation: net

     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  	"context"
     9  	"internal/poll"
    10  	"os"
    11  	"runtime"
    12  	"syscall"
    13  	"time"
    14  	"unsafe"
    15  )
    16  
    17  // canUseConnectEx reports whether we can use the ConnectEx Windows API call
    18  // for the given network type.
    19  func canUseConnectEx(net string) bool {
    20  	switch net {
    21  	case "tcp", "tcp4", "tcp6":
    22  		return true
    23  	}
    24  	// ConnectEx windows API does not support connectionless sockets.
    25  	return false
    26  }
    27  
    28  // Network file descriptor.
    29  type netFD struct {
    30  	pfd poll.FD
    31  
    32  	// immutable until Close
    33  	family      int
    34  	sotype      int
    35  	isConnected bool // handshake completed or use of association with peer
    36  	net         string
    37  	laddr       Addr
    38  	raddr       Addr
    39  }
    40  
    41  func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
    42  	ret := &netFD{
    43  		pfd: poll.FD{
    44  			Sysfd:         sysfd,
    45  			IsStream:      sotype == syscall.SOCK_STREAM,
    46  			ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
    47  		},
    48  		family: family,
    49  		sotype: sotype,
    50  		net:    net,
    51  	}
    52  	return ret, nil
    53  }
    54  
    55  func (fd *netFD) init() error {
    56  	errcall, err := fd.pfd.Init(fd.net, true)
    57  	if errcall != "" {
    58  		err = wrapSyscallError(errcall, err)
    59  	}
    60  	return err
    61  }
    62  
    63  func (fd *netFD) setAddr(laddr, raddr Addr) {
    64  	fd.laddr = laddr
    65  	fd.raddr = raddr
    66  	runtime.SetFinalizer(fd, (*netFD).Close)
    67  }
    68  
    69  // Always returns nil for connected peer address result.
    70  func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
    71  	// Do not need to call fd.writeLock here,
    72  	// because fd is not yet accessible to user,
    73  	// so no concurrent operations are possible.
    74  	if err := fd.init(); err != nil {
    75  		return nil, err
    76  	}
    77  	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
    78  		fd.pfd.SetWriteDeadline(deadline)
    79  		defer fd.pfd.SetWriteDeadline(noDeadline)
    80  	}
    81  	if !canUseConnectEx(fd.net) {
    82  		err := connectFunc(fd.pfd.Sysfd, ra)
    83  		return nil, os.NewSyscallError("connect", err)
    84  	}
    85  	// ConnectEx windows API requires an unconnected, previously bound socket.
    86  	if la == nil {
    87  		switch ra.(type) {
    88  		case *syscall.SockaddrInet4:
    89  			la = &syscall.SockaddrInet4{}
    90  		case *syscall.SockaddrInet6:
    91  			la = &syscall.SockaddrInet6{}
    92  		default:
    93  			panic("unexpected type in connect")
    94  		}
    95  		if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
    96  			return nil, os.NewSyscallError("bind", err)
    97  		}
    98  	}
    99  
   100  	// Wait for the goroutine converting context.Done into a write timeout
   101  	// to exist, otherwise our caller might cancel the context and
   102  	// cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
   103  	done := make(chan bool) // must be unbuffered
   104  	defer func() { done <- true }()
   105  	go func() {
   106  		select {
   107  		case <-ctx.Done():
   108  			// Force the runtime's poller to immediately give
   109  			// up waiting for writability.
   110  			fd.pfd.SetWriteDeadline(aLongTimeAgo)
   111  			<-done
   112  		case <-done:
   113  		}
   114  	}()
   115  
   116  	// Call ConnectEx API.
   117  	if err := fd.pfd.ConnectEx(ra); err != nil {
   118  		select {
   119  		case <-ctx.Done():
   120  			return nil, mapErr(ctx.Err())
   121  		default:
   122  			if _, ok := err.(syscall.Errno); ok {
   123  				err = os.NewSyscallError("connectex", err)
   124  			}
   125  			return nil, err
   126  		}
   127  	}
   128  	// Refresh socket properties.
   129  	return nil, os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.pfd.Sysfd)), int32(unsafe.Sizeof(fd.pfd.Sysfd))))
   130  }
   131  
   132  func (fd *netFD) Close() error {
   133  	runtime.SetFinalizer(fd, nil)
   134  	return fd.pfd.Close()
   135  }
   136  
   137  func (fd *netFD) shutdown(how int) error {
   138  	err := fd.pfd.Shutdown(how)
   139  	runtime.KeepAlive(fd)
   140  	return err
   141  }
   142  
   143  func (fd *netFD) closeRead() error {
   144  	return fd.shutdown(syscall.SHUT_RD)
   145  }
   146  
   147  func (fd *netFD) closeWrite() error {
   148  	return fd.shutdown(syscall.SHUT_WR)
   149  }
   150  
   151  func (fd *netFD) Read(buf []byte) (int, error) {
   152  	n, err := fd.pfd.Read(buf)
   153  	runtime.KeepAlive(fd)
   154  	return n, wrapSyscallError("wsarecv", err)
   155  }
   156  
   157  func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
   158  	n, sa, err := fd.pfd.ReadFrom(buf)
   159  	runtime.KeepAlive(fd)
   160  	return n, sa, wrapSyscallError("wsarecvfrom", err)
   161  }
   162  
   163  func (fd *netFD) Write(buf []byte) (int, error) {
   164  	n, err := fd.pfd.Write(buf)
   165  	runtime.KeepAlive(fd)
   166  	return n, wrapSyscallError("wsasend", err)
   167  }
   168  
   169  func (c *conn) writeBuffers(v *Buffers) (int64, error) {
   170  	if !c.ok() {
   171  		return 0, syscall.EINVAL
   172  	}
   173  	n, err := c.fd.writeBuffers(v)
   174  	if err != nil {
   175  		return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   176  	}
   177  	return n, nil
   178  }
   179  
   180  func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
   181  	n, err := fd.pfd.Writev((*[][]byte)(buf))
   182  	runtime.KeepAlive(fd)
   183  	return n, wrapSyscallError("wsasend", err)
   184  }
   185  
   186  func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
   187  	n, err := fd.pfd.WriteTo(buf, sa)
   188  	runtime.KeepAlive(fd)
   189  	return n, wrapSyscallError("wsasendto", err)
   190  }
   191  
   192  func (fd *netFD) accept() (*netFD, error) {
   193  	s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
   194  		return sysSocket(fd.family, fd.sotype, 0)
   195  	})
   196  
   197  	if err != nil {
   198  		if errcall != "" {
   199  			err = wrapSyscallError(errcall, err)
   200  		}
   201  		return nil, err
   202  	}
   203  
   204  	// Associate our new socket with IOCP.
   205  	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
   206  	if err != nil {
   207  		poll.CloseFunc(s)
   208  		return nil, err
   209  	}
   210  	if err := netfd.init(); err != nil {
   211  		fd.Close()
   212  		return nil, err
   213  	}
   214  
   215  	// Get local and peer addr out of AcceptEx buffer.
   216  	var lrsa, rrsa *syscall.RawSockaddrAny
   217  	var llen, rlen int32
   218  	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
   219  		0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
   220  	lsa, _ := lrsa.Sockaddr()
   221  	rsa, _ := rrsa.Sockaddr()
   222  
   223  	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
   224  	return netfd, nil
   225  }
   226  
   227  func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
   228  	n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
   229  	runtime.KeepAlive(fd)
   230  	return n, oobn, flags, sa, wrapSyscallError("wsarecvmsg", err)
   231  }
   232  
   233  func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   234  	n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
   235  	runtime.KeepAlive(fd)
   236  	return n, oobn, wrapSyscallError("wsasendmsg", err)
   237  }
   238  
   239  // Unimplemented functions.
   240  
   241  func (fd *netFD) dup() (*os.File, error) {
   242  	// TODO: Implement this
   243  	return nil, syscall.EWINDOWS
   244  }
   245  
   246  func (fd *netFD) SetDeadline(t time.Time) error {
   247  	return fd.pfd.SetDeadline(t)
   248  }
   249  
   250  func (fd *netFD) SetReadDeadline(t time.Time) error {
   251  	return fd.pfd.SetReadDeadline(t)
   252  }
   253  
   254  func (fd *netFD) SetWriteDeadline(t time.Time) error {
   255  	return fd.pfd.SetWriteDeadline(t)
   256  }
   257  

View as plain text