blob: 24e6c59f370785d141c1be6a1b6529e826ad8c1c [file] [log] [blame]
Russ Coxe4a61c62008-09-29 13:37:00 -07001// 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
Dave Cheney7c8280c2014-02-25 09:47:42 -05005// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
Russ Cox27159562011-09-15 16:48:57 -04006
Russ Coxe4a61c62008-09-29 13:37:00 -07007package net
8
9import (
Russ Cox47a05332010-04-26 22:15:25 -070010 "io"
Robert Griesemera3d10452009-12-15 15:35:38 -080011 "os"
Dmitriy Vyukov3b6de5e2013-07-30 19:47:16 +040012 "runtime"
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -070013 "sync/atomic"
Robert Griesemera3d10452009-12-15 15:35:38 -080014 "syscall"
Russ Cox00f9f0c2010-03-30 10:34:57 -070015 "time"
Russ Coxe4a61c62008-09-29 13:37:00 -070016)
17
Russ Coxd8921c52009-02-15 14:18:39 -080018// Network file descriptor.
19type netFD struct {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +040020 // locking/lifetime of sysfd + serialize access to Read and Write methods
21 fdmu fdMutex
Devon H. O'Delleb163462009-12-01 23:28:57 -080022
Russ Coxe4a61c62008-09-29 13:37:00 -070023 // immutable until Close
Mikio Hara974fa752012-01-27 01:31:42 +090024 sysfd int
25 family int
26 sotype int
27 isConnected bool
Mikio Hara974fa752012-01-27 01:31:42 +090028 net string
29 laddr Addr
30 raddr Addr
Russ Coxe4a61c62008-09-29 13:37:00 -070031
Sébastien Paolacci7014bc62012-09-26 15:32:59 -040032 // wait server
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +040033 pd pollDesc
Russ Coxe4a61c62008-09-29 13:37:00 -070034}
35
Alex Brainman1a948952013-05-20 15:23:45 +100036func sysInit() {
37}
38
Mikio Hara89b26762013-09-11 10:48:53 -040039func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
40 return dialer(deadline)
Alex Brainman810e4392013-01-11 12:42:09 +110041}
42
Mikio Hara6a76bca362013-08-06 23:42:33 +090043func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
44 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
45}
46
47func (fd *netFD) init() error {
48 if err := fd.pd.Init(fd); err != nil {
49 return err
Robert Griesemera3d10452009-12-15 15:35:38 -080050 }
Mikio Hara6a76bca362013-08-06 23:42:33 +090051 return nil
Alexey Borzenkov2f45f722011-03-28 23:40:01 -040052}
53
54func (fd *netFD) setAddr(laddr, raddr Addr) {
55 fd.laddr = laddr
56 fd.raddr = raddr
Dmitriy Vyukov3b6de5e2013-07-30 19:47:16 +040057 runtime.SetFinalizer(fd, (*netFD).Close)
Dave Cheney067315c2012-10-26 19:41:21 +110058}
59
60func (fd *netFD) name() string {
Robert Griesemera3d10452009-12-15 15:35:38 -080061 var ls, rs string
Dave Cheney067315c2012-10-26 19:41:21 +110062 if fd.laddr != nil {
63 ls = fd.laddr.String()
Russ Coxc83b8382009-11-02 18:37:30 -080064 }
Dave Cheney067315c2012-10-26 19:41:21 +110065 if fd.raddr != nil {
66 rs = fd.raddr.String()
Russ Coxc83b8382009-11-02 18:37:30 -080067 }
Dave Cheney067315c2012-10-26 19:41:21 +110068 return fd.net + ":" + ls + "->" + rs
Alexey Borzenkov2f45f722011-03-28 23:40:01 -040069}
70
Mikio Harac0325f52014-07-29 16:48:11 +090071func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +040072 // Do not need to call fd.writeLock here,
73 // because fd is not yet accessible to user,
74 // so no concurrent operations are possible.
Mikio Harad1e3ad82014-03-25 02:56:10 +090075 switch err := syscall.Connect(fd.sysfd, ra); err {
76 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
77 case nil, syscall.EISCONN:
Mikio Harac0325f52014-07-29 16:48:11 +090078 if !deadline.IsZero() && deadline.Before(time.Now()) {
79 return errTimeout
80 }
81 if err := fd.init(); err != nil {
82 return err
83 }
Mikio Harad1e3ad82014-03-25 02:56:10 +090084 return nil
85 case syscall.EINVAL:
Ian Lance Taylor672525a2013-12-28 09:37:54 -080086 // On Solaris we can see EINVAL if the socket has
87 // already been accepted and closed by the server.
88 // Treat this as a successful connection--writes to
89 // the socket will see EOF. For details and a test
90 // case in C see http://golang.org/issue/6828.
Mikio Harad1e3ad82014-03-25 02:56:10 +090091 if runtime.GOOS == "solaris" {
92 return nil
Ian Lance Taylor672525a2013-12-28 09:37:54 -080093 }
Mikio Harad1e3ad82014-03-25 02:56:10 +090094 fallthrough
95 default:
96 return err
97 }
Mikio Harac0325f52014-07-29 16:48:11 +090098 if err := fd.init(); err != nil {
99 return err
100 }
101 if !deadline.IsZero() {
102 fd.setWriteDeadline(deadline)
103 defer fd.setWriteDeadline(noDeadline)
104 }
Mikio Harad1e3ad82014-03-25 02:56:10 +0900105 for {
106 // Performing multiple connect system calls on a
107 // non-blocking socket under Unix variants does not
108 // necessarily result in earlier errors being
109 // returned. Instead, once runtime-integrated network
110 // poller tells us that the socket is ready, get the
111 // SO_ERROR socket option to see if the connection
112 // succeeded or failed. See issue 7474 for further
113 // details.
114 if err := fd.pd.WaitWrite(); err != nil {
Dmitriy Vyukova11d7d42013-03-14 10:32:42 +0400115 return err
116 }
Mikio Harad1e3ad82014-03-25 02:56:10 +0900117 nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
118 if err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500119 return err
120 }
Mikio Harad1e3ad82014-03-25 02:56:10 +0900121 switch err := syscall.Errno(nerr); err {
122 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
123 case syscall.Errno(0), syscall.EISCONN:
124 return nil
125 default:
126 return err
Joel Sing734d4632014-03-06 00:07:16 +1100127 }
Alexey Borzenkov2f45f722011-03-28 23:40:01 -0400128 }
Russ Coxe4a61c62008-09-29 13:37:00 -0700129}
130
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400131func (fd *netFD) destroy() {
132 // Poller may want to unregister fd in readiness notification mechanism,
133 // so this must be executed before closesocket.
134 fd.pd.Close()
135 closesocket(fd.sysfd)
136 fd.sysfd = -1
137 runtime.SetFinalizer(fd, nil)
138}
139
Devon H. O'Delleb163462009-12-01 23:28:57 -0800140// Add a reference to this fd.
Russ Cox5e4e3d82012-02-14 00:40:37 -0500141// Returns an error if the fd cannot be used.
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400142func (fd *netFD) incref() error {
143 if !fd.fdmu.Incref() {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500144 return errClosing
145 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500146 return nil
Devon H. O'Delleb163462009-12-01 23:28:57 -0800147}
148
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400149// Remove a reference to this FD and close if we've been asked to do so
150// (and there are no references left).
Devon H. O'Delleb163462009-12-01 23:28:57 -0800151func (fd *netFD) decref() {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400152 if fd.fdmu.Decref() {
153 fd.destroy()
Devon H. O'Delleb163462009-12-01 23:28:57 -0800154 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400155}
156
157// Add a reference to this fd and lock for reading.
158// Returns an error if the fd cannot be used.
159func (fd *netFD) readLock() error {
160 if !fd.fdmu.RWLock(true) {
161 return errClosing
162 }
163 return nil
164}
165
166// Unlock for reading and remove a reference to this FD.
167func (fd *netFD) readUnlock() {
168 if fd.fdmu.RWUnlock(true) {
169 fd.destroy()
170 }
171}
172
173// Add a reference to this fd and lock for writing.
174// Returns an error if the fd cannot be used.
175func (fd *netFD) writeLock() error {
176 if !fd.fdmu.RWLock(false) {
177 return errClosing
178 }
179 return nil
180}
181
182// Unlock for writing and remove a reference to this FD.
183func (fd *netFD) writeUnlock() {
184 if fd.fdmu.RWUnlock(false) {
185 fd.destroy()
186 }
Devon H. O'Delleb163462009-12-01 23:28:57 -0800187}
188
Russ Coxeb692922011-11-01 22:05:34 -0400189func (fd *netFD) Close() error {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400190 if !fd.fdmu.IncrefAndClose() {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400191 return errClosing
Russ Coxe4a61c62008-09-29 13:37:00 -0700192 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500193 // Unblock any I/O. Once it all unblocks and returns,
194 // so that it cannot be referring to fd.sysfd anymore,
195 // the final decref will close fd.sysfd. This should happen
196 // fairly quickly, since all the I/O is non-blocking, and any
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400197 // attempts to block in the pollDesc will return errClosing.
Mikio Harac768a842015-02-04 18:00:52 +0900198 fd.pd.Evict()
Robert Griesemera3d10452009-12-15 15:35:38 -0800199 fd.decref()
200 return nil
Russ Coxe4a61c62008-09-29 13:37:00 -0700201}
202
Russ Coxeb692922011-11-01 22:05:34 -0400203func (fd *netFD) shutdown(how int) error {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400204 if err := fd.incref(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500205 return err
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700206 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500207 defer fd.decref()
Russ Coxc017a822011-11-13 22:44:52 -0500208 err := syscall.Shutdown(fd.sysfd, how)
209 if err != nil {
210 return &OpError{"shutdown", fd.net, fd.laddr, err}
Albert Strasheim791b2a42011-10-12 13:45:25 -0400211 }
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700212 return nil
213}
214
Mikio Haraebe5f202014-04-04 09:07:44 +0900215func (fd *netFD) closeRead() error {
Albert Strasheim791b2a42011-10-12 13:45:25 -0400216 return fd.shutdown(syscall.SHUT_RD)
217}
218
Mikio Haraebe5f202014-04-04 09:07:44 +0900219func (fd *netFD) closeWrite() error {
Albert Strasheim791b2a42011-10-12 13:45:25 -0400220 return fd.shutdown(syscall.SHUT_WR)
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700221}
222
Russ Coxeb692922011-11-01 22:05:34 -0400223func (fd *netFD) Read(p []byte) (n int, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400224 if err := fd.readLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500225 return 0, err
Michael Hoisie9192ec22010-05-20 17:13:50 -0700226 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400227 defer fd.readUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400228 if err := fd.pd.PrepareRead(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400229 return 0, &OpError{"read", fd.net, fd.raddr, err}
230 }
Russ Coxa0bcaf42009-06-25 20:24:55 -0700231 for {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500232 n, err = syscall.Read(int(fd.sysfd), p)
Dave Cheney28b599422012-11-28 11:29:25 +1100233 if err != nil {
Dave Cheney73b3e232012-11-26 10:59:43 +1100234 n = 0
Dave Cheney28b599422012-11-28 11:29:25 +1100235 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400236 if err = fd.pd.WaitRead(); err == nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500237 continue
238 }
239 }
Russ Coxa0bcaf42009-06-25 20:24:55 -0700240 }
Mikio Haraa877e812014-12-31 10:08:51 +0900241 err = fd.eofError(n, err)
Robert Griesemera3d10452009-12-15 15:35:38 -0800242 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700243 }
Russ Coxc017a822011-11-13 22:44:52 -0500244 if err != nil && err != io.EOF {
245 err = &OpError{"read", fd.net, fd.raddr, err}
Russ Coxe89441b2009-12-02 15:17:49 -0800246 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800247 return
Russ Coxe4a61c62008-09-29 13:37:00 -0700248}
249
Ian Lance Taylor7d299d02014-04-02 17:06:51 -0700250func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400251 if err := fd.readLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500252 return 0, nil, err
253 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400254 defer fd.readUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400255 if err := fd.pd.PrepareRead(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400256 return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
257 }
Russ Cox6e788e02009-11-17 08:39:17 -0800258 for {
Russ Coxc017a822011-11-13 22:44:52 -0500259 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
Dave Cheney28b599422012-11-28 11:29:25 +1100260 if err != nil {
Dave Cheney73b3e232012-11-26 10:59:43 +1100261 n = 0
Dave Cheney28b599422012-11-28 11:29:25 +1100262 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400263 if err = fd.pd.WaitRead(); err == nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500264 continue
265 }
266 }
Russ Cox6e788e02009-11-17 08:39:17 -0800267 }
Mikio Haraa877e812014-12-31 10:08:51 +0900268 err = fd.eofError(n, err)
Robert Griesemera3d10452009-12-15 15:35:38 -0800269 break
Russ Cox6e788e02009-11-17 08:39:17 -0800270 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500271 if err != nil && err != io.EOF {
Russ Coxc017a822011-11-13 22:44:52 -0500272 err = &OpError{"read", fd.net, fd.laddr, err}
Russ Cox47a05332010-04-26 22:15:25 -0700273 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800274 return
Russ Cox6e788e02009-11-17 08:39:17 -0800275}
276
Ian Lance Taylor7d299d02014-04-02 17:06:51 -0700277func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400278 if err := fd.readLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500279 return 0, 0, 0, nil, err
280 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400281 defer fd.readUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400282 if err := fd.pd.PrepareRead(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400283 return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
284 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500285 for {
Russ Coxc017a822011-11-13 22:44:52 -0500286 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
Dave Cheney28b599422012-11-28 11:29:25 +1100287 if err != nil {
Dave Cheney9fb96992012-12-05 15:59:01 +1100288 // TODO(dfc) should n and oobn be set to 0
Dave Cheney28b599422012-11-28 11:29:25 +1100289 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400290 if err = fd.pd.WaitRead(); err == nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500291 continue
292 }
293 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500294 }
Mikio Haraa877e812014-12-31 10:08:51 +0900295 err = fd.eofError(n, err)
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500296 break
297 }
Russ Coxc017a822011-11-13 22:44:52 -0500298 if err != nil && err != io.EOF {
299 err = &OpError{"read", fd.net, fd.laddr, err}
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500300 }
301 return
302}
303
Dave Cheney9fb96992012-12-05 15:59:01 +1100304func (fd *netFD) Write(p []byte) (nn int, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400305 if err := fd.writeLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500306 return 0, err
307 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400308 defer fd.writeUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400309 if err := fd.pd.PrepareWrite(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400310 return 0, &OpError{"write", fd.net, fd.raddr, err}
311 }
Russ Cox47a05332010-04-26 22:15:25 -0700312 for {
Russ Coxc017a822011-11-13 22:44:52 -0500313 var n int
Russ Cox5e4e3d82012-02-14 00:40:37 -0500314 n, err = syscall.Write(int(fd.sysfd), p[nn:])
Russ Coxe4a61c62008-09-29 13:37:00 -0700315 if n > 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800316 nn += n
Russ Coxe4a61c62008-09-29 13:37:00 -0700317 }
Russ Cox1e37e8a2009-03-06 17:51:31 -0800318 if nn == len(p) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800319 break
Russ Cox1e37e8a2009-03-06 17:51:31 -0800320 }
Russ Coxc017a822011-11-13 22:44:52 -0500321 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400322 if err = fd.pd.WaitWrite(); err == nil {
Dave Cheney28b599422012-11-28 11:29:25 +1100323 continue
Russ Cox5e4e3d82012-02-14 00:40:37 -0500324 }
Russ Cox1e37e8a2009-03-06 17:51:31 -0800325 }
Russ Coxc017a822011-11-13 22:44:52 -0500326 if err != nil {
Russ Cox47a05332010-04-26 22:15:25 -0700327 n = 0
Robert Griesemer40621d52009-11-09 12:07:39 -0800328 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700329 }
Russ Cox47a05332010-04-26 22:15:25 -0700330 if n == 0 {
Russ Coxc017a822011-11-13 22:44:52 -0500331 err = io.ErrUnexpectedEOF
Russ Cox47a05332010-04-26 22:15:25 -0700332 break
333 }
334 }
Russ Coxc017a822011-11-13 22:44:52 -0500335 if err != nil {
336 err = &OpError{"write", fd.net, fd.raddr, err}
Russ Coxe4a61c62008-09-29 13:37:00 -0700337 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800338 return nn, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700339}
340
Ian Lance Taylor7d299d02014-04-02 17:06:51 -0700341func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400342 if err := fd.writeLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500343 return 0, err
344 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400345 defer fd.writeUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400346 if err := fd.pd.PrepareWrite(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400347 return 0, &OpError{"write", fd.net, fd.raddr, err}
348 }
Russ Cox6e788e02009-11-17 08:39:17 -0800349 for {
Russ Coxc017a822011-11-13 22:44:52 -0500350 err = syscall.Sendto(fd.sysfd, p, 0, sa)
351 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400352 if err = fd.pd.WaitWrite(); err == nil {
Dave Cheney28b599422012-11-28 11:29:25 +1100353 continue
Russ Cox5e4e3d82012-02-14 00:40:37 -0500354 }
Russ Cox6e788e02009-11-17 08:39:17 -0800355 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800356 break
Russ Cox6e788e02009-11-17 08:39:17 -0800357 }
Russ Coxc017a822011-11-13 22:44:52 -0500358 if err == nil {
Russ Cox6e788e02009-11-17 08:39:17 -0800359 n = len(p)
Russ Cox47a05332010-04-26 22:15:25 -0700360 } else {
Russ Coxc017a822011-11-13 22:44:52 -0500361 err = &OpError{"write", fd.net, fd.raddr, err}
Russ Cox6e788e02009-11-17 08:39:17 -0800362 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800363 return
Russ Cox6e788e02009-11-17 08:39:17 -0800364}
365
Ian Lance Taylor7d299d02014-04-02 17:06:51 -0700366func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400367 if err := fd.writeLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500368 return 0, 0, err
369 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400370 defer fd.writeUnlock()
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400371 if err := fd.pd.PrepareWrite(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400372 return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
373 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500374 for {
Mikio Harae419ab62014-04-26 06:52:37 +0900375 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
Russ Coxc017a822011-11-13 22:44:52 -0500376 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400377 if err = fd.pd.WaitWrite(); err == nil {
Dave Cheney28b599422012-11-28 11:29:25 +1100378 continue
Russ Cox5e4e3d82012-02-14 00:40:37 -0500379 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500380 }
381 break
382 }
Russ Coxc017a822011-11-13 22:44:52 -0500383 if err == nil {
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500384 oobn = len(oob)
385 } else {
Russ Coxc017a822011-11-13 22:44:52 -0500386 err = &OpError{"write", fd.net, fd.raddr, err}
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500387 }
388 return
389}
390
Mikio Hara5c055e72014-08-05 06:10:46 +0900391func (fd *netFD) accept() (netfd *netFD, err error) {
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400392 if err := fd.readLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500393 return nil, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700394 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400395 defer fd.readUnlock()
Devon H. O'Delleb163462009-12-01 23:28:57 -0800396
Russ Coxc017a822011-11-13 22:44:52 -0500397 var s int
Mikio Harac20ced92011-08-16 16:53:09 -0400398 var rsa syscall.Sockaddr
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400399 if err = fd.pd.PrepareRead(); err != nil {
Dmitriy Vyukov0f136f22013-03-07 17:03:40 +0400400 return nil, &OpError{"accept", fd.net, fd.laddr, err}
401 }
Russ Coxd8921c52009-02-15 14:18:39 -0800402 for {
Ian Lance Taylor31f58dc2013-01-28 08:54:15 -0800403 s, rsa, err = accept(fd.sysfd)
Russ Coxc017a822011-11-13 22:44:52 -0500404 if err != nil {
Russ Coxc017a822011-11-13 22:44:52 -0500405 if err == syscall.EAGAIN {
Dmitriy Vyukovb09d8812013-03-13 00:03:00 +0400406 if err = fd.pd.WaitRead(); err == nil {
Dave Cheney28b599422012-11-28 11:29:25 +1100407 continue
Russ Cox5e4e3d82012-02-14 00:40:37 -0500408 }
Devon H. O'Della63c37b2012-03-27 00:06:14 -0400409 } else if err == syscall.ECONNABORTED {
410 // This means that a socket on the listen queue was closed
411 // before we Accept()ed it; it's a silly error, so try again.
412 continue
Russ Coxc017a822011-11-13 22:44:52 -0500413 }
414 return nil, &OpError{"accept", fd.net, fd.laddr, err}
415 }
416 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700417 }
Russ Coxd8921c52009-02-15 14:18:39 -0800418
Mikio Hara28397be2012-02-01 00:36:45 +0900419 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
Mikio Hara6cf77f22012-08-23 20:54:00 +0900420 closesocket(s)
Robert Griesemera3d10452009-12-15 15:35:38 -0800421 return nil, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700422 }
Mikio Hara6a76bca362013-08-06 23:42:33 +0900423 if err = netfd.init(); err != nil {
424 fd.Close()
425 return nil, err
426 }
Mikio Harae4389c02012-09-19 01:33:03 +0900427 lsa, _ := syscall.Getsockname(netfd.sysfd)
Mikio Hara5c055e72014-08-05 06:10:46 +0900428 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
Mikio Hara28397be2012-02-01 00:36:45 +0900429 return netfd, nil
Russ Coxe4a61c62008-09-29 13:37:00 -0700430}
Keith Raricka144e3e2010-11-05 14:02:03 -0400431
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -0700432// tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
433// If the kernel doesn't support it, this is set to 0.
434var tryDupCloexec = int32(1)
435
436func dupCloseOnExec(fd int) (newfd int, err error) {
437 if atomic.LoadInt32(&tryDupCloexec) == 1 {
438 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
Brad Fitzpatrickb2fcdfa2013-08-06 07:18:06 -0700439 if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
440 // On OS X 10.6 and below (but we only support
441 // >= 10.6), F_DUPFD_CLOEXEC is unsupported
442 // and fcntl there falls back (undocumented)
443 // to doing an ioctl instead, returning EBADF
444 // in this case because fd is not of the
445 // expected device fd type. Treat it as
446 // EINVAL instead, so we fall back to the
447 // normal dup path.
448 // TODO: only do this on 10.6 if we can detect 10.6
449 // cheaply.
450 e1 = syscall.EINVAL
451 }
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -0700452 switch e1 {
453 case 0:
454 return int(r0), nil
455 case syscall.EINVAL:
456 // Old kernel. Fall back to the portable way
457 // from now on.
458 atomic.StoreInt32(&tryDupCloexec, 0)
459 default:
460 return -1, e1
461 }
462 }
463 return dupCloseOnExecOld(fd)
464}
465
466// dupCloseOnExecUnixOld is the traditional way to dup an fd and
467// set its O_CLOEXEC bit, using two system calls.
468func dupCloseOnExecOld(fd int) (newfd int, err error) {
Brad Fitzpatrick2d2866e2012-08-06 14:12:23 +1000469 syscall.ForkLock.RLock()
Brad Fitzpatrick37feacf2013-08-05 15:43:45 -0700470 defer syscall.ForkLock.RUnlock()
471 newfd, err = syscall.Dup(fd)
472 if err != nil {
473 return -1, err
474 }
475 syscall.CloseOnExec(newfd)
476 return
477}
478
479func (fd *netFD) dup() (f *os.File, err error) {
480 ns, err := dupCloseOnExec(fd.sysfd)
Russ Coxc017a822011-11-13 22:44:52 -0500481 if err != nil {
482 return nil, &OpError{"dup", fd.net, fd.laddr, err}
Keith Raricka144e3e2010-11-05 14:02:03 -0400483 }
484
485 // We want blocking mode for the new fd, hence the double negative.
Russ Cox18441e82013-02-07 22:45:12 -0500486 // This also puts the old fd into blocking mode, meaning that
487 // I/O will block the thread instead of letting us use the epoll server.
488 // Everything will still work, just with more threads.
Russ Coxc017a822011-11-13 22:44:52 -0500489 if err = syscall.SetNonblock(ns, false); err != nil {
490 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
Keith Raricka144e3e2010-11-05 14:02:03 -0400491 }
492
Dave Cheney067315c2012-10-26 19:41:21 +1100493 return os.NewFile(uintptr(ns), fd.name()), nil
Keith Raricka144e3e2010-11-05 14:02:03 -0400494}
Alex Brainman3a052b52011-01-12 15:55:17 +1100495
Russ Coxc017a822011-11-13 22:44:52 -0500496func closesocket(s int) error {
Alex Brainman3a052b52011-01-12 15:55:17 +1100497 return syscall.Close(s)
498}