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.
16 func boolint(b
bool) int {
23 // Generic socket creation.
24 func socket(net
string, f
, p
, t
int, la
, ra syscall
.Sockaddr
, toAddr
func(syscall
.Sockaddr
) Addr
) (fd
*netFD
, err os
.Error
) {
25 // See ../syscall/exec.go for description of ForkLock.
26 syscall
.ForkLock
.RLock()
27 s
, e
:= syscall
.Socket(f
, p
, t
)
29 syscall
.ForkLock
.RUnlock()
30 return nil, os
.Errno(e
)
32 syscall
.CloseOnExec(s
)
33 syscall
.ForkLock
.RUnlock()
35 // Allow reuse of recently-used addresses.
36 syscall
.SetsockoptInt(s
, syscall
.SOL_SOCKET
, syscall
.SO_REUSEADDR
, 1)
39 syscall
.SetsockoptInt(s
, syscall
.SOL_SOCKET
, syscall
.SO_BROADCAST
, 1)
41 if f
== syscall
.AF_INET6
{
42 // using ip, tcp, udp, etc.
43 // allow both protocols even if the OS default is otherwise.
44 syscall
.SetsockoptInt(s
, syscall
.IPPROTO_IPV6
, syscall
.IPV6_V6ONLY
, 0)
48 e
= syscall
.Bind(s
, la
)
51 return nil, os
.Errno(e
)
55 if fd
, err
= newFD(s
, f
, p
, net
); err
!= nil {
61 if err
= fd
.connect(ra
); err
!= nil {
68 sa
, _
:= syscall
.Getsockname(s
)
70 sa
, _
= syscall
.Getpeername(s
)
73 fd
.setAddr(laddr
, raddr
)
77 func setsockoptInt(fd
, level
, opt
int, value
int) os
.Error
{
78 return os
.NewSyscallError("setsockopt", syscall
.SetsockoptInt(fd
, level
, opt
, value
))
81 func setsockoptNsec(fd
, level
, opt
int, nsec
int64) os
.Error
{
82 var tv
= syscall
.NsecToTimeval(nsec
)
83 return os
.NewSyscallError("setsockopt", syscall
.SetsockoptTimeval(fd
, level
, opt
, &tv
))
86 func setReadBuffer(fd
*netFD
, bytes
int) os
.Error
{
89 return setsockoptInt(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_RCVBUF
, bytes
)
92 func setWriteBuffer(fd
*netFD
, bytes
int) os
.Error
{
95 return setsockoptInt(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_SNDBUF
, bytes
)
98 func setReadTimeout(fd
*netFD
, nsec
int64) os
.Error
{
99 fd
.rdeadline_delta
= nsec
103 func setWriteTimeout(fd
*netFD
, nsec
int64) os
.Error
{
104 fd
.wdeadline_delta
= nsec
108 func setTimeout(fd
*netFD
, nsec
int64) os
.Error
{
109 if e
:= setReadTimeout(fd
, nsec
); e
!= nil {
112 return setWriteTimeout(fd
, nsec
)
115 func setReuseAddr(fd
*netFD
, reuse
bool) os
.Error
{
118 return setsockoptInt(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_REUSEADDR
, boolint(reuse
))
121 func bindToDevice(fd
*netFD
, dev
string) os
.Error
{
122 // TODO(rsc): call setsockopt with null-terminated string pointer
126 func setDontRoute(fd
*netFD
, dontroute
bool) os
.Error
{
129 return setsockoptInt(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_DONTROUTE
, boolint(dontroute
))
132 func setKeepAlive(fd
*netFD
, keepalive
bool) os
.Error
{
135 return setsockoptInt(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_KEEPALIVE
, boolint(keepalive
))
138 func setNoDelay(fd
*netFD
, noDelay
bool) os
.Error
{
141 return setsockoptInt(fd
.sysfd
, syscall
.IPPROTO_TCP
, syscall
.TCP_NODELAY
, boolint(noDelay
))
144 func setLinger(fd
*netFD
, sec
int) os
.Error
{
148 l
.Linger
= int32(sec
)
155 e
:= syscall
.SetsockoptLinger(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_LINGER
, &l
)
156 return os
.NewSyscallError("setsockopt", e
)
159 type UnknownSocketError
struct {
163 func (e
*UnknownSocketError
) String() string {
164 return "unknown socket address type " + reflect
.Typeof(e
.sa
).String()
167 func sockaddrToString(sa syscall
.Sockaddr
) (name
string, err os
.Error
) {
168 switch a
:= sa
.(type) {
169 case *syscall
.SockaddrInet4
:
170 return JoinHostPort(IP(a
.Addr
[0:]).String(), itoa(a
.Port
)), nil
171 case *syscall
.SockaddrInet6
:
172 return JoinHostPort(IP(a
.Addr
[0:]).String(), itoa(a
.Port
)), nil
173 case *syscall
.SockaddrUnix
:
177 return "", &UnknownSocketError
{sa
}