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 return nil
72 }
73
74
75 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
76
77
78
79 if err := fd.init(); err != nil {
80 return nil, err
81 }
82
83 if ctx.Done() != nil {
84
85
86
87
88 defer fd.pfd.SetWriteDeadline(noDeadline)
89
90 if ctx.Err() != nil {
91 fd.pfd.SetWriteDeadline(aLongTimeAgo)
92 } else {
93 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
94 fd.pfd.SetWriteDeadline(deadline)
95 }
96
97 done := make(chan struct{})
98 stop := context.AfterFunc(ctx, func() {
99
100
101 fd.pfd.SetWriteDeadline(aLongTimeAgo)
102 close(done)
103 })
104 defer func() {
105 if !stop() {
106
107
108 <-done
109 }
110 }()
111 }
112 }
113
114 if !canUseConnectEx(fd.net) {
115 err := connectFunc(fd.pfd.Sysfd, ra)
116 return nil, os.NewSyscallError("connect", err)
117 }
118
119 if la == nil {
120 switch ra.(type) {
121 case *syscall.SockaddrInet4:
122 la = &syscall.SockaddrInet4{}
123 case *syscall.SockaddrInet6:
124 la = &syscall.SockaddrInet6{}
125 default:
126 panic("unexpected type in connect")
127 }
128 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
129 return nil, os.NewSyscallError("bind", err)
130 }
131 }
132
133 var isloopback bool
134 switch ra := ra.(type) {
135 case *syscall.SockaddrInet4:
136 isloopback = ra.Addr[0] == 127
137 case *syscall.SockaddrInet6:
138 isloopback = ra.Addr == [16]byte(IPv6loopback)
139 default:
140 panic("unexpected type in connect")
141 }
142 if isloopback {
143
144
145 params := windows.TCP_INITIAL_RTO_PARAMETERS{
146 Rtt: windows.TCP_INITIAL_RTO_UNSPECIFIED_RTT,
147 MaxSynRetransmissions: 1,
148 }
149 if windows.SupportTCPInitialRTONoSYNRetransmissions() {
150
151 params.MaxSynRetransmissions = windows.TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
152 }
153 var out uint32
154
155
156 _ = fd.pfd.WSAIoctl(windows.SIO_TCP_INITIAL_RTO, (*byte)(unsafe.Pointer(¶ms)), uint32(unsafe.Sizeof(params)), nil, 0, &out, nil, 0)
157 }
158
159
160 if err := fd.pfd.ConnectEx(ra); err != nil {
161 select {
162 case <-ctx.Done():
163 return nil, mapErr(ctx.Err())
164 default:
165 if _, ok := err.(syscall.Errno); ok {
166 err = os.NewSyscallError("connectex", err)
167 }
168 return nil, err
169 }
170 }
171
172 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))))
173 }
174
175 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
176 if !c.ok() {
177 return 0, syscall.EINVAL
178 }
179 n, err := c.fd.writeBuffers(v)
180 if err != nil {
181 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
182 }
183 return n, nil
184 }
185
186 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
187 n, err := fd.pfd.Writev((*[][]byte)(buf))
188 runtime.KeepAlive(fd)
189 return n, wrapSyscallError("wsasend", 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
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
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
228
229 func (fd *netFD) dup() (*os.File, error) {
230
231 return nil, syscall.EWINDOWS
232 }
233
View as plain text