Daily bump.
[official-gcc.git] / libgo / go / net / sock_posix.go
blobc2d343c5858076c5653c5b48b875b7ae0ca7adaa
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
7 package net
9 import (
10 "os"
11 "syscall"
12 "time"
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 {
18 Addr
20 netaddr
22 // family returns the platform-dependent address family
23 // identifier.
24 family() int
26 // isWildcard reports whether the address is a wildcard
27 // address.
28 isWildcard() bool
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
33 // nil.
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)
41 if err != nil {
42 return nil, err
44 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
45 closesocket(s)
46 return nil, err
48 if fd, err = newFD(s, family, sotype, net); err != nil {
49 closesocket(s)
50 return nil, err
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
64 // dialer
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 {
76 switch sotype {
77 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
78 if err := fd.listenStream(laddr, listenerBacklog, toAddr); err != nil {
79 fd.Close()
80 return nil, err
82 return fd, nil
83 case syscall.SOCK_DGRAM:
84 if err := fd.listenDatagram(laddr, toAddr); err != nil {
85 fd.Close()
86 return nil, err
88 return fd, nil
91 if err := fd.dial(laddr, raddr, deadline, toAddr); err != nil {
92 fd.Close()
93 return nil, err
95 return fd, nil
98 func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) error {
99 var err error
100 var lsa syscall.Sockaddr
101 if laddr != nil {
102 if lsa, err = laddr.sockaddr(fd.family); err != nil {
103 return err
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 {
111 return err
113 var rsa syscall.Sockaddr
114 if raddr != nil {
115 if rsa, err = raddr.sockaddr(fd.family); err != nil {
116 return err
117 } else if rsa != nil {
118 if !deadline.IsZero() {
119 fd.setWriteDeadline(deadline)
121 if err := fd.connect(lsa, rsa); err != nil {
122 return err
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))
133 } else {
134 fd.setAddr(toAddr(lsa), raddr)
136 return nil
139 func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.Sockaddr) Addr) error {
140 if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
141 return err
143 if lsa, err := laddr.sockaddr(fd.family); err != nil {
144 return err
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 {
154 return err
156 lsa, _ := syscall.Getsockname(fd.sysfd)
157 fd.setAddr(toAddr(lsa), nil)
158 return nil
161 func (fd *netFD) listenDatagram(laddr sockaddr, toAddr func(syscall.Sockaddr) Addr) error {
162 switch addr := laddr.(type) {
163 case *UDPAddr:
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 {
173 return err
175 addr := *addr
176 switch fd.family {
177 case syscall.AF_INET:
178 addr.IP = IPv4zero
179 case syscall.AF_INET6:
180 addr.IP = IPv6unspecified
182 laddr = &addr
185 if lsa, err := laddr.sockaddr(fd.family); err != nil {
186 return err
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 {
193 return err
195 lsa, _ := syscall.Getsockname(fd.sysfd)
196 fd.setAddr(toAddr(lsa), nil)
197 return nil