~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
6
 
 
7
package net
 
8
 
 
9
import (
 
10
        "io"
 
11
        "os"
 
12
        "sync"
 
13
        "syscall"
 
14
        "time"
 
15
)
 
16
 
 
17
// Network file descriptor.
 
18
type netFD struct {
 
19
        // locking/lifetime of sysfd
 
20
        sysmu  sync.Mutex
 
21
        sysref int
 
22
 
 
23
        // must lock both sysmu and pollDesc to write
 
24
        // can lock either to read
 
25
        closing bool
 
26
 
 
27
        // immutable until Close
 
28
        sysfd       int
 
29
        family      int
 
30
        sotype      int
 
31
        isConnected bool
 
32
        sysfile     *os.File
 
33
        net         string
 
34
        laddr       Addr
 
35
        raddr       Addr
 
36
 
 
37
        // serialize access to Read and Write methods
 
38
        rio, wio sync.Mutex
 
39
 
 
40
        // wait server
 
41
        pd pollDesc
 
42
}
 
43
 
 
44
func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
 
45
        ra, err := resolveAddr("dial", net, addr, deadline)
 
46
        if err != nil {
 
47
                return nil, err
 
48
        }
 
49
        return dial(net, addr, localAddr, ra, deadline)
 
50
}
 
51
 
 
52
func newFD(fd, family, sotype int, net string) (*netFD, error) {
 
53
        netfd := &netFD{
 
54
                sysfd:  fd,
 
55
                family: family,
 
56
                sotype: sotype,
 
57
                net:    net,
 
58
        }
 
59
        if err := netfd.pd.Init(netfd); err != nil {
 
60
                return nil, err
 
61
        }
 
62
        return netfd, nil
 
63
}
 
64
 
 
65
func (fd *netFD) setAddr(laddr, raddr Addr) {
 
66
        fd.laddr = laddr
 
67
        fd.raddr = raddr
 
68
        fd.sysfile = os.NewFile(uintptr(fd.sysfd), fd.net)
 
69
}
 
70
 
 
71
func (fd *netFD) name() string {
 
72
        var ls, rs string
 
73
        if fd.laddr != nil {
 
74
                ls = fd.laddr.String()
 
75
        }
 
76
        if fd.raddr != nil {
 
77
                rs = fd.raddr.String()
 
78
        }
 
79
        return fd.net + ":" + ls + "->" + rs
 
80
}
 
81
 
 
82
func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
 
83
        fd.wio.Lock()
 
84
        defer fd.wio.Unlock()
 
85
        if err := fd.pd.PrepareWrite(); err != nil {
 
86
                return err
 
87
        }
 
88
        for {
 
89
                err := syscall.Connect(fd.sysfd, ra)
 
90
                if err == nil || err == syscall.EISCONN {
 
91
                        break
 
92
                }
 
93
                if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR {
 
94
                        return err
 
95
                }
 
96
                if err = fd.pd.WaitWrite(); err != nil {
 
97
                        return err
 
98
                }
 
99
        }
 
100
        return nil
 
101
}
 
102
 
 
103
// Add a reference to this fd.
 
104
// If closing==true, pollDesc must be locked; mark the fd as closing.
 
105
// Returns an error if the fd cannot be used.
 
106
func (fd *netFD) incref(closing bool) error {
 
107
        fd.sysmu.Lock()
 
108
        if fd.closing {
 
109
                fd.sysmu.Unlock()
 
110
                return errClosing
 
111
        }
 
112
        fd.sysref++
 
113
        if closing {
 
114
                fd.closing = true
 
115
        }
 
116
        fd.sysmu.Unlock()
 
117
        return nil
 
118
}
 
119
 
 
120
// Remove a reference to this FD and close if we've been asked to do so (and
 
121
// there are no references left.
 
122
func (fd *netFD) decref() {
 
123
        fd.sysmu.Lock()
 
124
        fd.sysref--
 
125
        if fd.closing && fd.sysref == 0 {
 
126
                // Poller may want to unregister fd in readiness notification mechanism,
 
127
                // so this must be executed before sysfile.Close().
 
128
                fd.pd.Close()
 
129
                if fd.sysfile != nil {
 
130
                        fd.sysfile.Close()
 
131
                        fd.sysfile = nil
 
132
                } else {
 
133
                        closesocket(fd.sysfd)
 
134
                }
 
135
                fd.sysfd = -1
 
136
        }
 
137
        fd.sysmu.Unlock()
 
138
}
 
139
 
 
140
func (fd *netFD) Close() error {
 
141
        fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
 
142
        if err := fd.incref(true); err != nil {
 
143
                fd.pd.Unlock()
 
144
                return err
 
145
        }
 
146
        // Unblock any I/O.  Once it all unblocks and returns,
 
147
        // so that it cannot be referring to fd.sysfd anymore,
 
148
        // the final decref will close fd.sysfd.  This should happen
 
149
        // fairly quickly, since all the I/O is non-blocking, and any
 
150
        // attempts to block in the pollDesc will return errClosing.
 
151
        doWakeup := fd.pd.Evict()
 
152
        fd.pd.Unlock()
 
153
        fd.decref()
 
154
        if doWakeup {
 
155
                fd.pd.Wakeup()
 
156
        }
 
157
        return nil
 
158
}
 
159
 
 
160
func (fd *netFD) shutdown(how int) error {
 
161
        if err := fd.incref(false); err != nil {
 
162
                return err
 
163
        }
 
164
        defer fd.decref()
 
165
        err := syscall.Shutdown(fd.sysfd, how)
 
166
        if err != nil {
 
167
                return &OpError{"shutdown", fd.net, fd.laddr, err}
 
168
        }
 
169
        return nil
 
170
}
 
171
 
 
172
func (fd *netFD) CloseRead() error {
 
173
        return fd.shutdown(syscall.SHUT_RD)
 
174
}
 
175
 
 
176
func (fd *netFD) CloseWrite() error {
 
177
        return fd.shutdown(syscall.SHUT_WR)
 
178
}
 
179
 
 
180
func (fd *netFD) Read(p []byte) (n int, err error) {
 
181
        fd.rio.Lock()
 
182
        defer fd.rio.Unlock()
 
183
        if err := fd.incref(false); err != nil {
 
184
                return 0, err
 
185
        }
 
186
        defer fd.decref()
 
187
        if err := fd.pd.PrepareRead(); err != nil {
 
188
                return 0, &OpError{"read", fd.net, fd.raddr, err}
 
189
        }
 
190
        for {
 
191
                n, err = syscall.Read(int(fd.sysfd), p)
 
192
                if err != nil {
 
193
                        n = 0
 
194
                        if err == syscall.EAGAIN {
 
195
                                if err = fd.pd.WaitRead(); err == nil {
 
196
                                        continue
 
197
                                }
 
198
                        }
 
199
                }
 
200
                err = chkReadErr(n, err, fd)
 
201
                break
 
202
        }
 
203
        if err != nil && err != io.EOF {
 
204
                err = &OpError{"read", fd.net, fd.raddr, err}
 
205
        }
 
206
        return
 
207
}
 
208
 
 
209
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
 
210
        fd.rio.Lock()
 
211
        defer fd.rio.Unlock()
 
212
        if err := fd.incref(false); err != nil {
 
213
                return 0, nil, err
 
214
        }
 
215
        defer fd.decref()
 
216
        if err := fd.pd.PrepareRead(); err != nil {
 
217
                return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
 
218
        }
 
219
        for {
 
220
                n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
 
221
                if err != nil {
 
222
                        n = 0
 
223
                        if err == syscall.EAGAIN {
 
224
                                if err = fd.pd.WaitRead(); err == nil {
 
225
                                        continue
 
226
                                }
 
227
                        }
 
228
                }
 
229
                err = chkReadErr(n, err, fd)
 
230
                break
 
231
        }
 
232
        if err != nil && err != io.EOF {
 
233
                err = &OpError{"read", fd.net, fd.laddr, err}
 
234
        }
 
235
        return
 
236
}
 
237
 
 
238
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
 
239
        fd.rio.Lock()
 
240
        defer fd.rio.Unlock()
 
241
        if err := fd.incref(false); err != nil {
 
242
                return 0, 0, 0, nil, err
 
243
        }
 
244
        defer fd.decref()
 
245
        if err := fd.pd.PrepareRead(); err != nil {
 
246
                return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
 
247
        }
 
248
        for {
 
249
                n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
 
250
                if err != nil {
 
251
                        // TODO(dfc) should n and oobn be set to 0
 
252
                        if err == syscall.EAGAIN {
 
253
                                if err = fd.pd.WaitRead(); err == nil {
 
254
                                        continue
 
255
                                }
 
256
                        }
 
257
                }
 
258
                err = chkReadErr(n, err, fd)
 
259
                break
 
260
        }
 
261
        if err != nil && err != io.EOF {
 
262
                err = &OpError{"read", fd.net, fd.laddr, err}
 
263
        }
 
264
        return
 
265
}
 
266
 
 
267
func chkReadErr(n int, err error, fd *netFD) error {
 
268
        if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
 
269
                return io.EOF
 
270
        }
 
271
        return err
 
272
}
 
273
 
 
274
func (fd *netFD) Write(p []byte) (nn int, err error) {
 
275
        fd.wio.Lock()
 
276
        defer fd.wio.Unlock()
 
277
        if err := fd.incref(false); err != nil {
 
278
                return 0, err
 
279
        }
 
280
        defer fd.decref()
 
281
        if err := fd.pd.PrepareWrite(); err != nil {
 
282
                return 0, &OpError{"write", fd.net, fd.raddr, err}
 
283
        }
 
284
        for {
 
285
                var n int
 
286
                n, err = syscall.Write(int(fd.sysfd), p[nn:])
 
287
                if n > 0 {
 
288
                        nn += n
 
289
                }
 
290
                if nn == len(p) {
 
291
                        break
 
292
                }
 
293
                if err == syscall.EAGAIN {
 
294
                        if err = fd.pd.WaitWrite(); err == nil {
 
295
                                continue
 
296
                        }
 
297
                }
 
298
                if err != nil {
 
299
                        n = 0
 
300
                        break
 
301
                }
 
302
                if n == 0 {
 
303
                        err = io.ErrUnexpectedEOF
 
304
                        break
 
305
                }
 
306
        }
 
307
        if err != nil {
 
308
                err = &OpError{"write", fd.net, fd.raddr, err}
 
309
        }
 
310
        return nn, err
 
311
}
 
312
 
 
313
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
 
314
        fd.wio.Lock()
 
315
        defer fd.wio.Unlock()
 
316
        if err := fd.incref(false); err != nil {
 
317
                return 0, err
 
318
        }
 
319
        defer fd.decref()
 
320
        if err := fd.pd.PrepareWrite(); err != nil {
 
321
                return 0, &OpError{"write", fd.net, fd.raddr, err}
 
322
        }
 
323
        for {
 
324
                err = syscall.Sendto(fd.sysfd, p, 0, sa)
 
325
                if err == syscall.EAGAIN {
 
326
                        if err = fd.pd.WaitWrite(); err == nil {
 
327
                                continue
 
328
                        }
 
329
                }
 
330
                break
 
331
        }
 
332
        if err == nil {
 
333
                n = len(p)
 
334
        } else {
 
335
                err = &OpError{"write", fd.net, fd.raddr, err}
 
336
        }
 
337
        return
 
338
}
 
339
 
 
340
func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
 
341
        fd.wio.Lock()
 
342
        defer fd.wio.Unlock()
 
343
        if err := fd.incref(false); err != nil {
 
344
                return 0, 0, err
 
345
        }
 
346
        defer fd.decref()
 
347
        if err := fd.pd.PrepareWrite(); err != nil {
 
348
                return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
 
349
        }
 
350
        for {
 
351
                err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
 
352
                if err == syscall.EAGAIN {
 
353
                        if err = fd.pd.WaitWrite(); err == nil {
 
354
                                continue
 
355
                        }
 
356
                }
 
357
                break
 
358
        }
 
359
        if err == nil {
 
360
                n = len(p)
 
361
                oobn = len(oob)
 
362
        } else {
 
363
                err = &OpError{"write", fd.net, fd.raddr, err}
 
364
        }
 
365
        return
 
366
}
 
367
 
 
368
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
 
369
        fd.rio.Lock()
 
370
        defer fd.rio.Unlock()
 
371
        if err := fd.incref(false); err != nil {
 
372
                return nil, err
 
373
        }
 
374
        defer fd.decref()
 
375
 
 
376
        var s int
 
377
        var rsa syscall.Sockaddr
 
378
        if err = fd.pd.PrepareRead(); err != nil {
 
379
                return nil, &OpError{"accept", fd.net, fd.laddr, err}
 
380
        }
 
381
        for {
 
382
                s, rsa, err = accept(fd.sysfd)
 
383
                if err != nil {
 
384
                        if err == syscall.EAGAIN {
 
385
                                if err = fd.pd.WaitRead(); err == nil {
 
386
                                        continue
 
387
                                }
 
388
                        } else if err == syscall.ECONNABORTED {
 
389
                                // This means that a socket on the listen queue was closed
 
390
                                // before we Accept()ed it; it's a silly error, so try again.
 
391
                                continue
 
392
                        }
 
393
                        return nil, &OpError{"accept", fd.net, fd.laddr, err}
 
394
                }
 
395
                break
 
396
        }
 
397
 
 
398
        if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
 
399
                closesocket(s)
 
400
                return nil, err
 
401
        }
 
402
        lsa, _ := syscall.Getsockname(netfd.sysfd)
 
403
        netfd.setAddr(toAddr(lsa), toAddr(rsa))
 
404
        return netfd, nil
 
405
}
 
406
 
 
407
func (fd *netFD) dup() (f *os.File, err error) {
 
408
        syscall.ForkLock.RLock()
 
409
        ns, err := syscall.Dup(fd.sysfd)
 
410
        if err != nil {
 
411
                syscall.ForkLock.RUnlock()
 
412
                return nil, &OpError{"dup", fd.net, fd.laddr, err}
 
413
        }
 
414
        syscall.CloseOnExec(ns)
 
415
        syscall.ForkLock.RUnlock()
 
416
 
 
417
        // We want blocking mode for the new fd, hence the double negative.
 
418
        // This also puts the old fd into blocking mode, meaning that
 
419
        // I/O will block the thread instead of letting us use the epoll server.
 
420
        // Everything will still work, just with more threads.
 
421
        if err = syscall.SetNonblock(ns, false); err != nil {
 
422
                return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
 
423
        }
 
424
 
 
425
        return os.NewFile(uintptr(ns), fd.name()), nil
 
426
}
 
427
 
 
428
func closesocket(s int) error {
 
429
        return syscall.Close(s)
 
430
}