...

Source file src/net/fd_windows.go

     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