testsuite: g++.dg: debug: fix test filenames
[official-gcc.git] / libgo / go / net / fd_windows.go
blob030b6a15fb5123ca9bd3f2207afaafe76b489a7a
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 const (
17 readSyscallName = "wsarecv"
18 readFromSyscallName = "wsarecvfrom"
19 readMsgSyscallName = "wsarecvmsg"
20 writeSyscallName = "wsasend"
21 writeToSyscallName = "wsasendto"
22 writeMsgSyscallName = "wsasendmsg"
25 // canUseConnectEx reports whether we can use the ConnectEx Windows API call
26 // for the given network type.
27 func canUseConnectEx(net string) bool {
28 switch net {
29 case "tcp", "tcp4", "tcp6":
30 return true
32 // ConnectEx windows API does not support connectionless sockets.
33 return false
36 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
37 ret := &netFD{
38 pfd: poll.FD{
39 Sysfd: sysfd,
40 IsStream: sotype == syscall.SOCK_STREAM,
41 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
43 family: family,
44 sotype: sotype,
45 net: net,
47 return ret, nil
50 func (fd *netFD) init() error {
51 errcall, err := fd.pfd.Init(fd.net, true)
52 if errcall != "" {
53 err = wrapSyscallError(errcall, err)
55 return err
58 // Always returns nil for connected peer address result.
59 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
60 // Do not need to call fd.writeLock here,
61 // because fd is not yet accessible to user,
62 // so no concurrent operations are possible.
63 if err := fd.init(); err != nil {
64 return nil, err
66 if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
67 fd.pfd.SetWriteDeadline(deadline)
68 defer fd.pfd.SetWriteDeadline(noDeadline)
70 if !canUseConnectEx(fd.net) {
71 err := connectFunc(fd.pfd.Sysfd, ra)
72 return nil, os.NewSyscallError("connect", err)
74 // ConnectEx windows API requires an unconnected, previously bound socket.
75 if la == nil {
76 switch ra.(type) {
77 case *syscall.SockaddrInet4:
78 la = &syscall.SockaddrInet4{}
79 case *syscall.SockaddrInet6:
80 la = &syscall.SockaddrInet6{}
81 default:
82 panic("unexpected type in connect")
84 if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
85 return nil, os.NewSyscallError("bind", err)
89 // Wait for the goroutine converting context.Done into a write timeout
90 // to exist, otherwise our caller might cancel the context and
91 // cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
92 done := make(chan bool) // must be unbuffered
93 defer func() { done <- true }()
94 go func() {
95 select {
96 case <-ctx.Done():
97 // Force the runtime's poller to immediately give
98 // up waiting for writability.
99 fd.pfd.SetWriteDeadline(aLongTimeAgo)
100 <-done
101 case <-done:
105 // Call ConnectEx API.
106 if err := fd.pfd.ConnectEx(ra); err != nil {
107 select {
108 case <-ctx.Done():
109 return nil, mapErr(ctx.Err())
110 default:
111 if _, ok := err.(syscall.Errno); ok {
112 err = os.NewSyscallError("connectex", err)
114 return nil, err
117 // Refresh socket properties.
118 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))))
121 func (c *conn) writeBuffers(v *Buffers) (int64, error) {
122 if !c.ok() {
123 return 0, syscall.EINVAL
125 n, err := c.fd.writeBuffers(v)
126 if err != nil {
127 return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
129 return n, nil
132 func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
133 n, err := fd.pfd.Writev((*[][]byte)(buf))
134 runtime.KeepAlive(fd)
135 return n, wrapSyscallError("wsasend", err)
138 func (fd *netFD) accept() (*netFD, error) {
139 s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
140 return sysSocket(fd.family, fd.sotype, 0)
143 if err != nil {
144 if errcall != "" {
145 err = wrapSyscallError(errcall, err)
147 return nil, err
150 // Associate our new socket with IOCP.
151 netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
152 if err != nil {
153 poll.CloseFunc(s)
154 return nil, err
156 if err := netfd.init(); err != nil {
157 fd.Close()
158 return nil, err
161 // Get local and peer addr out of AcceptEx buffer.
162 var lrsa, rrsa *syscall.RawSockaddrAny
163 var llen, rlen int32
164 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
165 0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
166 lsa, _ := lrsa.Sockaddr()
167 rsa, _ := rrsa.Sockaddr()
169 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
170 return netfd, nil
173 // Unimplemented functions.
175 func (fd *netFD) dup() (*os.File, error) {
176 // TODO: Implement this
177 return nil, syscall.EWINDOWS