Update Go library to last weekly.
[platform/upstream/gcc.git] / libgo / go / net / sock.go
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.
4
5 // +build darwin freebsd linux openbsd windows
6
7 // Sockets
8
9 package net
10
11 import (
12         "io"
13         "os"
14         "reflect"
15         "syscall"
16 )
17
18 // Boolean to int.
19 func boolint(b bool) int {
20         if b {
21                 return 1
22         }
23         return 0
24 }
25
26 // Generic socket creation.
27 func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) {
28         // See ../syscall/exec.go for description of ForkLock.
29         syscall.ForkLock.RLock()
30         s, e := syscall.Socket(f, p, t)
31         if e != 0 {
32                 syscall.ForkLock.RUnlock()
33                 return nil, os.Errno(e)
34         }
35         syscall.CloseOnExec(s)
36         syscall.ForkLock.RUnlock()
37
38         setKernelSpecificSockopt(s, f)
39
40         if la != nil {
41                 e = syscall.Bind(s, la)
42                 if e != 0 {
43                         closesocket(s)
44                         return nil, os.Errno(e)
45                 }
46         }
47
48         if fd, err = newFD(s, f, p, net); err != nil {
49                 closesocket(s)
50                 return nil, err
51         }
52
53         if ra != nil {
54                 if err = fd.connect(ra); err != nil {
55                         closesocket(s)
56                         fd.Close()
57                         return nil, err
58                 }
59         }
60
61         sa, _ := syscall.Getsockname(s)
62         laddr := toAddr(sa)
63         sa, _ = syscall.Getpeername(s)
64         raddr := toAddr(sa)
65
66         fd.setAddr(laddr, raddr)
67         return fd, nil
68 }
69
70 func setsockoptInt(fd *netFD, level, opt int, value int) os.Error {
71         return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, level, opt, value))
72 }
73
74 func setsockoptNsec(fd *netFD, level, opt int, nsec int64) os.Error {
75         var tv = syscall.NsecToTimeval(nsec)
76         return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd.sysfd, level, opt, &tv))
77 }
78
79 func setReadBuffer(fd *netFD, bytes int) os.Error {
80         fd.incref()
81         defer fd.decref()
82         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
83 }
84
85 func setWriteBuffer(fd *netFD, bytes int) os.Error {
86         fd.incref()
87         defer fd.decref()
88         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
89 }
90
91 func setReadTimeout(fd *netFD, nsec int64) os.Error {
92         fd.rdeadline_delta = nsec
93         return nil
94 }
95
96 func setWriteTimeout(fd *netFD, nsec int64) os.Error {
97         fd.wdeadline_delta = nsec
98         return nil
99 }
100
101 func setTimeout(fd *netFD, nsec int64) os.Error {
102         if e := setReadTimeout(fd, nsec); e != nil {
103                 return e
104         }
105         return setWriteTimeout(fd, nsec)
106 }
107
108 func setReuseAddr(fd *netFD, reuse bool) os.Error {
109         fd.incref()
110         defer fd.decref()
111         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
112 }
113
114 func bindToDevice(fd *netFD, dev string) os.Error {
115         // TODO(rsc): call setsockopt with null-terminated string pointer
116         return os.EINVAL
117 }
118
119 func setDontRoute(fd *netFD, dontroute bool) os.Error {
120         fd.incref()
121         defer fd.decref()
122         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
123 }
124
125 func setKeepAlive(fd *netFD, keepalive bool) os.Error {
126         fd.incref()
127         defer fd.decref()
128         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
129 }
130
131 func setNoDelay(fd *netFD, noDelay bool) os.Error {
132         fd.incref()
133         defer fd.decref()
134         return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
135 }
136
137 func setLinger(fd *netFD, sec int) os.Error {
138         var l syscall.Linger
139         if sec >= 0 {
140                 l.Onoff = 1
141                 l.Linger = int32(sec)
142         } else {
143                 l.Onoff = 0
144                 l.Linger = 0
145         }
146         fd.incref()
147         defer fd.decref()
148         e := syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
149         return os.NewSyscallError("setsockopt", e)
150 }
151
152 type UnknownSocketError struct {
153         sa syscall.Sockaddr
154 }
155
156 func (e *UnknownSocketError) String() string {
157         return "unknown socket address type " + reflect.TypeOf(e.sa).String()
158 }
159
160 type writerOnly struct {
161         io.Writer
162 }
163
164 // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
165 // applicable.
166 func genericReadFrom(w io.Writer, r io.Reader) (n int64, err os.Error) {
167         // Use wrapper to hide existing r.ReadFrom from io.Copy.
168         return io.Copy(writerOnly{w}, r)
169 }