blob: 334da7f22faea55dda5414639ac3681117213431 [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
Joel Sing9ca57a72011-12-21 21:44:47 +11005// +build darwin freebsd linux netbsd openbsd
Russ Cox27159562011-09-15 16:48:57 -04006
Russ Coxe4a61c62008-09-29 13:37:00 -07007package net
8
9import (
Russ Cox5e4e3d82012-02-14 00:40:37 -050010 "errors"
Russ Cox47a05332010-04-26 22:15:25 -070011 "io"
Robert Griesemera3d10452009-12-15 15:35:38 -080012 "os"
13 "sync"
14 "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 {
Devon H. O'Delleb163462009-12-01 23:28:57 -080020 // locking/lifetime of sysfd
Mikio Hara8c4fecd2012-02-14 14:57:57 +090021 sysmu sync.Mutex
22 sysref int
23
Russ Cox5e4e3d82012-02-14 00:40:37 -050024 // must lock both sysmu and pollserver to write
25 // can lock either to read
Robert Griesemera3d10452009-12-15 15:35:38 -080026 closing bool
Devon H. O'Delleb163462009-12-01 23:28:57 -080027
Russ Coxe4a61c62008-09-29 13:37:00 -070028 // immutable until Close
Mikio Hara974fa752012-01-27 01:31:42 +090029 sysfd int
30 family int
31 sotype int
32 isConnected bool
33 sysfile *os.File
Russ Cox5e4e3d82012-02-14 00:40:37 -050034 cr chan error
35 cw chan error
Mikio Hara974fa752012-01-27 01:31:42 +090036 net string
37 laddr Addr
38 raddr Addr
Russ Coxe4a61c62008-09-29 13:37:00 -070039
Russ Cox1e37e8a2009-03-06 17:51:31 -080040 // owned by client
Brad Fitzpatrickb71883e2012-01-18 16:24:06 -080041 rdeadline int64
42 rio sync.Mutex
43 wdeadline int64
44 wio sync.Mutex
Russ Cox1e37e8a2009-03-06 17:51:31 -080045
Russ Coxe4a61c62008-09-29 13:37:00 -070046 // owned by fd wait server
Robert Griesemera3d10452009-12-15 15:35:38 -080047 ncr, ncw int
Russ Coxe4a61c62008-09-29 13:37:00 -070048}
49
Russ Coxd8921c52009-02-15 14:18:39 -080050// A pollServer helps FDs determine when to retry a non-blocking
Russ Coxe4a61c62008-09-29 13:37:00 -070051// read or write after they get EAGAIN. When an FD needs to wait,
52// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
53// request to the poll server. Then receive on fd.cr/fd.cw.
Russ Coxd8921c52009-02-15 14:18:39 -080054// When the pollServer finds that i/o on FD should be possible
Russ Coxe4a61c62008-09-29 13:37:00 -070055// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
56// This protocol is implemented as s.WaitRead() and s.WaitWrite().
57//
58// There is one subtlety: when sending on s.cr/s.cw, the
59// poll server is probably in a system call, waiting for an fd
60// to become ready. It's not looking at the request channels.
61// To resolve this, the poll server waits not just on the FDs it has
62// been given but also its own pipe. After sending on the
63// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
Russ Coxd8921c52009-02-15 14:18:39 -080064// byte to the pipe, causing the pollServer's poll system call to
65// return. In response to the pipe being readable, the pollServer
Russ Coxe4a61c62008-09-29 13:37:00 -070066// re-polls its request channels.
67//
68// Note that the ordering is "send request" and then "wake up server".
69// If the operations were reversed, there would be a race: the poll
70// server might wake up and look at the request channel, see that it
71// was empty, and go back to sleep, all before the requester managed
72// to send the request. Because the send must complete before the wakeup,
73// the request channel must be buffered. A buffer of size 1 is sufficient
74// for any request load. If many processes are trying to submit requests,
Russ Coxd8921c52009-02-15 14:18:39 -080075// one will succeed, the pollServer will read the request, and then the
Russ Coxe4a61c62008-09-29 13:37:00 -070076// channel will be empty for the next process's request. A larger buffer
77// might help batch requests.
Adam Langleyef8f4832009-11-18 13:18:34 -080078//
Devon H. O'Delleb163462009-12-01 23:28:57 -080079// To avoid races in closing, all fd operations are locked and
80// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
81// and sets a closing flag. Only when the last reference is removed
82// will the fd be closed.
Russ Coxe4a61c62008-09-29 13:37:00 -070083
Russ Coxd8921c52009-02-15 14:18:39 -080084type pollServer struct {
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -070085 cr, cw chan *netFD // buffered >= 1
86 pr, pw *os.File
87 poll *pollster // low-level OS hooks
88 sync.Mutex // controls pending and deadline
89 pending map[int]*netFD
90 deadline int64 // next deadline (nsec since 1970)
Russ Coxe4a61c62008-09-29 13:37:00 -070091}
Russ Coxe4a61c62008-09-29 13:37:00 -070092
Russ Cox5e4e3d82012-02-14 00:40:37 -050093func (s *pollServer) AddFD(fd *netFD, mode int) error {
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -070094 s.Lock()
Russ Cox5e4e3d82012-02-14 00:40:37 -050095 intfd := fd.sysfd
96 if intfd < 0 || fd.closing {
97 // fd closed underfoot
98 s.Unlock()
99 return errClosing
100 }
Russ Coxe4a61c62008-09-29 13:37:00 -0700101
Robert Griesemera3d10452009-12-15 15:35:38 -0800102 var t int64
103 key := intfd << 1
Russ Coxe4a61c62008-09-29 13:37:00 -0700104 if mode == 'r' {
Robert Griesemera3d10452009-12-15 15:35:38 -0800105 fd.ncr++
106 t = fd.rdeadline
Russ Coxe4a61c62008-09-29 13:37:00 -0700107 } else {
Robert Griesemera3d10452009-12-15 15:35:38 -0800108 fd.ncw++
109 key++
110 t = fd.wdeadline
Russ Coxe4a61c62008-09-29 13:37:00 -0700111 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800112 s.pending[key] = fd
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700113 doWakeup := false
Russ Cox1e37e8a2009-03-06 17:51:31 -0800114 if t > 0 && (s.deadline == 0 || t < s.deadline) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800115 s.deadline = t
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700116 doWakeup = true
117 }
118
Ian Lance Taylor0caa0c02011-03-28 12:39:09 -0700119 wake, err := s.poll.AddFD(intfd, mode, false)
120 if err != nil {
Russ Coxeb692922011-11-01 22:05:34 -0400121 panic("pollServer AddFD " + err.Error())
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700122 }
Ian Lance Taylor0caa0c02011-03-28 12:39:09 -0700123 if wake {
124 doWakeup = true
125 }
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700126 s.Unlock()
127
128 if doWakeup {
129 s.Wakeup()
Russ Cox1e37e8a2009-03-06 17:51:31 -0800130 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500131 return nil
132}
133
134// Evict evicts fd from the pending list, unblocking
135// any I/O running on fd. The caller must have locked
136// pollserver.
137func (s *pollServer) Evict(fd *netFD) {
138 if s.pending[fd.sysfd<<1] == fd {
139 s.WakeFD(fd, 'r', errClosing)
140 s.poll.DelFD(fd.sysfd, 'r')
141 delete(s.pending, fd.sysfd<<1)
142 }
143 if s.pending[fd.sysfd<<1|1] == fd {
144 s.WakeFD(fd, 'w', errClosing)
145 s.poll.DelFD(fd.sysfd, 'w')
146 delete(s.pending, fd.sysfd<<1|1)
147 }
Russ Coxe4a61c62008-09-29 13:37:00 -0700148}
149
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700150var wakeupbuf [1]byte
151
152func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
153
Russ Cox9e0fec92009-06-01 22:14:39 -0700154func (s *pollServer) LookupFD(fd int, mode int) *netFD {
Robert Griesemera3d10452009-12-15 15:35:38 -0800155 key := fd << 1
Russ Coxe4a61c62008-09-29 13:37:00 -0700156 if mode == 'w' {
Robert Griesemer40621d52009-11-09 12:07:39 -0800157 key++
Russ Coxe4a61c62008-09-29 13:37:00 -0700158 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800159 netfd, ok := s.pending[key]
Russ Coxe4a61c62008-09-29 13:37:00 -0700160 if !ok {
Robert Griesemer40621d52009-11-09 12:07:39 -0800161 return nil
Russ Coxe4a61c62008-09-29 13:37:00 -0700162 }
Russ Cox313c8222011-10-18 09:56:34 -0400163 delete(s.pending, key)
Robert Griesemera3d10452009-12-15 15:35:38 -0800164 return netfd
Russ Coxe4a61c62008-09-29 13:37:00 -0700165}
166
Russ Cox5e4e3d82012-02-14 00:40:37 -0500167func (s *pollServer) WakeFD(fd *netFD, mode int, err error) {
Russ Cox1e37e8a2009-03-06 17:51:31 -0800168 if mode == 'r' {
169 for fd.ncr > 0 {
Robert Griesemera3d10452009-12-15 15:35:38 -0800170 fd.ncr--
Russ Cox5e4e3d82012-02-14 00:40:37 -0500171 fd.cr <- err
Russ Cox1e37e8a2009-03-06 17:51:31 -0800172 }
173 } else {
174 for fd.ncw > 0 {
Robert Griesemera3d10452009-12-15 15:35:38 -0800175 fd.ncw--
Russ Cox5e4e3d82012-02-14 00:40:37 -0500176 fd.cw <- err
Russ Cox1e37e8a2009-03-06 17:51:31 -0800177 }
178 }
179}
180
181func (s *pollServer) Now() int64 {
Russ Cox03823b82011-11-30 12:01:46 -0500182 return time.Now().UnixNano()
Russ Cox1e37e8a2009-03-06 17:51:31 -0800183}
184
185func (s *pollServer) CheckDeadlines() {
Robert Griesemera3d10452009-12-15 15:35:38 -0800186 now := s.Now()
Russ Cox1e37e8a2009-03-06 17:51:31 -0800187 // TODO(rsc): This will need to be handled more efficiently,
188 // probably with a heap indexed by wakeup time.
189
Robert Griesemera3d10452009-12-15 15:35:38 -0800190 var next_deadline int64
Russ Cox1e37e8a2009-03-06 17:51:31 -0800191 for key, fd := range s.pending {
Robert Griesemera3d10452009-12-15 15:35:38 -0800192 var t int64
193 var mode int
Russ Cox1e37e8a2009-03-06 17:51:31 -0800194 if key&1 == 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800195 mode = 'r'
Russ Cox1e37e8a2009-03-06 17:51:31 -0800196 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800197 mode = 'w'
Russ Cox1e37e8a2009-03-06 17:51:31 -0800198 }
199 if mode == 'r' {
Robert Griesemer40621d52009-11-09 12:07:39 -0800200 t = fd.rdeadline
Russ Cox1e37e8a2009-03-06 17:51:31 -0800201 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800202 t = fd.wdeadline
Russ Cox1e37e8a2009-03-06 17:51:31 -0800203 }
204 if t > 0 {
205 if t <= now {
Russ Cox313c8222011-10-18 09:56:34 -0400206 delete(s.pending, key)
Russ Cox1e37e8a2009-03-06 17:51:31 -0800207 if mode == 'r' {
Robert Griesemera3d10452009-12-15 15:35:38 -0800208 s.poll.DelFD(fd.sysfd, mode)
209 fd.rdeadline = -1
Russ Cox1e37e8a2009-03-06 17:51:31 -0800210 } else {
Robert Griesemera3d10452009-12-15 15:35:38 -0800211 s.poll.DelFD(fd.sysfd, mode)
212 fd.wdeadline = -1
Russ Cox1e37e8a2009-03-06 17:51:31 -0800213 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500214 s.WakeFD(fd, mode, nil)
Russ Cox1e37e8a2009-03-06 17:51:31 -0800215 } else if next_deadline == 0 || t < next_deadline {
Robert Griesemer40621d52009-11-09 12:07:39 -0800216 next_deadline = t
Russ Cox1e37e8a2009-03-06 17:51:31 -0800217 }
218 }
219 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800220 s.deadline = next_deadline
Russ Cox1e37e8a2009-03-06 17:51:31 -0800221}
222
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700223func (s *pollServer) Run() {
224 var scratch [100]byte
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700225 s.Lock()
226 defer s.Unlock()
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700227 for {
228 var t = s.deadline
229 if t > 0 {
230 t = t - s.Now()
231 if t <= 0 {
232 s.CheckDeadlines()
233 continue
234 }
235 }
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700236 fd, mode, err := s.poll.WaitFD(s, t)
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700237 if err != nil {
Russ Coxeb692922011-11-01 22:05:34 -0400238 print("pollServer WaitFD: ", err.Error(), "\n")
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700239 return
240 }
241 if fd < 0 {
242 // Timeout happened.
243 s.CheckDeadlines()
244 continue
245 }
Brad Fitzpatrick4152b432012-02-10 14:16:15 +1100246 if fd == int(s.pr.Fd()) {
Ian Lance Taylorc01238a2011-03-11 18:01:28 -0800247 // Drain our wakeup pipe (we could loop here,
248 // but it's unlikely that there are more than
249 // len(scratch) wakeup calls).
250 s.pr.Read(scratch[0:])
Ian Lance Taylor42bc7fc2011-03-17 13:42:40 -0700251 s.CheckDeadlines()
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700252 } else {
253 netfd := s.LookupFD(fd, mode)
254 if netfd == nil {
Vinu Rajashekhara9a24d42010-07-10 14:40:48 -0700255 print("pollServer: unexpected wakeup for fd=", fd, " mode=", string(mode), "\n")
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700256 continue
257 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500258 s.WakeFD(netfd, mode, nil)
Vinu Rajashekhar00ad47f2010-06-29 12:04:04 -0700259 }
260 }
261}
262
Russ Cox5e4e3d82012-02-14 00:40:37 -0500263func (s *pollServer) WaitRead(fd *netFD) error {
264 err := s.AddFD(fd, 'r')
265 if err == nil {
266 err = <-fd.cr
267 }
268 return err
Russ Coxe4a61c62008-09-29 13:37:00 -0700269}
270
Russ Cox5e4e3d82012-02-14 00:40:37 -0500271func (s *pollServer) WaitWrite(fd *netFD) error {
272 err := s.AddFD(fd, 'w')
273 if err == nil {
274 err = <-fd.cw
275 }
276 return err
Russ Coxe4a61c62008-09-29 13:37:00 -0700277}
278
Russ Coxe4a61c62008-09-29 13:37:00 -0700279// Network FD methods.
Russ Coxd8921c52009-02-15 14:18:39 -0800280// All the network FDs use a single pollServer.
Russ Coxe4a61c62008-09-29 13:37:00 -0700281
Russ Coxd8921c52009-02-15 14:18:39 -0800282var pollserver *pollServer
Rob Pikec78be462010-08-06 06:14:41 +1000283var onceStartServer sync.Once
Russ Coxe4a61c62008-09-29 13:37:00 -0700284
Russ Coxc83b8382009-11-02 18:37:30 -0800285func startServer() {
Robert Griesemera3d10452009-12-15 15:35:38 -0800286 p, err := newPollServer()
Russ Coxe4a61c62008-09-29 13:37:00 -0700287 if err != nil {
Russ Coxeb692922011-11-01 22:05:34 -0400288 print("Start pollServer: ", err.Error(), "\n")
Russ Coxe4a61c62008-09-29 13:37:00 -0700289 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800290 pollserver = p
Russ Coxe4a61c62008-09-29 13:37:00 -0700291}
292
Mikio Hara28397be2012-02-01 00:36:45 +0900293func newFD(fd, family, sotype int, net string) (*netFD, error) {
Rob Pikec78be462010-08-06 06:14:41 +1000294 onceStartServer.Do(startServer)
Mikio Hara28397be2012-02-01 00:36:45 +0900295 if err := syscall.SetNonblock(fd, true); err != nil {
296 return nil, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700297 }
Mikio Hara28397be2012-02-01 00:36:45 +0900298 netfd := &netFD{
Robert Griesemerf44fa9b2010-03-02 13:46:51 -0800299 sysfd: fd,
Russ Coxc83b8382009-11-02 18:37:30 -0800300 family: family,
Mikio Hara743c2d02012-01-20 07:31:13 +0900301 sotype: sotype,
Robert Griesemerf44fa9b2010-03-02 13:46:51 -0800302 net: net,
Robert Griesemera3d10452009-12-15 15:35:38 -0800303 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500304 netfd.cr = make(chan error, 1)
305 netfd.cw = make(chan error, 1)
Mikio Hara28397be2012-02-01 00:36:45 +0900306 return netfd, nil
Alexey Borzenkov2f45f722011-03-28 23:40:01 -0400307}
308
309func (fd *netFD) setAddr(laddr, raddr Addr) {
310 fd.laddr = laddr
311 fd.raddr = raddr
Robert Griesemera3d10452009-12-15 15:35:38 -0800312 var ls, rs string
Russ Coxc83b8382009-11-02 18:37:30 -0800313 if laddr != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800314 ls = laddr.String()
Russ Coxc83b8382009-11-02 18:37:30 -0800315 }
316 if raddr != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800317 rs = raddr.String()
Russ Coxc83b8382009-11-02 18:37:30 -0800318 }
Brad Fitzpatrick4152b432012-02-10 14:16:15 +1100319 fd.sysfile = os.NewFile(uintptr(fd.sysfd), fd.net+":"+ls+"->"+rs)
Alexey Borzenkov2f45f722011-03-28 23:40:01 -0400320}
321
Mikio Hara28397be2012-02-01 00:36:45 +0900322func (fd *netFD) connect(ra syscall.Sockaddr) error {
323 err := syscall.Connect(fd.sysfd, ra)
Russ Coxc017a822011-11-13 22:44:52 -0500324 if err == syscall.EINPROGRESS {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500325 if err = pollserver.WaitWrite(fd); err != nil {
326 return err
327 }
Russ Coxc017a822011-11-13 22:44:52 -0500328 var e int
329 e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
330 if err != nil {
331 return os.NewSyscallError("getsockopt", err)
332 }
333 if e != 0 {
334 err = syscall.Errno(e)
Alexey Borzenkov2f45f722011-03-28 23:40:01 -0400335 }
336 }
Russ Coxc017a822011-11-13 22:44:52 -0500337 return err
Russ Coxe4a61c62008-09-29 13:37:00 -0700338}
339
Russ Cox5e4e3d82012-02-14 00:40:37 -0500340var errClosing = errors.New("use of closed network connection")
341
Devon H. O'Delleb163462009-12-01 23:28:57 -0800342// Add a reference to this fd.
Russ Cox5e4e3d82012-02-14 00:40:37 -0500343// If closing==true, pollserver must be locked; mark the fd as closing.
344// Returns an error if the fd cannot be used.
345func (fd *netFD) incref(closing bool) error {
346 if fd == nil {
347 return errClosing
348 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800349 fd.sysmu.Lock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500350 if fd.closing {
351 fd.sysmu.Unlock()
352 return errClosing
353 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800354 fd.sysref++
Russ Cox5e4e3d82012-02-14 00:40:37 -0500355 if closing {
356 fd.closing = true
357 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800358 fd.sysmu.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500359 return nil
Devon H. O'Delleb163462009-12-01 23:28:57 -0800360}
361
362// Remove a reference to this FD and close if we've been asked to do so (and
363// there are no references left.
364func (fd *netFD) decref() {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500365 if fd == nil {
366 return
367 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800368 fd.sysmu.Lock()
369 fd.sysref--
Russ Cox5e4e3d82012-02-14 00:40:37 -0500370 if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
Robert Griesemera3d10452009-12-15 15:35:38 -0800371 fd.sysfile.Close()
372 fd.sysfile = nil
373 fd.sysfd = -1
Devon H. O'Delleb163462009-12-01 23:28:57 -0800374 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800375 fd.sysmu.Unlock()
Devon H. O'Delleb163462009-12-01 23:28:57 -0800376}
377
Russ Coxeb692922011-11-01 22:05:34 -0400378func (fd *netFD) Close() error {
Mikio Hara8c4fecd2012-02-14 14:57:57 +0900379 pollserver.Lock() // needed for both fd.incref(true) and pollserver.Evict
Russ Cox5e4e3d82012-02-14 00:40:37 -0500380 defer pollserver.Unlock()
381 if err := fd.incref(true); err != nil {
382 return err
Russ Coxe4a61c62008-09-29 13:37:00 -0700383 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500384 // Unblock any I/O. Once it all unblocks and returns,
385 // so that it cannot be referring to fd.sysfd anymore,
386 // the final decref will close fd.sysfd. This should happen
387 // fairly quickly, since all the I/O is non-blocking, and any
388 // attempts to block in the pollserver will return errClosing.
389 pollserver.Evict(fd)
Robert Griesemera3d10452009-12-15 15:35:38 -0800390 fd.decref()
391 return nil
Russ Coxe4a61c62008-09-29 13:37:00 -0700392}
393
Russ Coxeb692922011-11-01 22:05:34 -0400394func (fd *netFD) shutdown(how int) error {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500395 if err := fd.incref(false); err != nil {
396 return err
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700397 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500398 defer fd.decref()
Russ Coxc017a822011-11-13 22:44:52 -0500399 err := syscall.Shutdown(fd.sysfd, how)
400 if err != nil {
401 return &OpError{"shutdown", fd.net, fd.laddr, err}
Albert Strasheim791b2a42011-10-12 13:45:25 -0400402 }
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700403 return nil
404}
405
Russ Coxeb692922011-11-01 22:05:34 -0400406func (fd *netFD) CloseRead() error {
Albert Strasheim791b2a42011-10-12 13:45:25 -0400407 return fd.shutdown(syscall.SHUT_RD)
408}
409
Russ Coxeb692922011-11-01 22:05:34 -0400410func (fd *netFD) CloseWrite() error {
Albert Strasheim791b2a42011-10-12 13:45:25 -0400411 return fd.shutdown(syscall.SHUT_WR)
Brad Fitzpatrick394842e2011-09-28 08:12:38 -0700412}
413
Russ Coxeb692922011-11-01 22:05:34 -0400414func (fd *netFD) Read(p []byte) (n int, err error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800415 fd.rio.Lock()
416 defer fd.rio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500417 if err := fd.incref(false); err != nil {
418 return 0, err
Michael Hoisie9192ec22010-05-20 17:13:50 -0700419 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500420 defer fd.decref()
Russ Coxa0bcaf42009-06-25 20:24:55 -0700421 for {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500422 n, err = syscall.Read(int(fd.sysfd), p)
Russ Coxc017a822011-11-13 22:44:52 -0500423 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500424 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500425 if fd.rdeadline >= 0 {
426 if err = pollserver.WaitRead(fd); err == nil {
427 continue
428 }
429 }
Russ Coxa0bcaf42009-06-25 20:24:55 -0700430 }
Russ Coxc017a822011-11-13 22:44:52 -0500431 if err != nil {
Russ Cox47a05332010-04-26 22:15:25 -0700432 n = 0
Mikio Hara743c2d02012-01-20 07:31:13 +0900433 } else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM {
Russ Coxeb692922011-11-01 22:05:34 -0400434 err = io.EOF
Russ Cox47a05332010-04-26 22:15:25 -0700435 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800436 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700437 }
Russ Coxc017a822011-11-13 22:44:52 -0500438 if err != nil && err != io.EOF {
439 err = &OpError{"read", fd.net, fd.raddr, err}
Russ Coxe89441b2009-12-02 15:17:49 -0800440 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800441 return
Russ Coxe4a61c62008-09-29 13:37:00 -0700442}
443
Russ Coxeb692922011-11-01 22:05:34 -0400444func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800445 fd.rio.Lock()
446 defer fd.rio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500447 if err := fd.incref(false); err != nil {
448 return 0, nil, err
449 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800450 defer fd.decref()
Russ Cox6e788e02009-11-17 08:39:17 -0800451 for {
Russ Coxc017a822011-11-13 22:44:52 -0500452 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
453 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500454 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500455 if fd.rdeadline >= 0 {
456 if err = pollserver.WaitRead(fd); err == nil {
457 continue
458 }
459 }
Russ Cox6e788e02009-11-17 08:39:17 -0800460 }
Russ Coxc017a822011-11-13 22:44:52 -0500461 if err != nil {
Robert Griesemera3d10452009-12-15 15:35:38 -0800462 n = 0
Russ Cox6e788e02009-11-17 08:39:17 -0800463 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800464 break
Russ Cox6e788e02009-11-17 08:39:17 -0800465 }
Russ Cox5e4e3d82012-02-14 00:40:37 -0500466 if err != nil && err != io.EOF {
Russ Coxc017a822011-11-13 22:44:52 -0500467 err = &OpError{"read", fd.net, fd.laddr, err}
Russ Cox47a05332010-04-26 22:15:25 -0700468 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800469 return
Russ Cox6e788e02009-11-17 08:39:17 -0800470}
471
Russ Coxeb692922011-11-01 22:05:34 -0400472func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500473 fd.rio.Lock()
474 defer fd.rio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500475 if err := fd.incref(false); err != nil {
476 return 0, 0, 0, nil, err
477 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500478 defer fd.decref()
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500479 for {
Russ Coxc017a822011-11-13 22:44:52 -0500480 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
481 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500482 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500483 if fd.rdeadline >= 0 {
484 if err = pollserver.WaitRead(fd); err == nil {
485 continue
486 }
487 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500488 }
Russ Coxc017a822011-11-13 22:44:52 -0500489 if err == nil && n == 0 {
490 err = io.EOF
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500491 }
492 break
493 }
Russ Coxc017a822011-11-13 22:44:52 -0500494 if err != nil && err != io.EOF {
495 err = &OpError{"read", fd.net, fd.laddr, err}
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500496 return
497 }
498 return
499}
500
Mikio Hara28397be2012-02-01 00:36:45 +0900501func (fd *netFD) Write(p []byte) (int, error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800502 fd.wio.Lock()
503 defer fd.wio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500504 if err := fd.incref(false); err != nil {
505 return 0, err
506 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800507 defer fd.decref()
Michael Hoisie9192ec22010-05-20 17:13:50 -0700508 if fd.sysfile == nil {
Rob Pike56069f02012-02-17 10:04:29 +1100509 return 0, syscall.EINVAL
Michael Hoisie9192ec22010-05-20 17:13:50 -0700510 }
Michael Hoisie9192ec22010-05-20 17:13:50 -0700511
Mikio Hara28397be2012-02-01 00:36:45 +0900512 var err error
513 nn := 0
Russ Cox47a05332010-04-26 22:15:25 -0700514 for {
Russ Coxc017a822011-11-13 22:44:52 -0500515 var n int
Russ Cox5e4e3d82012-02-14 00:40:37 -0500516 n, err = syscall.Write(int(fd.sysfd), p[nn:])
Russ Coxe4a61c62008-09-29 13:37:00 -0700517 if n > 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800518 nn += n
Russ Coxe4a61c62008-09-29 13:37:00 -0700519 }
Russ Cox1e37e8a2009-03-06 17:51:31 -0800520 if nn == len(p) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800521 break
Russ Cox1e37e8a2009-03-06 17:51:31 -0800522 }
Russ Coxc017a822011-11-13 22:44:52 -0500523 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500524 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500525 if fd.wdeadline >= 0 {
526 if err = pollserver.WaitWrite(fd); err == nil {
527 continue
528 }
529 }
Russ Cox1e37e8a2009-03-06 17:51:31 -0800530 }
Russ Coxc017a822011-11-13 22:44:52 -0500531 if err != nil {
Russ Cox47a05332010-04-26 22:15:25 -0700532 n = 0
Robert Griesemer40621d52009-11-09 12:07:39 -0800533 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700534 }
Russ Cox47a05332010-04-26 22:15:25 -0700535 if n == 0 {
Russ Coxc017a822011-11-13 22:44:52 -0500536 err = io.ErrUnexpectedEOF
Russ Cox47a05332010-04-26 22:15:25 -0700537 break
538 }
539 }
Russ Coxc017a822011-11-13 22:44:52 -0500540 if err != nil {
541 err = &OpError{"write", fd.net, fd.raddr, err}
Russ Coxe4a61c62008-09-29 13:37:00 -0700542 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800543 return nn, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700544}
545
Russ Coxeb692922011-11-01 22:05:34 -0400546func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800547 fd.wio.Lock()
548 defer fd.wio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500549 if err := fd.incref(false); err != nil {
550 return 0, err
551 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800552 defer fd.decref()
Russ Cox6e788e02009-11-17 08:39:17 -0800553 for {
Russ Coxc017a822011-11-13 22:44:52 -0500554 err = syscall.Sendto(fd.sysfd, p, 0, sa)
555 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500556 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500557 if fd.wdeadline >= 0 {
558 if err = pollserver.WaitWrite(fd); err == nil {
559 continue
560 }
561 }
Russ Cox6e788e02009-11-17 08:39:17 -0800562 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800563 break
Russ Cox6e788e02009-11-17 08:39:17 -0800564 }
Russ Coxc017a822011-11-13 22:44:52 -0500565 if err == nil {
Russ Cox6e788e02009-11-17 08:39:17 -0800566 n = len(p)
Russ Cox47a05332010-04-26 22:15:25 -0700567 } else {
Russ Coxc017a822011-11-13 22:44:52 -0500568 err = &OpError{"write", fd.net, fd.raddr, err}
Russ Cox6e788e02009-11-17 08:39:17 -0800569 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800570 return
Russ Cox6e788e02009-11-17 08:39:17 -0800571}
572
Russ Coxeb692922011-11-01 22:05:34 -0400573func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500574 fd.wio.Lock()
575 defer fd.wio.Unlock()
Russ Cox5e4e3d82012-02-14 00:40:37 -0500576 if err := fd.incref(false); err != nil {
577 return 0, 0, err
578 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500579 defer fd.decref()
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500580 for {
Russ Coxc017a822011-11-13 22:44:52 -0500581 err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
582 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500583 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500584 if fd.wdeadline >= 0 {
585 if err = pollserver.WaitWrite(fd); err == nil {
586 continue
587 }
588 }
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500589 }
590 break
591 }
Russ Coxc017a822011-11-13 22:44:52 -0500592 if err == nil {
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500593 n = len(p)
594 oobn = len(oob)
595 } else {
Russ Coxc017a822011-11-13 22:44:52 -0500596 err = &OpError{"write", fd.net, fd.raddr, err}
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500597 }
598 return
599}
600
Mikio Hara28397be2012-02-01 00:36:45 +0900601func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
Russ Cox5e4e3d82012-02-14 00:40:37 -0500602 if err := fd.incref(false); err != nil {
603 return nil, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700604 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800605 defer fd.decref()
Devon H. O'Delleb163462009-12-01 23:28:57 -0800606
Russ Cox91ceda52009-02-15 19:35:52 -0800607 // See ../syscall/exec.go for description of ForkLock.
608 // It is okay to hold the lock across syscall.Accept
Devon H. O'Delleb163462009-12-01 23:28:57 -0800609 // because we have put fd.sysfd into non-blocking mode.
Russ Coxc017a822011-11-13 22:44:52 -0500610 var s int
Mikio Harac20ced92011-08-16 16:53:09 -0400611 var rsa syscall.Sockaddr
Russ Coxd8921c52009-02-15 14:18:39 -0800612 for {
Robert Griesemera3d10452009-12-15 15:35:38 -0800613 syscall.ForkLock.RLock()
Russ Coxc017a822011-11-13 22:44:52 -0500614 s, rsa, err = syscall.Accept(fd.sysfd)
615 if err != nil {
616 syscall.ForkLock.RUnlock()
617 if err == syscall.EAGAIN {
Russ Coxc017a822011-11-13 22:44:52 -0500618 err = errTimeout
Russ Cox5e4e3d82012-02-14 00:40:37 -0500619 if fd.rdeadline >= 0 {
620 if err = pollserver.WaitRead(fd); err == nil {
621 continue
622 }
623 }
Russ Coxc017a822011-11-13 22:44:52 -0500624 }
625 return nil, &OpError{"accept", fd.net, fd.laddr, err}
626 }
627 break
Russ Coxe4a61c62008-09-29 13:37:00 -0700628 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800629 syscall.CloseOnExec(s)
630 syscall.ForkLock.RUnlock()
Russ Coxd8921c52009-02-15 14:18:39 -0800631
Mikio Hara28397be2012-02-01 00:36:45 +0900632 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
Robert Griesemera3d10452009-12-15 15:35:38 -0800633 syscall.Close(s)
634 return nil, err
Russ Coxe4a61c62008-09-29 13:37:00 -0700635 }
Mikio Hara28397be2012-02-01 00:36:45 +0900636 lsa, _ := syscall.Getsockname(netfd.sysfd)
637 netfd.setAddr(toAddr(lsa), toAddr(rsa))
638 return netfd, nil
Russ Coxe4a61c62008-09-29 13:37:00 -0700639}
Keith Raricka144e3e2010-11-05 14:02:03 -0400640
Russ Coxeb692922011-11-01 22:05:34 -0400641func (fd *netFD) dup() (f *os.File, err error) {
Russ Coxc017a822011-11-13 22:44:52 -0500642 ns, err := syscall.Dup(fd.sysfd)
643 if err != nil {
644 return nil, &OpError{"dup", fd.net, fd.laddr, err}
Keith Raricka144e3e2010-11-05 14:02:03 -0400645 }
646
647 // We want blocking mode for the new fd, hence the double negative.
Russ Coxc017a822011-11-13 22:44:52 -0500648 if err = syscall.SetNonblock(ns, false); err != nil {
649 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
Keith Raricka144e3e2010-11-05 14:02:03 -0400650 }
651
Brad Fitzpatrick4152b432012-02-10 14:16:15 +1100652 return os.NewFile(uintptr(ns), fd.sysfile.Name()), nil
Keith Raricka144e3e2010-11-05 14:02:03 -0400653}
Alex Brainman3a052b52011-01-12 15:55:17 +1100654
Russ Coxc017a822011-11-13 22:44:52 -0500655func closesocket(s int) error {
Alex Brainman3a052b52011-01-12 15:55:17 +1100656 return syscall.Close(s)
657}