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