annotate libgo/go/net/fd_windows.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2010 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 package net
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 import (
kono
parents:
diff changeset
8 "context"
kono
parents:
diff changeset
9 "internal/poll"
kono
parents:
diff changeset
10 "os"
kono
parents:
diff changeset
11 "runtime"
kono
parents:
diff changeset
12 "syscall"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
13 "time"
111
kono
parents:
diff changeset
14 "unsafe"
kono
parents:
diff changeset
15 )
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 // canUseConnectEx reports whether we can use the ConnectEx Windows API call
kono
parents:
diff changeset
18 // for the given network type.
kono
parents:
diff changeset
19 func canUseConnectEx(net string) bool {
kono
parents:
diff changeset
20 switch net {
kono
parents:
diff changeset
21 case "tcp", "tcp4", "tcp6":
kono
parents:
diff changeset
22 return true
kono
parents:
diff changeset
23 }
kono
parents:
diff changeset
24 // ConnectEx windows API does not support connectionless sockets.
kono
parents:
diff changeset
25 return false
kono
parents:
diff changeset
26 }
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 // Network file descriptor.
kono
parents:
diff changeset
29 type netFD struct {
kono
parents:
diff changeset
30 pfd poll.FD
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 // immutable until Close
kono
parents:
diff changeset
33 family int
kono
parents:
diff changeset
34 sotype int
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
35 isConnected bool // handshake completed or use of association with peer
111
kono
parents:
diff changeset
36 net string
kono
parents:
diff changeset
37 laddr Addr
kono
parents:
diff changeset
38 raddr Addr
kono
parents:
diff changeset
39 }
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
kono
parents:
diff changeset
42 ret := &netFD{
kono
parents:
diff changeset
43 pfd: poll.FD{
kono
parents:
diff changeset
44 Sysfd: sysfd,
kono
parents:
diff changeset
45 IsStream: sotype == syscall.SOCK_STREAM,
kono
parents:
diff changeset
46 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
kono
parents:
diff changeset
47 },
kono
parents:
diff changeset
48 family: family,
kono
parents:
diff changeset
49 sotype: sotype,
kono
parents:
diff changeset
50 net: net,
kono
parents:
diff changeset
51 }
kono
parents:
diff changeset
52 return ret, nil
kono
parents:
diff changeset
53 }
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 func (fd *netFD) init() error {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
56 errcall, err := fd.pfd.Init(fd.net, true)
111
kono
parents:
diff changeset
57 if errcall != "" {
kono
parents:
diff changeset
58 err = wrapSyscallError(errcall, err)
kono
parents:
diff changeset
59 }
kono
parents:
diff changeset
60 return err
kono
parents:
diff changeset
61 }
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 func (fd *netFD) setAddr(laddr, raddr Addr) {
kono
parents:
diff changeset
64 fd.laddr = laddr
kono
parents:
diff changeset
65 fd.raddr = raddr
kono
parents:
diff changeset
66 runtime.SetFinalizer(fd, (*netFD).Close)
kono
parents:
diff changeset
67 }
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 // Always returns nil for connected peer address result.
kono
parents:
diff changeset
70 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
kono
parents:
diff changeset
71 // Do not need to call fd.writeLock here,
kono
parents:
diff changeset
72 // because fd is not yet accessible to user,
kono
parents:
diff changeset
73 // so no concurrent operations are possible.
kono
parents:
diff changeset
74 if err := fd.init(); err != nil {
kono
parents:
diff changeset
75 return nil, err
kono
parents:
diff changeset
76 }
kono
parents:
diff changeset
77 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
kono
parents:
diff changeset
78 fd.pfd.SetWriteDeadline(deadline)
kono
parents:
diff changeset
79 defer fd.pfd.SetWriteDeadline(noDeadline)
kono
parents:
diff changeset
80 }
kono
parents:
diff changeset
81 if !canUseConnectEx(fd.net) {
kono
parents:
diff changeset
82 err := connectFunc(fd.pfd.Sysfd, ra)
kono
parents:
diff changeset
83 return nil, os.NewSyscallError("connect", err)
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85 // ConnectEx windows API requires an unconnected, previously bound socket.
kono
parents:
diff changeset
86 if la == nil {
kono
parents:
diff changeset
87 switch ra.(type) {
kono
parents:
diff changeset
88 case *syscall.SockaddrInet4:
kono
parents:
diff changeset
89 la = &syscall.SockaddrInet4{}
kono
parents:
diff changeset
90 case *syscall.SockaddrInet6:
kono
parents:
diff changeset
91 la = &syscall.SockaddrInet6{}
kono
parents:
diff changeset
92 default:
kono
parents:
diff changeset
93 panic("unexpected type in connect")
kono
parents:
diff changeset
94 }
kono
parents:
diff changeset
95 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
kono
parents:
diff changeset
96 return nil, os.NewSyscallError("bind", err)
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98 }
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 // Wait for the goroutine converting context.Done into a write timeout
kono
parents:
diff changeset
101 // to exist, otherwise our caller might cancel the context and
kono
parents:
diff changeset
102 // cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
kono
parents:
diff changeset
103 done := make(chan bool) // must be unbuffered
kono
parents:
diff changeset
104 defer func() { done <- true }()
kono
parents:
diff changeset
105 go func() {
kono
parents:
diff changeset
106 select {
kono
parents:
diff changeset
107 case <-ctx.Done():
kono
parents:
diff changeset
108 // Force the runtime's poller to immediately give
kono
parents:
diff changeset
109 // up waiting for writability.
kono
parents:
diff changeset
110 fd.pfd.SetWriteDeadline(aLongTimeAgo)
kono
parents:
diff changeset
111 <-done
kono
parents:
diff changeset
112 case <-done:
kono
parents:
diff changeset
113 }
kono
parents:
diff changeset
114 }()
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 // Call ConnectEx API.
kono
parents:
diff changeset
117 if err := fd.pfd.ConnectEx(ra); err != nil {
kono
parents:
diff changeset
118 select {
kono
parents:
diff changeset
119 case <-ctx.Done():
kono
parents:
diff changeset
120 return nil, mapErr(ctx.Err())
kono
parents:
diff changeset
121 default:
kono
parents:
diff changeset
122 if _, ok := err.(syscall.Errno); ok {
kono
parents:
diff changeset
123 err = os.NewSyscallError("connectex", err)
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125 return nil, err
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128 // Refresh socket properties.
kono
parents:
diff changeset
129 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))))
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 func (fd *netFD) Close() error {
kono
parents:
diff changeset
133 runtime.SetFinalizer(fd, nil)
kono
parents:
diff changeset
134 return fd.pfd.Close()
kono
parents:
diff changeset
135 }
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 func (fd *netFD) shutdown(how int) error {
kono
parents:
diff changeset
138 err := fd.pfd.Shutdown(how)
kono
parents:
diff changeset
139 runtime.KeepAlive(fd)
kono
parents:
diff changeset
140 return err
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 func (fd *netFD) closeRead() error {
kono
parents:
diff changeset
144 return fd.shutdown(syscall.SHUT_RD)
kono
parents:
diff changeset
145 }
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 func (fd *netFD) closeWrite() error {
kono
parents:
diff changeset
148 return fd.shutdown(syscall.SHUT_WR)
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 func (fd *netFD) Read(buf []byte) (int, error) {
kono
parents:
diff changeset
152 n, err := fd.pfd.Read(buf)
kono
parents:
diff changeset
153 runtime.KeepAlive(fd)
kono
parents:
diff changeset
154 return n, wrapSyscallError("wsarecv", err)
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
kono
parents:
diff changeset
158 n, sa, err := fd.pfd.ReadFrom(buf)
kono
parents:
diff changeset
159 runtime.KeepAlive(fd)
kono
parents:
diff changeset
160 return n, sa, wrapSyscallError("wsarecvfrom", err)
kono
parents:
diff changeset
161 }
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 func (fd *netFD) Write(buf []byte) (int, error) {
kono
parents:
diff changeset
164 n, err := fd.pfd.Write(buf)
kono
parents:
diff changeset
165 runtime.KeepAlive(fd)
kono
parents:
diff changeset
166 return n, wrapSyscallError("wsasend", err)
kono
parents:
diff changeset
167 }
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
kono
parents:
diff changeset
170 if !c.ok() {
kono
parents:
diff changeset
171 return 0, syscall.EINVAL
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173 n, err := c.fd.writeBuffers(v)
kono
parents:
diff changeset
174 if err != nil {
kono
parents:
diff changeset
175 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
kono
parents:
diff changeset
176 }
kono
parents:
diff changeset
177 return n, nil
kono
parents:
diff changeset
178 }
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
kono
parents:
diff changeset
181 n, err := fd.pfd.Writev((*[][]byte)(buf))
kono
parents:
diff changeset
182 runtime.KeepAlive(fd)
kono
parents:
diff changeset
183 return n, wrapSyscallError("wsasend", err)
kono
parents:
diff changeset
184 }
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
kono
parents:
diff changeset
187 n, err := fd.pfd.WriteTo(buf, sa)
kono
parents:
diff changeset
188 runtime.KeepAlive(fd)
kono
parents:
diff changeset
189 return n, wrapSyscallError("wsasendto", err)
kono
parents:
diff changeset
190 }
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 func (fd *netFD) accept() (*netFD, error) {
kono
parents:
diff changeset
193 s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
kono
parents:
diff changeset
194 return sysSocket(fd.family, fd.sotype, 0)
kono
parents:
diff changeset
195 })
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 if err != nil {
kono
parents:
diff changeset
198 if errcall != "" {
kono
parents:
diff changeset
199 err = wrapSyscallError(errcall, err)
kono
parents:
diff changeset
200 }
kono
parents:
diff changeset
201 return nil, err
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 // Associate our new socket with IOCP.
kono
parents:
diff changeset
205 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
kono
parents:
diff changeset
206 if err != nil {
kono
parents:
diff changeset
207 poll.CloseFunc(s)
kono
parents:
diff changeset
208 return nil, err
kono
parents:
diff changeset
209 }
kono
parents:
diff changeset
210 if err := netfd.init(); err != nil {
kono
parents:
diff changeset
211 fd.Close()
kono
parents:
diff changeset
212 return nil, err
kono
parents:
diff changeset
213 }
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 // Get local and peer addr out of AcceptEx buffer.
kono
parents:
diff changeset
216 var lrsa, rrsa *syscall.RawSockaddrAny
kono
parents:
diff changeset
217 var llen, rlen int32
kono
parents:
diff changeset
218 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
kono
parents:
diff changeset
219 0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
kono
parents:
diff changeset
220 lsa, _ := lrsa.Sockaddr()
kono
parents:
diff changeset
221 rsa, _ := rrsa.Sockaddr()
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
kono
parents:
diff changeset
224 return netfd, nil
kono
parents:
diff changeset
225 }
kono
parents:
diff changeset
226
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
227 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
228 n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
229 runtime.KeepAlive(fd)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
230 return n, oobn, flags, sa, wrapSyscallError("wsarecvmsg", err)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
231 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
232
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
233 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
234 n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
235 runtime.KeepAlive(fd)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
236 return n, oobn, wrapSyscallError("wsasendmsg", err)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
237 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
238
111
kono
parents:
diff changeset
239 // Unimplemented functions.
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 func (fd *netFD) dup() (*os.File, error) {
kono
parents:
diff changeset
242 // TODO: Implement this
kono
parents:
diff changeset
243 return nil, syscall.EWINDOWS
kono
parents:
diff changeset
244 }
kono
parents:
diff changeset
245
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
246 func (fd *netFD) SetDeadline(t time.Time) error {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
247 return fd.pfd.SetDeadline(t)
111
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
250 func (fd *netFD) SetReadDeadline(t time.Time) error {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
251 return fd.pfd.SetReadDeadline(t)
111
kono
parents:
diff changeset
252 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
253
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
254 func (fd *netFD) SetWriteDeadline(t time.Time) error {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
255 return fd.pfd.SetWriteDeadline(t)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
256 }