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
27
28 func canUseConnectEx(net string) bool {
29 switch net {
30 case "tcp", "tcp4", "tcp6":
31 return true
32 }
33
34 return false
35 }
36
37 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
38 ret := &netFD{
39 pfd: poll.FD{
40 Sysfd: sysfd,
41 IsStream: sotype == syscall.SOCK_STREAM,
42 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
43 },
44 family: family,
45 sotype: sotype,
46 net: net,
47 }
48 return ret, nil
49 }
50
51 func (fd *netFD) init() error {
52 errcall, err := fd.pfd.Init(fd.net, true)
53 if errcall != "" {
54 err = wrapSyscallError(errcall, err)
55 }
56 return err
57 }
58
59
60 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
61
62
63
64 if err := fd.init(); err != nil {
65 return nil, err
66 }
67 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
68 fd.pfd.SetWriteDeadline(deadline)
69 defer fd.pfd.SetWriteDeadline(noDeadline)
70 }
71 if !canUseConnectEx(fd.net) {
72 err := connectFunc(fd.pfd.Sysfd, ra)
73 return nil, os.NewSyscallError("connect", err)
74 }
75
76 if la == nil {
77 switch ra.(type) {
78 case *syscall.SockaddrInet4:
79 la = &syscall.SockaddrInet4{}
80 case *syscall.SockaddrInet6:
81 la = &syscall.SockaddrInet6{}
82 default:
83 panic("unexpected type in connect")
84 }
85 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
86 return nil, os.NewSyscallError("bind", err)
87 }
88 }
89
90 var isloopback bool
91 switch ra := ra.(type) {
92 case *syscall.SockaddrInet4:
93 isloopback = ra.Addr[0] == 127
94 case *syscall.SockaddrInet6:
95 isloopback = ra.Addr == [16]byte(IPv6loopback)
96 default:
97 panic("unexpected type in connect")
98 }
99 if isloopback {
100
101
102 params := windows.TCP_INITIAL_RTO_PARAMETERS{
103 Rtt: windows.TCP_INITIAL_RTO_UNSPECIFIED_RTT,
104 MaxSynRetransmissions: 1,
105 }
106 if windows.Support_TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS() {
107
108 params.MaxSynRetransmissions = windows.TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
109 }
110 var out uint32
111
112
113 _ = fd.pfd.WSAIoctl(windows.SIO_TCP_INITIAL_RTO, (*byte)(unsafe.Pointer(¶ms)), uint32(unsafe.Sizeof(params)), nil, 0, &out, nil, 0)
114 }
115
116
117
118
119 done := make(chan bool)
120 defer func() { done <- true }()
121 go func() {
122 select {
123 case <-ctx.Done():
124
125
126 fd.pfd.SetWriteDeadline(aLongTimeAgo)
127 <-done
128 case <-done:
129 }
130 }()
131
132
133 if err := fd.pfd.ConnectEx(ra); err != nil {
134 select {
135 case <-ctx.Done():
136 return nil, mapErr(ctx.Err())
137 default:
138 if _, ok := err.(syscall.Errno); ok {
139 err = os.NewSyscallError("connectex", err)
140 }
141 return nil, err
142 }
143 }
144
145 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))))
146 }
147
148 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
149 if !c.ok() {
150 return 0, syscall.EINVAL
151 }
152 n, err := c.fd.writeBuffers(v)
153 if err != nil {
154 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
155 }
156 return n, nil
157 }
158
159 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
160 n, err := fd.pfd.Writev((*[][]byte)(buf))
161 runtime.KeepAlive(fd)
162 return n, wrapSyscallError("wsasend", err)
163 }
164
165 func (fd *netFD) accept() (*netFD, error) {
166 s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
167 return sysSocket(fd.family, fd.sotype, 0)
168 })
169
170 if err != nil {
171 if errcall != "" {
172 err = wrapSyscallError(errcall, err)
173 }
174 return nil, err
175 }
176
177
178 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
179 if err != nil {
180 poll.CloseFunc(s)
181 return nil, err
182 }
183 if err := netfd.init(); err != nil {
184 fd.Close()
185 return nil, err
186 }
187
188
189 var lrsa, rrsa *syscall.RawSockaddrAny
190 var llen, rlen int32
191 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
192 0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
193 lsa, _ := lrsa.Sockaddr()
194 rsa, _ := rrsa.Sockaddr()
195
196 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
197 return netfd, nil
198 }
199
200
201
202 func (fd *netFD) dup() (*os.File, error) {
203
204 return nil, syscall.EWINDOWS
205 }
206
View as plain text