libgo: update to go1.9
[official-gcc.git] / libgo / go / net / fd_windows.go
blobc2156b255e5abd0a36c780ba8ccfec18ee79c250
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 "unsafe"
16 // canUseConnectEx reports whether we can use the ConnectEx Windows API call
17 // for the given network type.
18 func canUseConnectEx(net string) bool {
19 switch net {
20 case "tcp", "tcp4", "tcp6":
21 return true
23 // ConnectEx windows API does not support connectionless sockets.
24 return false
27 // Network file descriptor.
28 type netFD struct {
29 pfd poll.FD
31 // immutable until Close
32 family int
33 sotype int
34 isConnected bool
35 net string
36 laddr Addr
37 raddr Addr
40 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
41 ret := &netFD{
42 pfd: poll.FD{
43 Sysfd: sysfd,
44 IsStream: sotype == syscall.SOCK_STREAM,
45 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
47 family: family,
48 sotype: sotype,
49 net: net,
51 return ret, nil
54 func (fd *netFD) init() error {
55 errcall, err := fd.pfd.Init(fd.net)
56 if errcall != "" {
57 err = wrapSyscallError(errcall, err)
59 return err
62 func (fd *netFD) setAddr(laddr, raddr Addr) {
63 fd.laddr = laddr
64 fd.raddr = raddr
65 runtime.SetFinalizer(fd, (*netFD).Close)
68 // Always returns nil for connected peer address result.
69 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
70 // Do not need to call fd.writeLock here,
71 // because fd is not yet accessible to user,
72 // so no concurrent operations are possible.
73 if err := fd.init(); err != nil {
74 return nil, err
76 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
77 fd.pfd.SetWriteDeadline(deadline)
78 defer fd.pfd.SetWriteDeadline(noDeadline)
80 if !canUseConnectEx(fd.net) {
81 err := connectFunc(fd.pfd.Sysfd, ra)
82 return nil, os.NewSyscallError("connect", err)
84 // ConnectEx windows API requires an unconnected, previously bound socket.
85 if la == nil {
86 switch ra.(type) {
87 case *syscall.SockaddrInet4:
88 la = &syscall.SockaddrInet4{}
89 case *syscall.SockaddrInet6:
90 la = &syscall.SockaddrInet6{}
91 default:
92 panic("unexpected type in connect")
94 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
95 return nil, os.NewSyscallError("bind", err)
99 // Wait for the goroutine converting context.Done into a write timeout
100 // to exist, otherwise our caller might cancel the context and
101 // cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
102 done := make(chan bool) // must be unbuffered
103 defer func() { done <- true }()
104 go func() {
105 select {
106 case <-ctx.Done():
107 // Force the runtime's poller to immediately give
108 // up waiting for writability.
109 fd.pfd.SetWriteDeadline(aLongTimeAgo)
110 <-done
111 case <-done:
115 // Call ConnectEx API.
116 if err := fd.pfd.ConnectEx(ra); err != nil {
117 select {
118 case <-ctx.Done():
119 return nil, mapErr(ctx.Err())
120 default:
121 if _, ok := err.(syscall.Errno); ok {
122 err = os.NewSyscallError("connectex", err)
124 return nil, err
127 // Refresh socket properties.
128 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))))
131 func (fd *netFD) Close() error {
132 runtime.SetFinalizer(fd, nil)
133 return fd.pfd.Close()
136 func (fd *netFD) shutdown(how int) error {
137 err := fd.pfd.Shutdown(how)
138 runtime.KeepAlive(fd)
139 return err
142 func (fd *netFD) closeRead() error {
143 return fd.shutdown(syscall.SHUT_RD)
146 func (fd *netFD) closeWrite() error {
147 return fd.shutdown(syscall.SHUT_WR)
150 func (fd *netFD) Read(buf []byte) (int, error) {
151 n, err := fd.pfd.Read(buf)
152 runtime.KeepAlive(fd)
153 return n, wrapSyscallError("wsarecv", err)
156 func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
157 n, sa, err := fd.pfd.ReadFrom(buf)
158 runtime.KeepAlive(fd)
159 return n, sa, wrapSyscallError("wsarecvfrom", err)
162 func (fd *netFD) Write(buf []byte) (int, error) {
163 n, err := fd.pfd.Write(buf)
164 runtime.KeepAlive(fd)
165 return n, wrapSyscallError("wsasend", err)
168 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
169 if !c.ok() {
170 return 0, syscall.EINVAL
172 n, err := c.fd.writeBuffers(v)
173 if err != nil {
174 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
176 return n, nil
179 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
180 n, err := fd.pfd.Writev((*[][]byte)(buf))
181 runtime.KeepAlive(fd)
182 return n, wrapSyscallError("wsasend", err)
185 func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
186 n, err := fd.pfd.WriteTo(buf, sa)
187 runtime.KeepAlive(fd)
188 return n, wrapSyscallError("wsasendto", err)
191 func (fd *netFD) accept() (*netFD, error) {
192 s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
193 return sysSocket(fd.family, fd.sotype, 0)
196 if err != nil {
197 if errcall != "" {
198 err = wrapSyscallError(errcall, err)
200 return nil, err
203 // Associate our new socket with IOCP.
204 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
205 if err != nil {
206 poll.CloseFunc(s)
207 return nil, err
209 if err := netfd.init(); err != nil {
210 fd.Close()
211 return nil, err
214 // Get local and peer addr out of AcceptEx buffer.
215 var lrsa, rrsa *syscall.RawSockaddrAny
216 var llen, rlen int32
217 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
218 0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
219 lsa, _ := lrsa.Sockaddr()
220 rsa, _ := rrsa.Sockaddr()
222 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
223 return netfd, nil
226 // Unimplemented functions.
228 func (fd *netFD) dup() (*os.File, error) {
229 // TODO: Implement this
230 return nil, syscall.EWINDOWS
233 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
234 return 0, 0, 0, nil, syscall.EWINDOWS
237 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
238 return 0, 0, syscall.EWINDOWS