Source file 
src/net/fd_windows.go
     1  
     2  
     3  
     4  
     5  package net
     6  
     7  import (
     8  	"context"
     9  	"internal/poll"
    10  	"internal/syscall/windows"
    11  	"os"
    12  	"runtime"
    13  	"syscall"
    14  	"unsafe"
    15  )
    16  
    17  const (
    18  	readSyscallName     = "wsarecv"
    19  	readFromSyscallName = "wsarecvfrom"
    20  	readMsgSyscallName  = "wsarecvmsg"
    21  	writeSyscallName    = "wsasend"
    22  	writeToSyscallName  = "wsasendto"
    23  	writeMsgSyscallName = "wsasendmsg"
    24  )
    25  
    26  func init() {
    27  	poll.InitWSA()
    28  }
    29  
    30  
    31  
    32  func canUseConnectEx(net string) bool {
    33  	switch net {
    34  	case "tcp", "tcp4", "tcp6":
    35  		return true
    36  	}
    37  	
    38  	return false
    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  	if err := fd.pfd.Init(fd.net, true); err != nil {
    57  		return err
    58  	}
    59  	switch fd.net {
    60  	case "udp", "udp4", "udp6":
    61  		
    62  		
    63  		ret := uint32(0)
    64  		flag := uint32(0)
    65  		size := uint32(unsafe.Sizeof(flag))
    66  		err := syscall.WSAIoctl(fd.pfd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
    67  		if err != nil {
    68  			return wrapSyscallError("wsaioctl", err)
    69  		}
    70  		
    71  		
    72  		ret = 0
    73  		flag = 0
    74  		size = uint32(unsafe.Sizeof(flag))
    75  		err = syscall.WSAIoctl(fd.pfd.Sysfd, windows.SIO_UDP_NETRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
    76  		if err != nil {
    77  			return wrapSyscallError("wsaioctl", err)
    78  		}
    79  	}
    80  	return nil
    81  }
    82  
    83  
    84  func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
    85  	
    86  	
    87  	
    88  	if err := fd.init(); err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if ctx.Done() != nil {
    93  		
    94  		
    95  		
    96  		
    97  		defer fd.pfd.SetWriteDeadline(noDeadline)
    98  
    99  		if ctx.Err() != nil {
   100  			fd.pfd.SetWriteDeadline(aLongTimeAgo)
   101  		} else {
   102  			if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
   103  				fd.pfd.SetWriteDeadline(deadline)
   104  			}
   105  
   106  			done := make(chan struct{})
   107  			stop := context.AfterFunc(ctx, func() {
   108  				
   109  				
   110  				fd.pfd.SetWriteDeadline(aLongTimeAgo)
   111  				close(done)
   112  			})
   113  			defer func() {
   114  				if !stop() {
   115  					
   116  					
   117  					<-done
   118  				}
   119  			}()
   120  		}
   121  	}
   122  
   123  	if !canUseConnectEx(fd.net) {
   124  		err := connectFunc(fd.pfd.Sysfd, ra)
   125  		return nil, os.NewSyscallError("connect", err)
   126  	}
   127  	
   128  	if la == nil {
   129  		switch ra.(type) {
   130  		case *syscall.SockaddrInet4:
   131  			la = &syscall.SockaddrInet4{}
   132  		case *syscall.SockaddrInet6:
   133  			la = &syscall.SockaddrInet6{}
   134  		default:
   135  			panic("unexpected type in connect")
   136  		}
   137  		if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
   138  			return nil, os.NewSyscallError("bind", err)
   139  		}
   140  	}
   141  
   142  	var isloopback bool
   143  	switch ra := ra.(type) {
   144  	case *syscall.SockaddrInet4:
   145  		isloopback = ra.Addr[0] == 127
   146  	case *syscall.SockaddrInet6:
   147  		isloopback = ra.Addr == [16]byte(IPv6loopback)
   148  	default:
   149  		panic("unexpected type in connect")
   150  	}
   151  	if isloopback {
   152  		
   153  		
   154  		params := windows.TCP_INITIAL_RTO_PARAMETERS{
   155  			Rtt:                   windows.TCP_INITIAL_RTO_UNSPECIFIED_RTT, 
   156  			MaxSynRetransmissions: 1,                                       
   157  		}
   158  		if windows.SupportTCPInitialRTONoSYNRetransmissions() {
   159  			
   160  			params.MaxSynRetransmissions = windows.TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
   161  		}
   162  		var out uint32
   163  		
   164  		
   165  		_ = fd.pfd.WSAIoctl(windows.SIO_TCP_INITIAL_RTO, (*byte)(unsafe.Pointer(¶ms)), uint32(unsafe.Sizeof(params)), nil, 0, &out, nil, 0)
   166  	}
   167  
   168  	
   169  	if err := fd.pfd.ConnectEx(ra); err != nil {
   170  		select {
   171  		case <-ctx.Done():
   172  			return nil, mapErr(ctx.Err())
   173  		default:
   174  			if _, ok := err.(syscall.Errno); ok {
   175  				err = os.NewSyscallError("connectex", err)
   176  			}
   177  			return nil, err
   178  		}
   179  	}
   180  	
   181  	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))))
   182  }
   183  
   184  func (c *conn) writeBuffers(v *Buffers) (int64, error) {
   185  	if !c.ok() {
   186  		return 0, syscall.EINVAL
   187  	}
   188  	n, err := c.fd.writeBuffers(v)
   189  	if err != nil {
   190  		return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   191  	}
   192  	return n, nil
   193  }
   194  
   195  func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
   196  	n, err := fd.pfd.Writev((*[][]byte)(buf))
   197  	runtime.KeepAlive(fd)
   198  	return n, wrapSyscallError("wsasend", err)
   199  }
   200  
   201  func (fd *netFD) accept() (*netFD, error) {
   202  	s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
   203  		return sysSocket(fd.family, fd.sotype, 0)
   204  	})
   205  
   206  	if err != nil {
   207  		if errcall != "" {
   208  			err = wrapSyscallError(errcall, err)
   209  		}
   210  		return nil, err
   211  	}
   212  
   213  	
   214  	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
   215  	if err != nil {
   216  		poll.CloseFunc(s)
   217  		return nil, err
   218  	}
   219  	if err := netfd.init(); err != nil {
   220  		fd.Close()
   221  		return nil, err
   222  	}
   223  
   224  	
   225  	var lrsa, rrsa *syscall.RawSockaddrAny
   226  	var llen, rlen int32
   227  	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
   228  		0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
   229  	lsa, _ := lrsa.Sockaddr()
   230  	rsa, _ := rrsa.Sockaddr()
   231  
   232  	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
   233  	return netfd, nil
   234  }
   235  
   236  
   237  func newWindowsFile(h syscall.Handle, name string) *os.File
   238  
   239  func (fd *netFD) dup() (*os.File, error) {
   240  	
   241  	
   242  	
   243  	if err := fd.pfd.DisassociateIOCP(); err != nil {
   244  		return nil, err
   245  	}
   246  	var h syscall.Handle
   247  	var syserr error
   248  	err := fd.pfd.RawControl(func(fd uintptr) {
   249  		h, syserr = dupSocket(syscall.Handle(fd))
   250  	})
   251  	if err != nil {
   252  		err = syserr
   253  	}
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	
   258  	
   259  	
   260  	return newWindowsFile(h, fd.name()), nil
   261  }
   262  
View as plain text