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 linux nacl netbsd openbsd solaris windows
15 // A sockaddr represents a TCP, UDP, IP or Unix network endpoint
16 // address that can be converted into a syscall.Sockaddr.
17 type sockaddr
interface {
20 // family returns the platform-dependent address family
24 // isWildcard reports whether the address is a wildcard
28 // sockaddr returns the address converted into a syscall
29 // sockaddr type that implements syscall.Sockaddr
30 // interface. It returns a nil interface when the address is
32 sockaddr(family
int) (syscall
.Sockaddr
, error
)
34 // toLocal maps the zero address to a local system address (127.0.0.1 or ::1)
35 toLocal(net
string) sockaddr
38 // socket returns a network file descriptor that is ready for
39 // asynchronous I/O using the network poller.
40 func socket(ctx context
.Context
, net
string, family
, sotype
, proto
int, ipv6only
bool, laddr
, raddr sockaddr
) (fd
*netFD
, err error
) {
41 s
, err
:= sysSocket(family
, sotype
, proto
)
45 if err
= setDefaultSockopts(s
, family
, sotype
, ipv6only
); err
!= nil {
49 if fd
, err
= newFD(s
, family
, sotype
, net
); err
!= nil {
54 // This function makes a network file descriptor for the
55 // following applications:
57 // - An endpoint holder that opens a passive stream
58 // connection, known as a stream listener
60 // - An endpoint holder that opens a destination-unspecific
61 // datagram connection, known as a datagram listener
63 // - An endpoint holder that opens an active stream or a
64 // destination-specific datagram connection, known as a
67 // - An endpoint holder that opens the other connection, such
68 // as talking to the protocol stack inside the kernel
70 // For stream and datagram listeners, they will only require
71 // named sockets, so we can assume that it's just a request
72 // from stream or datagram listeners when laddr is not nil but
73 // raddr is nil. Otherwise we assume it's just for dialers or
74 // the other connection holders.
76 if laddr
!= nil && raddr
== nil {
78 case syscall
.SOCK_STREAM
, syscall
.SOCK_SEQPACKET
:
79 if err
:= fd
.listenStream(laddr
, listenerBacklog
); err
!= nil {
84 case syscall
.SOCK_DGRAM
:
85 if err
:= fd
.listenDatagram(laddr
); err
!= nil {
92 if err
:= fd
.dial(ctx
, laddr
, raddr
); err
!= nil {
99 func (fd
*netFD
) addrFunc() func(syscall
.Sockaddr
) Addr
{
101 case syscall
.AF_INET
, syscall
.AF_INET6
:
103 case syscall
.SOCK_STREAM
:
105 case syscall
.SOCK_DGRAM
:
107 case syscall
.SOCK_RAW
:
110 case syscall
.AF_UNIX
:
112 case syscall
.SOCK_STREAM
:
113 return sockaddrToUnix
114 case syscall
.SOCK_DGRAM
:
115 return sockaddrToUnixgram
116 case syscall
.SOCK_SEQPACKET
:
117 return sockaddrToUnixpacket
120 return func(syscall
.Sockaddr
) Addr
{ return nil }
123 func (fd
*netFD
) dial(ctx context
.Context
, laddr
, raddr sockaddr
) error
{
125 var lsa syscall
.Sockaddr
127 if lsa
, err
= laddr
.sockaddr(fd
.family
); err
!= nil {
129 } else if lsa
!= nil {
130 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
131 return os
.NewSyscallError("bind", err
)
135 var rsa syscall
.Sockaddr
137 if rsa
, err
= raddr
.sockaddr(fd
.family
); err
!= nil {
140 if err
:= fd
.connect(ctx
, lsa
, rsa
); err
!= nil {
143 fd
.isConnected
= true
145 if err
:= fd
.init(); err
!= nil {
149 lsa
, _
= syscall
.Getsockname(fd
.sysfd
)
150 if rsa
, _
= syscall
.Getpeername(fd
.sysfd
); rsa
!= nil {
151 fd
.setAddr(fd
.addrFunc()(lsa
), fd
.addrFunc()(rsa
))
153 fd
.setAddr(fd
.addrFunc()(lsa
), raddr
)
158 func (fd
*netFD
) listenStream(laddr sockaddr
, backlog
int) error
{
159 if err
:= setDefaultListenerSockopts(fd
.sysfd
); err
!= nil {
162 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
164 } else if lsa
!= nil {
165 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
166 return os
.NewSyscallError("bind", err
)
169 if err
:= listenFunc(fd
.sysfd
, backlog
); err
!= nil {
170 return os
.NewSyscallError("listen", err
)
172 if err
:= fd
.init(); err
!= nil {
175 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
176 fd
.setAddr(fd
.addrFunc()(lsa
), nil)
180 func (fd
*netFD
) listenDatagram(laddr sockaddr
) error
{
181 switch addr
:= laddr
.(type) {
183 // We provide a socket that listens to a wildcard
184 // address with reusable UDP port when the given laddr
185 // is an appropriate UDP multicast address prefix.
186 // This makes it possible for a single UDP listener to
187 // join multiple different group addresses, for
188 // multiple UDP listeners that listen on the same UDP
189 // port to join the same group address.
190 if addr
.IP
!= nil && addr
.IP
.IsMulticast() {
191 if err
:= setDefaultMulticastSockopts(fd
.sysfd
); err
!= nil {
196 case syscall
.AF_INET
:
198 case syscall
.AF_INET6
:
199 addr
.IP
= IPv6unspecified
204 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
206 } else if lsa
!= nil {
207 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
208 return os
.NewSyscallError("bind", err
)
211 if err
:= fd
.init(); err
!= nil {
214 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
215 fd
.setAddr(fd
.addrFunc()(lsa
), nil)