~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

Viewing changes to src/pkg/net/tcpsock_posix.go

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 
5
5
// +build darwin freebsd linux netbsd openbsd windows
6
6
 
7
 
// TCP sockets
8
 
 
9
7
package net
10
8
 
11
9
import (
23
21
func sockaddrToTCP(sa syscall.Sockaddr) Addr {
24
22
        switch sa := sa.(type) {
25
23
        case *syscall.SockaddrInet4:
26
 
                return &TCPAddr{sa.Addr[0:], sa.Port}
 
24
                return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
27
25
        case *syscall.SockaddrInet6:
28
 
                return &TCPAddr{sa.Addr[0:], sa.Port}
29
 
        default:
30
 
                if sa != nil {
31
 
                        // Diagnose when we will turn a non-nil sockaddr into a nil.
32
 
                        panic("unexpected type in sockaddrToTCP")
33
 
                }
 
26
                return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
34
27
        }
35
28
        return nil
36
29
}
53
46
}
54
47
 
55
48
func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
56
 
        return ipToSockaddr(family, a.IP, a.Port)
 
49
        return ipToSockaddr(family, a.IP, a.Port, a.Zone)
57
50
}
58
51
 
59
52
func (a *TCPAddr) toAddr() sockaddr {
63
56
        return a
64
57
}
65
58
 
66
 
// TCPConn is an implementation of the Conn interface
67
 
// for TCP network connections.
 
59
// TCPConn is an implementation of the Conn interface for TCP network
 
60
// connections.
68
61
type TCPConn struct {
69
 
        fd *netFD
 
62
        conn
70
63
}
71
64
 
72
65
func newTCPConn(fd *netFD) *TCPConn {
73
 
        c := &TCPConn{fd}
 
66
        c := &TCPConn{conn{fd}}
74
67
        c.SetNoDelay(true)
75
68
        return c
76
69
}
77
70
 
78
 
func (c *TCPConn) ok() bool { return c != nil && c.fd != nil }
79
 
 
80
 
// Implementation of the Conn interface - see Conn for documentation.
81
 
 
82
 
// Read implements the Conn Read method.
83
 
func (c *TCPConn) Read(b []byte) (n int, err error) {
84
 
        if !c.ok() {
85
 
                return 0, syscall.EINVAL
86
 
        }
87
 
        return c.fd.Read(b)
88
 
}
89
 
 
90
71
// ReadFrom implements the io.ReaderFrom ReadFrom method.
91
72
func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
92
73
        if n, err, handled := sendFile(c.fd, r); handled {
95
76
        return genericReadFrom(c, r)
96
77
}
97
78
 
98
 
// Write implements the Conn Write method.
99
 
func (c *TCPConn) Write(b []byte) (n int, err error) {
100
 
        if !c.ok() {
101
 
                return 0, syscall.EINVAL
102
 
        }
103
 
        return c.fd.Write(b)
104
 
}
105
 
 
106
 
// Close closes the TCP connection.
107
 
func (c *TCPConn) Close() error {
108
 
        if !c.ok() {
109
 
                return syscall.EINVAL
110
 
        }
111
 
        return c.fd.Close()
112
 
}
113
 
 
114
79
// CloseRead shuts down the reading side of the TCP connection.
115
80
// Most callers should just use Close.
116
81
func (c *TCPConn) CloseRead() error {
129
94
        return c.fd.CloseWrite()
130
95
}
131
96
 
132
 
// LocalAddr returns the local network address, a *TCPAddr.
133
 
func (c *TCPConn) LocalAddr() Addr {
134
 
        if !c.ok() {
135
 
                return nil
136
 
        }
137
 
        return c.fd.laddr
138
 
}
139
 
 
140
 
// RemoteAddr returns the remote network address, a *TCPAddr.
141
 
func (c *TCPConn) RemoteAddr() Addr {
142
 
        if !c.ok() {
143
 
                return nil
144
 
        }
145
 
        return c.fd.raddr
146
 
}
147
 
 
148
 
// SetDeadline implements the Conn SetDeadline method.
149
 
func (c *TCPConn) SetDeadline(t time.Time) error {
150
 
        if !c.ok() {
151
 
                return syscall.EINVAL
152
 
        }
153
 
        return setDeadline(c.fd, t)
154
 
}
155
 
 
156
 
// SetReadDeadline implements the Conn SetReadDeadline method.
157
 
func (c *TCPConn) SetReadDeadline(t time.Time) error {
158
 
        if !c.ok() {
159
 
                return syscall.EINVAL
160
 
        }
161
 
        return setReadDeadline(c.fd, t)
162
 
}
163
 
 
164
 
// SetWriteDeadline implements the Conn SetWriteDeadline method.
165
 
func (c *TCPConn) SetWriteDeadline(t time.Time) error {
166
 
        if !c.ok() {
167
 
                return syscall.EINVAL
168
 
        }
169
 
        return setWriteDeadline(c.fd, t)
170
 
}
171
 
 
172
 
// SetReadBuffer sets the size of the operating system's
173
 
// receive buffer associated with the connection.
174
 
func (c *TCPConn) SetReadBuffer(bytes int) error {
175
 
        if !c.ok() {
176
 
                return syscall.EINVAL
177
 
        }
178
 
        return setReadBuffer(c.fd, bytes)
179
 
}
180
 
 
181
 
// SetWriteBuffer sets the size of the operating system's
182
 
// transmit buffer associated with the connection.
183
 
func (c *TCPConn) SetWriteBuffer(bytes int) error {
184
 
        if !c.ok() {
185
 
                return syscall.EINVAL
186
 
        }
187
 
        return setWriteBuffer(c.fd, bytes)
188
 
}
189
 
 
190
 
// SetLinger sets the behavior of Close() on a connection
191
 
// which still has data waiting to be sent or to be acknowledged.
 
97
// SetLinger sets the behavior of Close() on a connection which still
 
98
// has data waiting to be sent or to be acknowledged.
192
99
//
193
 
// If sec < 0 (the default), Close returns immediately and
194
 
// the operating system finishes sending the data in the background.
 
100
// If sec < 0 (the default), Close returns immediately and the
 
101
// operating system finishes sending the data in the background.
195
102
//
196
103
// If sec == 0, Close returns immediately and the operating system
197
104
// discards any unsent or unacknowledged data.
198
105
//
199
 
// If sec > 0, Close blocks for at most sec seconds waiting for
200
 
// data to be sent and acknowledged.
 
106
// If sec > 0, Close blocks for at most sec seconds waiting for data
 
107
// to be sent and acknowledged.
201
108
func (c *TCPConn) SetLinger(sec int) error {
202
109
        if !c.ok() {
203
110
                return syscall.EINVAL
215
122
}
216
123
 
217
124
// SetNoDelay controls whether the operating system should delay
218
 
// packet transmission in hopes of sending fewer packets
219
 
// (Nagle's algorithm).  The default is true (no delay), meaning
220
 
// that data is sent as soon as possible after a Write.
 
125
// packet transmission in hopes of sending fewer packets (Nagle's
 
126
// algorithm).  The default is true (no delay), meaning that data is
 
127
// sent as soon as possible after a Write.
221
128
func (c *TCPConn) SetNoDelay(noDelay bool) error {
222
129
        if !c.ok() {
223
130
                return syscall.EINVAL
225
132
        return setNoDelay(c.fd, noDelay)
226
133
}
227
134
 
228
 
// File returns a copy of the underlying os.File, set to blocking mode.
229
 
// It is the caller's responsibility to close f when finished.
230
 
// Closing c does not affect f, and closing f does not affect c.
231
 
func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
232
 
 
233
135
// DialTCP connects to the remote address raddr on the network net,
234
 
// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
235
 
// as the local address for the connection.
 
136
// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
 
137
// used as the local address for the connection.
236
138
func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 
139
        switch net {
 
140
        case "tcp", "tcp4", "tcp6":
 
141
        default:
 
142
                return nil, UnknownNetworkError(net)
 
143
        }
237
144
        if raddr == nil {
238
145
                return nil, &OpError{"dial", net, nil, errMissingAddress}
239
146
        }
 
147
        return dialTCP(net, laddr, raddr, noDeadline)
 
148
}
240
149
 
241
 
        fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
 
150
func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
 
151
        fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
242
152
 
243
153
        // TCP has a rarely used mechanism called a 'simultaneous connection' in
244
154
        // which Dial("tcp", addr1, addr2) run on the machine at addr1 can
257
167
        // use the result.  See also:
258
168
        //      http://golang.org/issue/2690
259
169
        //      http://stackoverflow.com/questions/4949858/
260
 
        for i := 0; i < 2 && err == nil && laddr == nil && selfConnect(fd); i++ {
261
 
                fd.Close()
262
 
                fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
 
170
        //
 
171
        // The opposite can also happen: if we ask the kernel to pick an appropriate
 
172
        // originating local address, sometimes it picks one that is already in use.
 
173
        // So if the error is EADDRNOTAVAIL, we have to try again too, just for
 
174
        // a different reason.
 
175
        //
 
176
        // The kernel socket code is no doubt enjoying watching us squirm.
 
177
        for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
 
178
                if err == nil {
 
179
                        fd.Close()
 
180
                }
 
181
                fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
263
182
        }
264
183
 
265
184
        if err != nil {
268
187
        return newTCPConn(fd), nil
269
188
}
270
189
 
271
 
func selfConnect(fd *netFD) bool {
 
190
func selfConnect(fd *netFD, err error) bool {
 
191
        // If the connect failed, we clearly didn't connect to ourselves.
 
192
        if err != nil {
 
193
                return false
 
194
        }
 
195
 
272
196
        // The socket constructor can return an fd with raddr nil under certain
273
197
        // unknown conditions. The errors in the calls there to Getpeername
274
198
        // are discarded, but we can't catch the problem there because those
285
209
        return l.Port == r.Port && l.IP.Equal(r.IP)
286
210
}
287
211
 
288
 
// TCPListener is a TCP network listener.
289
 
// Clients should typically use variables of type Listener
290
 
// instead of assuming TCP.
 
212
func spuriousENOTAVAIL(err error) bool {
 
213
        e, ok := err.(*OpError)
 
214
        return ok && e.Err == syscall.EADDRNOTAVAIL
 
215
}
 
216
 
 
217
// TCPListener is a TCP network listener.  Clients should typically
 
218
// use variables of type Listener instead of assuming TCP.
291
219
type TCPListener struct {
292
220
        fd *netFD
293
221
}
294
222
 
295
 
// ListenTCP announces on the TCP address laddr and returns a TCP listener.
296
 
// Net must be "tcp", "tcp4", or "tcp6".
297
 
// If laddr has a port of 0, it means to listen on some available port.
298
 
// The caller can use l.Addr() to retrieve the chosen address.
299
 
func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
300
 
        fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
301
 
        if err != nil {
302
 
                return nil, err
303
 
        }
304
 
        err = syscall.Listen(fd.sysfd, listenerBacklog)
305
 
        if err != nil {
306
 
                closesocket(fd.sysfd)
307
 
                return nil, &OpError{"listen", net, laddr, err}
308
 
        }
309
 
        l := new(TCPListener)
310
 
        l.fd = fd
311
 
        return l, nil
312
 
}
313
 
 
314
 
// AcceptTCP accepts the next incoming call and returns the new connection
315
 
// and the remote address.
316
 
func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
317
 
        if l == nil || l.fd == nil || l.fd.sysfd < 0 {
 
223
// AcceptTCP accepts the next incoming call and returns the new
 
224
// connection and the remote address.
 
225
func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
 
226
        if l == nil || l.fd == nil {
318
227
                return nil, syscall.EINVAL
319
228
        }
320
229
        fd, err := l.fd.accept(sockaddrToTCP)
324
233
        return newTCPConn(fd), nil
325
234
}
326
235
 
327
 
// Accept implements the Accept method in the Listener interface;
328
 
// it waits for the next call and returns a generic Conn.
329
 
func (l *TCPListener) Accept() (c Conn, err error) {
330
 
        c1, err := l.AcceptTCP()
 
236
// Accept implements the Accept method in the Listener interface; it
 
237
// waits for the next call and returns a generic Conn.
 
238
func (l *TCPListener) Accept() (Conn, error) {
 
239
        c, err := l.AcceptTCP()
331
240
        if err != nil {
332
241
                return nil, err
333
242
        }
334
 
        return c1, nil
 
243
        return c, nil
335
244
}
336
245
 
337
246
// Close stops listening on the TCP address.
355
264
        return setDeadline(l.fd, t)
356
265
}
357
266
 
358
 
// File returns a copy of the underlying os.File, set to blocking mode.
359
 
// It is the caller's responsibility to close f when finished.
 
267
// File returns a copy of the underlying os.File, set to blocking
 
268
// mode.  It is the caller's responsibility to close f when finished.
360
269
// Closing l does not affect f, and closing f does not affect l.
 
270
//
 
271
// The returned os.File's file descriptor is different from the
 
272
// connection's.  Attempting to change properties of the original
 
273
// using this duplicate may or may not have the desired effect.
361
274
func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
 
275
 
 
276
// ListenTCP announces on the TCP address laddr and returns a TCP
 
277
// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
 
278
// port of 0, ListenTCP will choose an available port.  The caller can
 
279
// use the Addr method of TCPListener to retrieve the chosen address.
 
280
func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 
281
        switch net {
 
282
        case "tcp", "tcp4", "tcp6":
 
283
        default:
 
284
                return nil, UnknownNetworkError(net)
 
285
        }
 
286
        if laddr == nil {
 
287
                laddr = &TCPAddr{}
 
288
        }
 
289
        fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
 
290
        if err != nil {
 
291
                return nil, err
 
292
        }
 
293
        err = syscall.Listen(fd.sysfd, listenerBacklog)
 
294
        if err != nil {
 
295
                fd.Close()
 
296
                return nil, &OpError{"listen", net, laddr, err}
 
297
        }
 
298
        return &TCPListener{fd}, nil
 
299
}