Fix "PR c++/92804 ICE trying to use concept as a nested-name-specifier"
[official-gcc.git] / libgo / go / net / fd_windows.go
blob3cc4c7a6a2267746042df2cd8a527ab66d524507
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package net
7 import (
8 "context"
9 "internal/poll"
10 "os"
11 "runtime"
12 "syscall"
13 "time"
14 "unsafe"
17 // canUseConnectEx reports whether we can use the ConnectEx Windows API call
18 // for the given network type.
19 func canUseConnectEx(net string) bool {
20 switch net {
21 case "tcp", "tcp4", "tcp6":
22 return true
24 // ConnectEx windows API does not support connectionless sockets.
25 return false
28 // Network file descriptor.
29 type netFD struct {
30 pfd poll.FD
32 // immutable until Close
33 family int
34 sotype int
35 isConnected bool // handshake completed or use of association with peer
36 net string
37 laddr Addr
38 raddr Addr
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,
48 family: family,
49 sotype: sotype,
50 net: net,
52 return ret, nil
55 func (fd *netFD) init() error {
56 errcall, err := fd.pfd.Init(fd.net, true)
57 if errcall != "" {
58 err = wrapSyscallError(errcall, err)
60 return err
63 func (fd *netFD) setAddr(laddr, raddr Addr) {
64 fd.laddr = laddr
65 fd.raddr = raddr
66 runtime.SetFinalizer(fd, (*netFD).Close)
69 // Always returns nil for connected peer address result.
70 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
71 // Do not need to call fd.writeLock here,
72 // because fd is not yet accessible to user,
73 // so no concurrent operations are possible.
74 if err := fd.init(); err != nil {
75 return nil, err
77 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
78 fd.pfd.SetWriteDeadline(deadline)
79 defer fd.pfd.SetWriteDeadline(noDeadline)
81 if !canUseConnectEx(fd.net) {
82 err := connectFunc(fd.pfd.Sysfd, ra)
83 return nil, os.NewSyscallError("connect", err)
85 // ConnectEx windows API requires an unconnected, previously bound socket.
86 if la == nil {
87 switch ra.(type) {
88 case *syscall.SockaddrInet4:
89 la = &syscall.SockaddrInet4{}
90 case *syscall.SockaddrInet6:
91 la = &syscall.SockaddrInet6{}
92 default:
93 panic("unexpected type in connect")
95 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
96 return nil, os.NewSyscallError("bind", err)
100 // Wait for the goroutine converting context.Done into a write timeout
101 // to exist, otherwise our caller might cancel the context and
102 // cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
103 done := make(chan bool) // must be unbuffered
104 defer func() { done <- true }()
105 go func() {
106 select {
107 case <-ctx.Done():
108 // Force the runtime's poller to immediately give
109 // up waiting for writability.
110 fd.pfd.SetWriteDeadline(aLongTimeAgo)
111 <-done
112 case <-done:
116 // Call ConnectEx API.
117 if err := fd.pfd.ConnectEx(ra); err != nil {
118 select {
119 case <-ctx.Done():
120 return nil, mapErr(ctx.Err())
121 default:
122 if _, ok := err.(syscall.Errno); ok {
123 err = os.NewSyscallError("connectex", err)
125 return nil, err
128 // Refresh socket properties.
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))))
132 func (fd *netFD) Close() error {
133 runtime.SetFinalizer(fd, nil)
134 return fd.pfd.Close()
137 func (fd *netFD) shutdown(how int) error {
138 err := fd.pfd.Shutdown(how)
139 runtime.KeepAlive(fd)
140 return err
143 func (fd *netFD) closeRead() error {
144 return fd.shutdown(syscall.SHUT_RD)
147 func (fd *netFD) closeWrite() error {
148 return fd.shutdown(syscall.SHUT_WR)
151 func (fd *netFD) Read(buf []byte) (int, error) {
152 n, err := fd.pfd.Read(buf)
153 runtime.KeepAlive(fd)
154 return n, wrapSyscallError("wsarecv", err)
157 func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
158 n, sa, err := fd.pfd.ReadFrom(buf)
159 runtime.KeepAlive(fd)
160 return n, sa, wrapSyscallError("wsarecvfrom", err)
163 func (fd *netFD) Write(buf []byte) (int, error) {
164 n, err := fd.pfd.Write(buf)
165 runtime.KeepAlive(fd)
166 return n, wrapSyscallError("wsasend", err)
169 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
170 if !c.ok() {
171 return 0, syscall.EINVAL
173 n, err := c.fd.writeBuffers(v)
174 if err != nil {
175 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
177 return n, nil
180 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
181 n, err := fd.pfd.Writev((*[][]byte)(buf))
182 runtime.KeepAlive(fd)
183 return n, wrapSyscallError("wsasend", err)
186 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
187 n, err := fd.pfd.WriteTo(buf, sa)
188 runtime.KeepAlive(fd)
189 return n, wrapSyscallError("wsasendto", err)
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)
197 if err != nil {
198 if errcall != "" {
199 err = wrapSyscallError(errcall, err)
201 return nil, err
204 // Associate our new socket with IOCP.
205 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
206 if err != nil {
207 poll.CloseFunc(s)
208 return nil, err
210 if err := netfd.init(); err != nil {
211 fd.Close()
212 return nil, err
215 // Get local and peer addr out of AcceptEx buffer.
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()
223 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
224 return netfd, nil
227 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
228 n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
229 runtime.KeepAlive(fd)
230 return n, oobn, flags, sa, wrapSyscallError("wsarecvmsg", err)
233 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
234 n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
235 runtime.KeepAlive(fd)
236 return n, oobn, wrapSyscallError("wsasendmsg", err)
239 // Unimplemented functions.
241 func (fd *netFD) dup() (*os.File, error) {
242 // TODO: Implement this
243 return nil, syscall.EWINDOWS
246 func (fd *netFD) SetDeadline(t time.Time) error {
247 return fd.pfd.SetDeadline(t)
250 func (fd *netFD) SetReadDeadline(t time.Time) error {
251 return fd.pfd.SetReadDeadline(t)
254 func (fd *netFD) SetWriteDeadline(t time.Time) error {
255 return fd.pfd.SetWriteDeadline(t)