LEFT | RIGHT |
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 netbsd openbsd windows | |
6 | |
7 // TCP sockets | |
8 | |
9 package net | |
10 | |
11 import ( | |
12 "io" | |
13 "os" | |
14 "syscall" | |
15 "time" | |
16 ) | |
17 | |
18 // BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for | |
19 // both IPv4 and IPv6 connections. This is due to the fact that IPv4 traffic | |
20 // will not be routed to an IPv6 socket - two separate sockets are required | |
21 // if both AFs are to be supported. See inet6(4) on OpenBSD for details. | |
22 | |
23 func sockaddrToTCP(sa syscall.Sockaddr) Addr { | 1 func sockaddrToTCP(sa syscall.Sockaddr) Addr { |
24 switch sa := sa.(type) { | 2 switch sa := sa.(type) { |
25 case *syscall.SockaddrInet4: | 3 case *syscall.SockaddrInet4: |
26 » » return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port} | 4 » » return &TCPAddr{sa.Addr[0:], sa.Port} |
27 case *syscall.SockaddrInet6: | 5 case *syscall.SockaddrInet6: |
28 » » return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, ZoneId: zoneIdTo
String(int(sa.ZoneId))} | 6 » » return &TCPAddr{sa.Addr[0:], sa.Port} |
29 default: | 7 default: |
30 if sa != nil { | 8 if sa != nil { |
31 // Diagnose when we will turn a non-nil sockaddr into a
nil. | 9 // Diagnose when we will turn a non-nil sockaddr into a
nil. |
32 panic("unexpected type in sockaddrToTCP") | |
33 } | |
34 } | |
35 return nil | |
36 } | |
37 | |
38 func (a *TCPAddr) family() int { | |
39 if a == nil || len(a.IP) <= IPv4len { | |
40 return syscall.AF_INET | |
41 } | |
42 if a.IP.To4() != nil { | |
43 return syscall.AF_INET | |
44 } | |
45 return syscall.AF_INET6 | |
46 } | |
47 | |
48 func (a *TCPAddr) isWildcard() bool { | |
49 if a == nil || a.IP == nil { | |
50 return true | |
51 } | |
52 return a.IP.IsUnspecified() | |
53 } | |
54 | |
55 func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) { | |
56 return ipToSockaddr(family, a.IP, a.Port, a.ZoneId) | |
57 } | |
58 | |
59 func (a *TCPAddr) toAddr() sockaddr { | |
60 if a == nil { // nil *TCPAddr | |
61 return nil // nil interface | |
62 } | |
63 return a | |
64 } | |
65 | |
66 // TCPConn is an implementation of the Conn interface | |
67 // for TCP network connections. | |
68 type TCPConn struct { | |
69 conn | |
70 } | |
71 | |
72 func newTCPConn(fd *netFD) *TCPConn { | |
73 c := &TCPConn{conn{fd}} | |
74 c.SetNoDelay(true) | |
75 return c | |
76 } | |
77 | |
78 // ReadFrom implements the io.ReaderFrom ReadFrom method. | |
79 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) { | |
80 if n, err, handled := sendFile(c.fd, r); handled { | |
81 return n, err | |
82 } | |
83 return genericReadFrom(c, r) | |
84 } | |
85 | |
86 // CloseRead shuts down the reading side of the TCP connection. | |
87 // Most callers should just use Close. | |
88 func (c *TCPConn) CloseRead() error { | |
89 if !c.ok() { | |
90 return syscall.EINVAL | |
91 } | |
92 return c.fd.CloseRead() | |
93 } | |
94 | |
95 // CloseWrite shuts down the writing side of the TCP connection. | |
96 // Most callers should just use Close. | |
97 func (c *TCPConn) CloseWrite() error { | |
98 if !c.ok() { | |
99 return syscall.EINVAL | |
100 } | |
101 return c.fd.CloseWrite() | |
102 } | |
103 | |
104 // SetLinger sets the behavior of Close() on a connection | |
105 // which still has data waiting to be sent or to be acknowledged. | |
106 // | |
107 // If sec < 0 (the default), Close returns immediately and | |
108 // the operating system finishes sending the data in the background. | |
109 // | |
110 // If sec == 0, Close returns immediately and the operating system | |
111 // discards any unsent or unacknowledged data. | |
112 // | |
113 // If sec > 0, Close blocks for at most sec seconds waiting for | |
114 // data to be sent and acknowledged. | |
115 func (c *TCPConn) SetLinger(sec int) error { | |
116 if !c.ok() { | |
117 return syscall.EINVAL | |
118 } | |
119 return setLinger(c.fd, sec) | |
120 } | |
121 | |
122 // SetKeepAlive sets whether the operating system should send | |
123 // keepalive messages on the connection. | |
124 func (c *TCPConn) SetKeepAlive(keepalive bool) error { | |
125 if !c.ok() { | |
126 return syscall.EINVAL | |
127 } | |
128 return setKeepAlive(c.fd, keepalive) | |
129 } | |
130 | |
131 // SetNoDelay controls whether the operating system should delay | |
132 // packet transmission in hopes of sending fewer packets | |
133 // (Nagle's algorithm). The default is true (no delay), meaning | |
134 // that data is sent as soon as possible after a Write. | |
135 func (c *TCPConn) SetNoDelay(noDelay bool) error { | |
136 if !c.ok() { | |
137 return syscall.EINVAL | |
138 } | |
139 return setNoDelay(c.fd, noDelay) | |
140 } | |
141 | |
142 // DialTCP connects to the remote address raddr on the network net, | |
143 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used | |
144 // as the local address for the connection. | |
145 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { | |
146 switch net { | |
147 case "tcp", "tcp4", "tcp6": | |
148 default: | |
149 return nil, UnknownNetworkError(net) | |
150 } | |
151 if raddr == nil { | |
152 return nil, &OpError{"dial", net, nil, errMissingAddress} | |
153 } | |
154 return dialTCP(net, laddr, raddr, noDeadline) | |
155 } | |
156 | |
157 func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
rror) { | |
158 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline,
syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) | |
159 | |
160 // TCP has a rarely used mechanism called a 'simultaneous connection' in | |
161 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can | |
162 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin
e | |
163 // at addr2, without either machine executing Listen. If laddr == nil, | |
164 // it means we want the kernel to pick an appropriate originating local | |
165 // address. Some Linux kernels cycle blindly through a fixed range of | |
166 // local ports, regardless of destination port. If a kernel happens to | |
167 // pick local port 50001 as the source for a Dial("tcp", "", "localhost:
50001"), | |
168 // then the Dial will succeed, having simultaneously connected to itself
. | |
169 // This can only happen when we are letting the kernel pick a port (ladd
r == nil) | |
170 // and when there is no listener for the destination address. | |
171 // It's hard to argue this is anything other than a kernel bug. If we | |
172 // see this happen, rather than expose the buggy effect to users, we | |
173 // close the fd and try again. If it happens twice more, we relent and | |
174 // use the result. See also: | |
175 // http://golang.org/issue/2690 | |
176 // http://stackoverflow.com/questions/4949858/ | |
177 // | |
178 // The opposite can also happen: if we ask the kernel to pick an appropr
iate | |
179 // originating local address, sometimes it picks one that is already in
use. | |
180 // So if the error is EADDRNOTAVAIL, we have to try again too, just for | |
181 // a different reason. | |
182 // | |
183 // The kernel socket code is no doubt enjoying watching us squirm. | |
184 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(f
d, err) || spuriousENOTAVAIL(err)); i++ { | |
185 if err == nil { | |
186 fd.Close() | |
187 } | |
188 fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), de
adline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) | |
189 } | |
190 | |
191 if err != nil { | |
192 return nil, err | |
193 } | |
194 return newTCPConn(fd), nil | |
195 } | |
196 | |
197 func selfConnect(fd *netFD, err error) bool { | |
198 // If the connect failed, we clearly didn't connect to ourselves. | |
199 if err != nil { | |
200 return false | |
201 } | |
202 | |
203 // The socket constructor can return an fd with raddr nil under certain | |
204 // unknown conditions. The errors in the calls there to Getpeername | |
205 // are discarded, but we can't catch the problem there because those | |
206 // calls are sometimes legally erroneous with a "socket not connected". | |
207 // Since this code (selfConnect) is already trying to work around | |
208 // a problem, we make sure if this happens we recognize trouble and | |
209 // ask the DialTCP routine to try again. | |
210 // TODO: try to understand what's really going on. | |
211 if fd.laddr == nil || fd.raddr == nil { | |
212 return true | |
213 } | |
214 l := fd.laddr.(*TCPAddr) | |
215 r := fd.raddr.(*TCPAddr) | |
216 return l.Port == r.Port && l.IP.Equal(r.IP) | |
217 } | |
218 | |
219 func spuriousENOTAVAIL(err error) bool { | |
220 e, ok := err.(*OpError) | |
221 return ok && e.Err == syscall.EADDRNOTAVAIL | |
222 } | |
223 | |
224 // TCPListener is a TCP network listener. | |
225 // Clients should typically use variables of type Listener | |
226 // instead of assuming TCP. | |
227 type TCPListener struct { | |
228 fd *netFD | |
229 } | |
230 | |
231 // AcceptTCP accepts the next incoming call and returns the new connection | |
232 // and the remote address. | |
233 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { | |
234 if l == nil || l.fd == nil || l.fd.sysfd < 0 { | |
235 return nil, syscall.EINVAL | |
236 } | |
237 fd, err := l.fd.accept(sockaddrToTCP) | |
238 if err != nil { | |
239 return nil, err | |
240 } | |
241 return newTCPConn(fd), nil | |
242 } | |
243 | |
244 // Accept implements the Accept method in the Listener interface; | |
245 // it waits for the next call and returns a generic Conn. | |
246 func (l *TCPListener) Accept() (c Conn, err error) { | |
247 c1, err := l.AcceptTCP() | |
248 if err != nil { | |
249 return nil, err | |
250 } | |
251 return c1, nil | |
252 } | |
253 | |
254 // Close stops listening on the TCP address. | |
255 // Already Accepted connections are not closed. | |
256 func (l *TCPListener) Close() error { | |
257 if l == nil || l.fd == nil { | |
258 return syscall.EINVAL | |
259 } | |
260 return l.fd.Close() | |
261 } | |
262 | |
263 // Addr returns the listener's network address, a *TCPAddr. | |
264 func (l *TCPListener) Addr() Addr { return l.fd.laddr } | |
265 | |
266 // SetDeadline sets the deadline associated with the listener. | |
267 // A zero time value disables the deadline. | |
268 func (l *TCPListener) SetDeadline(t time.Time) error { | |
269 if l == nil || l.fd == nil { | |
270 return syscall.EINVAL | |
271 } | |
272 return setDeadline(l.fd, t) | |
273 } | |
274 | |
275 // File returns a copy of the underlying os.File, set to blocking mode. | |
276 // It is the caller's responsibility to close f when finished. | |
277 // Closing l does not affect f, and closing f does not affect l. | |
278 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } | |
279 | |
280 // ListenTCP announces on the TCP address laddr and returns a TCP listener. | |
281 // Net must be "tcp", "tcp4", or "tcp6". | |
282 // If laddr has a port of 0, it means to listen on some available port. | |
283 // The caller can use l.Addr() to retrieve the chosen address. | |
284 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { | |
285 switch net { | |
286 case "tcp", "tcp4", "tcp6": | |
287 default: | |
288 return nil, UnknownNetworkError(net) | |
289 } | |
290 if laddr == nil { | |
291 laddr = &TCPAddr{} | |
292 } | |
293 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.
SOCK_STREAM, 0, "listen", sockaddrToTCP) | |
294 if err != nil { | |
295 return nil, err | |
296 } | |
297 err = syscall.Listen(fd.sysfd, listenerBacklog) | |
298 if err != nil { | |
299 closesocket(fd.sysfd) | |
300 return nil, &OpError{"listen", net, laddr, err} | |
301 } | |
302 l := new(TCPListener) | |
303 l.fd = fd | |
304 return l, nil | |
305 } | |
LEFT | RIGHT |