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 netbsd openbsd 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
, toAddr
func(syscall
.Sockaddr
) Addr
) (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
, toAddr
); err
!= nil {
83 case syscall
.SOCK_DGRAM
:
84 if err
:= fd
.listenDatagram(laddr
, toAddr
); err
!= nil {
91 if err
:= fd
.dial(laddr
, raddr
, deadline
, toAddr
); err
!= nil {
98 func (fd
*netFD
) dial(laddr
, raddr sockaddr
, deadline time
.Time
, toAddr
func(syscall
.Sockaddr
) Addr
) error
{
100 var lsa syscall
.Sockaddr
102 if lsa
, err
= laddr
.sockaddr(fd
.family
); err
!= nil {
104 } else if lsa
!= nil {
105 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
106 return os
.NewSyscallError("bind", err
)
110 if err
:= fd
.init(); err
!= nil {
113 var rsa syscall
.Sockaddr
115 if rsa
, err
= raddr
.sockaddr(fd
.family
); err
!= nil {
117 } else if rsa
!= nil {
118 if !deadline
.IsZero() {
119 fd
.setWriteDeadline(deadline
)
121 if err
:= fd
.connect(lsa
, rsa
); err
!= nil {
124 fd
.isConnected
= true
125 if !deadline
.IsZero() {
126 fd
.setWriteDeadline(noDeadline
)
130 lsa
, _
= syscall
.Getsockname(fd
.sysfd
)
131 if rsa
, _
= syscall
.Getpeername(fd
.sysfd
); rsa
!= nil {
132 fd
.setAddr(toAddr(lsa
), toAddr(rsa
))
134 fd
.setAddr(toAddr(lsa
), raddr
)
139 func (fd
*netFD
) listenStream(laddr sockaddr
, backlog
int, toAddr
func(syscall
.Sockaddr
) Addr
) error
{
140 if err
:= setDefaultListenerSockopts(fd
.sysfd
); err
!= nil {
143 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
145 } else if lsa
!= nil {
146 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
147 return os
.NewSyscallError("bind", err
)
150 if err
:= syscall
.Listen(fd
.sysfd
, backlog
); err
!= nil {
151 return os
.NewSyscallError("listen", err
)
153 if err
:= fd
.init(); err
!= nil {
156 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
157 fd
.setAddr(toAddr(lsa
), nil)
161 func (fd
*netFD
) listenDatagram(laddr sockaddr
, toAddr
func(syscall
.Sockaddr
) Addr
) error
{
162 switch addr
:= laddr
.(type) {
164 // We provide a socket that listens to a wildcard
165 // address with reusable UDP port when the given laddr
166 // is an appropriate UDP multicast address prefix.
167 // This makes it possible for a single UDP listener to
168 // join multiple different group addresses, for
169 // multiple UDP listeners that listen on the same UDP
170 // port to join the same group address.
171 if addr
.IP
!= nil && addr
.IP
.IsMulticast() {
172 if err
:= setDefaultMulticastSockopts(fd
.sysfd
); err
!= nil {
177 case syscall
.AF_INET
:
179 case syscall
.AF_INET6
:
180 addr
.IP
= IPv6unspecified
185 if lsa
, err
:= laddr
.sockaddr(fd
.family
); err
!= nil {
187 } else if lsa
!= nil {
188 if err
:= syscall
.Bind(fd
.sysfd
, lsa
); err
!= nil {
189 return os
.NewSyscallError("bind", err
)
192 if err
:= fd
.init(); err
!= nil {
195 lsa
, _
:= syscall
.Getsockname(fd
.sysfd
)
196 fd
.setAddr(toAddr(lsa
), nil)