Fix "PR c++/92804 ICE trying to use concept as a nested-name-specifier"
[official-gcc.git] / libgo / go / net / sock_posix.go
blob8fe9bc74871ff4ef8add77a31bf7160bb0bb888a
1 // Copyright 2009 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 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
7 package net
9 import (
10 "context"
11 "internal/poll"
12 "os"
13 "syscall"
16 // socket returns a network file descriptor that is ready for
17 // asynchronous I/O using the network poller.
18 func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) (fd *netFD, err error) {
19 s, err := sysSocket(family, sotype, proto)
20 if err != nil {
21 return nil, err
23 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
24 poll.CloseFunc(s)
25 return nil, err
27 if fd, err = newFD(s, family, sotype, net); err != nil {
28 poll.CloseFunc(s)
29 return nil, err
32 // This function makes a network file descriptor for the
33 // following applications:
35 // - An endpoint holder that opens a passive stream
36 // connection, known as a stream listener
38 // - An endpoint holder that opens a destination-unspecific
39 // datagram connection, known as a datagram listener
41 // - An endpoint holder that opens an active stream or a
42 // destination-specific datagram connection, known as a
43 // dialer
45 // - An endpoint holder that opens the other connection, such
46 // as talking to the protocol stack inside the kernel
48 // For stream and datagram listeners, they will only require
49 // named sockets, so we can assume that it's just a request
50 // from stream or datagram listeners when laddr is not nil but
51 // raddr is nil. Otherwise we assume it's just for dialers or
52 // the other connection holders.
54 if laddr != nil && raddr == nil {
55 switch sotype {
56 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
57 if err := fd.listenStream(laddr, listenerBacklog(), ctrlFn); err != nil {
58 fd.Close()
59 return nil, err
61 return fd, nil
62 case syscall.SOCK_DGRAM:
63 if err := fd.listenDatagram(laddr, ctrlFn); err != nil {
64 fd.Close()
65 return nil, err
67 return fd, nil
70 if err := fd.dial(ctx, laddr, raddr, ctrlFn); err != nil {
71 fd.Close()
72 return nil, err
74 return fd, nil
77 func (fd *netFD) ctrlNetwork() string {
78 switch fd.net {
79 case "unix", "unixgram", "unixpacket":
80 return fd.net
82 switch fd.net[len(fd.net)-1] {
83 case '4', '6':
84 return fd.net
86 if fd.family == syscall.AF_INET {
87 return fd.net + "4"
89 return fd.net + "6"
92 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
93 switch fd.family {
94 case syscall.AF_INET, syscall.AF_INET6:
95 switch fd.sotype {
96 case syscall.SOCK_STREAM:
97 return sockaddrToTCP
98 case syscall.SOCK_DGRAM:
99 return sockaddrToUDP
100 case syscall.SOCK_RAW:
101 return sockaddrToIP
103 case syscall.AF_UNIX:
104 switch fd.sotype {
105 case syscall.SOCK_STREAM:
106 return sockaddrToUnix
107 case syscall.SOCK_DGRAM:
108 return sockaddrToUnixgram
109 case syscall.SOCK_SEQPACKET:
110 return sockaddrToUnixpacket
113 return func(syscall.Sockaddr) Addr { return nil }
116 func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) error {
117 if ctrlFn != nil {
118 c, err := newRawConn(fd)
119 if err != nil {
120 return err
122 var ctrlAddr string
123 if raddr != nil {
124 ctrlAddr = raddr.String()
125 } else if laddr != nil {
126 ctrlAddr = laddr.String()
128 if err := ctrlFn(fd.ctrlNetwork(), ctrlAddr, c); err != nil {
129 return err
132 var err error
133 var lsa syscall.Sockaddr
134 if laddr != nil {
135 if lsa, err = laddr.sockaddr(fd.family); err != nil {
136 return err
137 } else if lsa != nil {
138 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
139 return os.NewSyscallError("bind", err)
143 var rsa syscall.Sockaddr // remote address from the user
144 var crsa syscall.Sockaddr // remote address we actually connected to
145 if raddr != nil {
146 if rsa, err = raddr.sockaddr(fd.family); err != nil {
147 return err
149 if crsa, err = fd.connect(ctx, lsa, rsa); err != nil {
150 return err
152 fd.isConnected = true
153 } else {
154 if err := fd.init(); err != nil {
155 return err
158 // Record the local and remote addresses from the actual socket.
159 // Get the local address by calling Getsockname.
160 // For the remote address, use
161 // 1) the one returned by the connect method, if any; or
162 // 2) the one from Getpeername, if it succeeds; or
163 // 3) the one passed to us as the raddr parameter.
164 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
165 if crsa != nil {
166 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
167 } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
168 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
169 } else {
170 fd.setAddr(fd.addrFunc()(lsa), raddr)
172 return nil
175 func (fd *netFD) listenStream(laddr sockaddr, backlog int, ctrlFn func(string, string, syscall.RawConn) error) error {
176 var err error
177 if err = setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
178 return err
180 var lsa syscall.Sockaddr
181 if lsa, err = laddr.sockaddr(fd.family); err != nil {
182 return err
184 if ctrlFn != nil {
185 c, err := newRawConn(fd)
186 if err != nil {
187 return err
189 if err := ctrlFn(fd.ctrlNetwork(), laddr.String(), c); err != nil {
190 return err
193 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
194 return os.NewSyscallError("bind", err)
196 if err = listenFunc(fd.pfd.Sysfd, backlog); err != nil {
197 return os.NewSyscallError("listen", err)
199 if err = fd.init(); err != nil {
200 return err
202 lsa, err = syscall.Getsockname(fd.pfd.Sysfd)
203 if err != nil {
204 return os.NewSyscallError("getsockname", err)
206 fd.setAddr(fd.addrFunc()(lsa), nil)
207 return nil
210 func (fd *netFD) listenDatagram(laddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) error {
211 switch addr := laddr.(type) {
212 case *UDPAddr:
213 // We provide a socket that listens to a wildcard
214 // address with reusable UDP port when the given laddr
215 // is an appropriate UDP multicast address prefix.
216 // This makes it possible for a single UDP listener to
217 // join multiple different group addresses, for
218 // multiple UDP listeners that listen on the same UDP
219 // port to join the same group address.
220 if addr.IP != nil && addr.IP.IsMulticast() {
221 if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
222 return err
224 addr := *addr
225 switch fd.family {
226 case syscall.AF_INET:
227 addr.IP = IPv4zero
228 case syscall.AF_INET6:
229 addr.IP = IPv6unspecified
231 laddr = &addr
234 var err error
235 var lsa syscall.Sockaddr
236 if lsa, err = laddr.sockaddr(fd.family); err != nil {
237 return err
239 if ctrlFn != nil {
240 c, err := newRawConn(fd)
241 if err != nil {
242 return err
244 if err := ctrlFn(fd.ctrlNetwork(), laddr.String(), c); err != nil {
245 return err
248 if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
249 return os.NewSyscallError("bind", err)
251 if err = fd.init(); err != nil {
252 return err
254 lsa, err = syscall.Getsockname(fd.pfd.Sysfd)
255 if err != nil {
256 return os.NewSyscallError("getsockname", err)
258 fd.setAddr(fd.addrFunc()(lsa), nil)
259 return nil