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