Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2068)

Delta Between Two Patch Sets: src/pkg/net/tcpsock_posix.go

Issue 6525048: code review 6525048: net: protocol specific listen functions return a proper... (Closed)
Left Patch Set: diff -r 284f6a1e531b https://go.googlecode.com/hg/ Created 11 years, 5 months ago
Right Patch Set: diff -r 0b46d6fe2f1c https://go.googlecode.com/hg/ Created 11 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/net/tcpsock_plan9.go ('k') | src/pkg/net/udp_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin freebsd linux netbsd openbsd windows 5 // +build darwin freebsd linux netbsd openbsd windows
6 6
7 // TCP sockets 7 // TCP sockets
8 8
9 package net 9 package net
10 10
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 // (Nagle's algorithm). The default is true (no delay), meaning 133 // (Nagle's algorithm). The default is true (no delay), meaning
134 // that data is sent as soon as possible after a Write. 134 // that data is sent as soon as possible after a Write.
135 func (c *TCPConn) SetNoDelay(noDelay bool) error { 135 func (c *TCPConn) SetNoDelay(noDelay bool) error {
136 if !c.ok() { 136 if !c.ok() {
137 return syscall.EINVAL 137 return syscall.EINVAL
138 } 138 }
139 return setNoDelay(c.fd, noDelay) 139 return setNoDelay(c.fd, noDelay)
140 } 140 }
141 141
142 // DialTCP connects to the remote address raddr on the network net, 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 143 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
iant 2012/10/13 17:40:49 Do not remove the comma after "tcp4". It is corre
144 // used as the local address for the connection. 144 // as the local address for the connection.
145 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { 145 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
146 switch net { 146 switch net {
147 case "tcp", "tcp4", "tcp6": 147 case "tcp", "tcp4", "tcp6":
148 default: 148 default:
149 return nil, UnknownNetworkError(net) 149 return nil, UnknownNetworkError(net)
150 } 150 }
151 if raddr == nil { 151 if raddr == nil {
152 return nil, &OpError{"dial", net, nil, errMissingAddress} 152 return nil, &OpError{"dial", net, nil, errMissingAddress}
153 } 153 }
154 154 » return dialTCP(net, laddr, raddr, noDeadline)
155 » fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.S OCK_STREAM, 0, "dial", sockaddrToTCP) 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)
156 159
157 // TCP has a rarely used mechanism called a 'simultaneous connection' in 160 // TCP has a rarely used mechanism called a 'simultaneous connection' in
158 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can 161 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can
159 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin e 162 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin e
160 // at addr2, without either machine executing Listen. If laddr == nil, 163 // at addr2, without either machine executing Listen. If laddr == nil,
161 // it means we want the kernel to pick an appropriate originating local 164 // it means we want the kernel to pick an appropriate originating local
162 // address. Some Linux kernels cycle blindly through a fixed range of 165 // address. Some Linux kernels cycle blindly through a fixed range of
163 // local ports, regardless of destination port. If a kernel happens to 166 // local ports, regardless of destination port. If a kernel happens to
164 // pick local port 50001 as the source for a Dial("tcp", "", "localhost: 50001"), 167 // pick local port 50001 as the source for a Dial("tcp", "", "localhost: 50001"),
165 // then the Dial will succeed, having simultaneously connected to itself . 168 // then the Dial will succeed, having simultaneously connected to itself .
166 // This can only happen when we are letting the kernel pick a port (ladd r == nil) 169 // This can only happen when we are letting the kernel pick a port (ladd r == nil)
167 // and when there is no listener for the destination address. 170 // and when there is no listener for the destination address.
168 // It's hard to argue this is anything other than a kernel bug. If we 171 // It's hard to argue this is anything other than a kernel bug. If we
169 // see this happen, rather than expose the buggy effect to users, we 172 // see this happen, rather than expose the buggy effect to users, we
170 // close the fd and try again. If it happens twice more, we relent and 173 // close the fd and try again. If it happens twice more, we relent and
171 // use the result. See also: 174 // use the result. See also:
172 // http://golang.org/issue/2690 175 // http://golang.org/issue/2690
173 // http://stackoverflow.com/questions/4949858/ 176 // http://stackoverflow.com/questions/4949858/
174 // 177 //
175 // The opposite can also happen: if we ask the kernel to pick an appropr iate 178 // The opposite can also happen: if we ask the kernel to pick an appropr iate
176 // originating local address, sometimes it picks one that is already in use. 179 // originating local address, sometimes it picks one that is already in use.
177 // So if the error is EADDRNOTAVAIL, we have to try again too, just for 180 // So if the error is EADDRNOTAVAIL, we have to try again too, just for
178 // a different reason. 181 // a different reason.
179 // 182 //
180 // The kernel socket code is no doubt enjoying watching us squirm. 183 // The kernel socket code is no doubt enjoying watching us squirm.
181 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(f d, err) || spuriousENOTAVAIL(err)); i++ { 184 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(f d, err) || spuriousENOTAVAIL(err)); i++ {
182 if err == nil { 185 if err == nil {
183 fd.Close() 186 fd.Close()
184 } 187 }
185 » » fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), sy scall.SOCK_STREAM, 0, "dial", sockaddrToTCP) 188 » » fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), de adline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
186 } 189 }
187 190
188 if err != nil { 191 if err != nil {
189 return nil, err 192 return nil, err
190 } 193 }
191 return newTCPConn(fd), nil 194 return newTCPConn(fd), nil
192 } 195 }
193 196
194 func selfConnect(fd *netFD, err error) bool { 197 func selfConnect(fd *netFD, err error) bool {
195 // If the connect failed, we clearly didn't connect to ourselves. 198 // If the connect failed, we clearly didn't connect to ourselves.
(...skipping 22 matching lines...) Expand all
218 return ok && e.Err == syscall.EADDRNOTAVAIL 221 return ok && e.Err == syscall.EADDRNOTAVAIL
219 } 222 }
220 223
221 // TCPListener is a TCP network listener. 224 // TCPListener is a TCP network listener.
222 // Clients should typically use variables of type Listener 225 // Clients should typically use variables of type Listener
223 // instead of assuming TCP. 226 // instead of assuming TCP.
224 type TCPListener struct { 227 type TCPListener struct {
225 fd *netFD 228 fd *netFD
226 } 229 }
227 230
228 // ListenTCP announces on the TCP address laddr on the network net, 231 // AcceptTCP accepts the next incoming call and returns the new connection
229 // which must be "tcp", "tcp4" or "tcp6" and returns a TCP listener. 232 // and the remote address.
iant 2012/10/13 17:40:49 Need comma after "tcp6".
230 // If laddr has a port of 0, it means to listen on some available 233 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
231 // port. The caller can use Addr() of TCPListener to retrieve the 234 » if l == nil || l.fd == nil || l.fd.sysfd < 0 {
232 // chosen address. 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.
233 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { 284 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
234 switch net { 285 switch net {
235 case "tcp", "tcp4", "tcp6": 286 case "tcp", "tcp4", "tcp6":
236 default: 287 default:
237 return nil, UnknownNetworkError(net) 288 return nil, UnknownNetworkError(net)
238 } 289 }
239 if laddr == nil { 290 if laddr == nil {
240 » » return nil, &OpError{"listen", net, nil, errMissingAddress} 291 » » laddr = &TCPAddr{}
241 » } 292 » }
242 » fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) 293 » fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall. SOCK_STREAM, 0, "listen", sockaddrToTCP)
243 if err != nil { 294 if err != nil {
244 return nil, err 295 return nil, err
245 } 296 }
246 err = syscall.Listen(fd.sysfd, listenerBacklog) 297 err = syscall.Listen(fd.sysfd, listenerBacklog)
247 if err != nil { 298 if err != nil {
248 closesocket(fd.sysfd) 299 closesocket(fd.sysfd)
249 return nil, &OpError{"listen", net, laddr, err} 300 return nil, &OpError{"listen", net, laddr, err}
250 } 301 }
251 l := new(TCPListener) 302 l := new(TCPListener)
252 l.fd = fd 303 l.fd = fd
253 return l, nil 304 return l, nil
254 } 305 }
255
256 // AcceptTCP accepts the next incoming call and returns the new connection
257 // and the remote address.
258 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
259 if l == nil || l.fd == nil || l.fd.sysfd < 0 {
260 return nil, syscall.EINVAL
261 }
262 fd, err := l.fd.accept(sockaddrToTCP)
263 if err != nil {
264 return nil, err
265 }
266 return newTCPConn(fd), nil
267 }
268
269 // Accept implements the Accept method in the Listener interface;
270 // it waits for the next call and returns a generic Conn.
271 func (l *TCPListener) Accept() (c Conn, err error) {
272 c1, err := l.AcceptTCP()
273 if err != nil {
274 return nil, err
275 }
276 return c1, nil
277 }
278
279 // Close stops listening on the TCP address.
280 // Already Accepted connections are not closed.
281 func (l *TCPListener) Close() error {
282 if l == nil || l.fd == nil {
283 return syscall.EINVAL
284 }
285 return l.fd.Close()
286 }
287
288 // Addr returns the listener's network address, a *TCPAddr.
289 func (l *TCPListener) Addr() Addr { return l.fd.laddr }
290
291 // SetDeadline sets the deadline associated with the listener.
292 // A zero time value disables the deadline.
293 func (l *TCPListener) SetDeadline(t time.Time) error {
294 if l == nil || l.fd == nil {
295 return syscall.EINVAL
296 }
297 return setDeadline(l.fd, t)
298 }
299
300 // File returns a copy of the underlying os.File, set to blocking mode.
301 // It is the caller's responsibility to close f when finished.
302 // Closing l does not affect f, and closing f does not affect l.
303 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b