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 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 {
22 // family returns the platform-dependent address family
26 // isWildcard reports whether the address is a wildcard
30 // sockaddr returns the address converted into a syscall
31 // sockaddr type that implements syscall.Sockaddr
32 // interface. It returns a nil interface when the address is
34 sockaddr(family
int) (syscall
.Sockaddr
, error
)
37 // socket returns a network file descriptor that is ready for
38 // asynchronous I/O using the network poller.
39 func socket(net
string, family
, sotype
, proto
int, ipv6only
bool, laddr
, raddr sockaddr
, deadline time
.Time
) (fd
*netFD
, err error
) {
40 s
, err
:= sysSocket(family
, sotype
, proto
)
44 if err
= setDefaultSockopts(s
, family
, sotype
, ipv6only
); err
!= nil {
48 if fd
, err
= newFD(s
, family
, sotype
, net
); err
!= nil {
53 // This function makes a network file descriptor for the
54 // following applications:
56 // - An endpoint holder that opens a passive stream
57 // connenction, known as a stream listener
59 // - An endpoint holder that opens a destination-unspecific
60 // datagram connection, known as a datagram listener
62 // - An endpoint holder that opens an active stream or a
63 // destination-specific datagram connection, known as a
66 // - An endpoint holder that opens the other connection, such
67 // as talking to the protocol stack inside the kernel
69 // For stream and datagram listeners, they will only require
70 // named sockets, so we can assume that it's just a request
71 // from stream or datagram listeners when laddr is not nil but
72 // raddr is nil. Otherwise we assume it's just for dialers or
73 // the other connection holders.
75 if laddr
!= nil && raddr
== nil {
77 case syscall
.SOCK_STREAM
, syscall
.SOCK_SEQPACKET
:
78 if err
:= fd
.listenStream(laddr
, listenerBacklog
); err
!= nil {
83 case syscall
.SOCK_DGRAM
:
84 if err
:= fd
.listenDatagram(laddr
); err
!= nil {
91 if err
:= fd
.dial(laddr
, raddr
, deadline
); err
!= nil {
98 func (fd
*netFD
) addrFunc() func(syscall
.Sockaddr
) Addr
{
100 case syscall
.AF_INET
, syscall
.AF_INET6
:
102 case syscall
.SOCK_STREAM
:
104 case syscall
.SOCK_DGRAM
:
106 case syscall
.SOCK_RAW
:
109 case syscall
.AF_UNIX
:
111 case syscall
.SOCK_STREAM
:
112 return sockaddrToUnix
113 case syscall
.SOCK_DGRAM
:
114 return sockaddrToUnixgram
115 case syscall
.SOCK_SEQPACKET
:
116 return sockaddrToUnixpacket
119 return func(syscall
.Sockaddr
) Addr
{ return nil }
122 func (fd
*netFD
) dial(laddr
, raddr sockaddr
, deadline time
.Time
) error
{
124 var lsa syscall
.Sockaddr
126 if lsa
, err
= laddr
.sockaddr(fd
.family
); err
!= nil {
128 } else if lsa
!= nil {
129 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
130 return os
.NewSyscallError("bind", err
)
134 var rsa syscall
.Sockaddr
136 if rsa
, err
= raddr
.sockaddr(fd
.family
); err
!= nil {
139 if err
:= fd
.connect(lsa
, rsa
, deadline
); err
!= nil {
142 fd
.isConnected
= true
144 if err
:= fd
.init(); err
!= nil {
148 lsa
, _
= syscall
.Getsockname(fd
.sysfd
)
149 if rsa
, _
= syscall
.Getpeername(fd
.sysfd
); rsa
!= nil {
150 fd
.setAddr(fd
.addrFunc()(lsa
), fd
.addrFunc()(rsa
))
152 fd
.setAddr(fd
.addrFunc()(lsa
), raddr
)
157 func (fd
*netFD
) listenStream(laddr sockaddr
, backlog
int) error
{
158 if err
:= setDefaultListenerSockopts(fd
.sysfd
); err
!= nil {
161 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
163 } else if lsa
!= nil {
164 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
165 return os
.NewSyscallError("bind", err
)
168 if err
:= syscall
.Listen(fd
.sysfd
, backlog
); err
!= nil {
169 return os
.NewSyscallError("listen", err
)
171 if err
:= fd
.init(); err
!= nil {
174 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
175 fd
.setAddr(fd
.addrFunc()(lsa
), nil)
179 func (fd
*netFD
) listenDatagram(laddr sockaddr
) error
{
180 switch addr
:= laddr
.(type) {
182 // We provide a socket that listens to a wildcard
183 // address with reusable UDP port when the given laddr
184 // is an appropriate UDP multicast address prefix.
185 // This makes it possible for a single UDP listener to
186 // join multiple different group addresses, for
187 // multiple UDP listeners that listen on the same UDP
188 // port to join the same group address.
189 if addr
.IP
!= nil && addr
.IP
.IsMulticast() {
190 if err
:= setDefaultMulticastSockopts(fd
.sysfd
); err
!= nil {
195 case syscall
.AF_INET
:
197 case syscall
.AF_INET6
:
198 addr
.IP
= IPv6unspecified
203 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
205 } else if lsa
!= nil {
206 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
207 return os
.NewSyscallError("bind", err
)
210 if err
:= fd
.init(); err
!= nil {
213 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
214 fd
.setAddr(fd
.addrFunc()(lsa
), nil)