OSDN Git Service

libgo: Update to weekly.2011-12-06.
[pf3gnuchains/gcc-fork.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 error) {
28         // See ../syscall/exec.go for description of ForkLock.
29         syscall.ForkLock.RLock()
30         s, e := syscall.Socket(f, p, t)
31         if err != nil {
32                 syscall.ForkLock.RUnlock()
33                 return nil, err
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 != nil {
43                         closesocket(s)
44                         return nil, 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) 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) 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) 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) 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) error {
92         fd.rdeadline_delta = nsec
93         return nil
94 }
95
96 func setWriteTimeout(fd *netFD, nsec int64) error {
97         fd.wdeadline_delta = nsec
98         return nil
99 }
100
101 func setTimeout(fd *netFD, nsec int64) 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) error {
109         fd.incref()
110         defer fd.decref()
111         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
112 }
113
114 func setDontRoute(fd *netFD, dontroute bool) error {
115         fd.incref()
116         defer fd.decref()
117         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
118 }
119
120 func setKeepAlive(fd *netFD, keepalive bool) error {
121         fd.incref()
122         defer fd.decref()
123         return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
124 }
125
126 func setNoDelay(fd *netFD, noDelay bool) error {
127         fd.incref()
128         defer fd.decref()
129         return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
130 }
131
132 func setLinger(fd *netFD, sec int) error {
133         var l syscall.Linger
134         if sec >= 0 {
135                 l.Onoff = 1
136                 l.Linger = int32(sec)
137         } else {
138                 l.Onoff = 0
139                 l.Linger = 0
140         }
141         fd.incref()
142         defer fd.decref()
143         e := syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
144         return os.NewSyscallError("setsockopt", e)
145 }
146
147 type UnknownSocketError struct {
148         sa syscall.Sockaddr
149 }
150
151 func (e *UnknownSocketError) Error() string {
152         return "unknown socket address type " + reflect.TypeOf(e.sa).String()
153 }
154
155 type writerOnly struct {
156         io.Writer
157 }
158
159 // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
160 // applicable.
161 func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
162         // Use wrapper to hide existing r.ReadFrom from io.Copy.
163         return io.Copy(writerOnly{w}, r)
164 }