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 aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris 6 7package net 8 9import ( 10 "context" 11 "internal/poll" 12 "os" 13 "runtime" 14 "sync/atomic" 15 "syscall" 16) 17 18// Network file descriptor. 19type netFD struct { 20 pfd poll.FD 21 22 // immutable until Close 23 family int 24 sotype int 25 isConnected bool 26 net string 27 laddr Addr 28 raddr Addr 29} 30 31func newFD(sysfd, family, sotype int, net string) (*netFD, error) { 32 ret := &netFD{ 33 pfd: poll.FD{ 34 Sysfd: sysfd, 35 IsStream: sotype == syscall.SOCK_STREAM, 36 ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW, 37 }, 38 family: family, 39 sotype: sotype, 40 net: net, 41 } 42 return ret, nil 43} 44 45func (fd *netFD) init() error { 46 return fd.pfd.Init(fd.net, true) 47} 48 49func (fd *netFD) setAddr(laddr, raddr Addr) { 50 fd.laddr = laddr 51 fd.raddr = raddr 52 runtime.SetFinalizer(fd, (*netFD).Close) 53} 54 55func (fd *netFD) name() string { 56 var ls, rs string 57 if fd.laddr != nil { 58 ls = fd.laddr.String() 59 } 60 if fd.raddr != nil { 61 rs = fd.raddr.String() 62 } 63 return fd.net + ":" + ls + "->" + rs 64} 65 66func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa syscall.Sockaddr, ret error) { 67 // Do not need to call fd.writeLock here, 68 // because fd is not yet accessible to user, 69 // so no concurrent operations are possible. 70 switch err := connectFunc(fd.pfd.Sysfd, ra); err { 71 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 72 case nil, syscall.EISCONN: 73 select { 74 case <-ctx.Done(): 75 return nil, mapErr(ctx.Err()) 76 default: 77 } 78 if err := fd.pfd.Init(fd.net, true); err != nil { 79 return nil, err 80 } 81 runtime.KeepAlive(fd) 82 return nil, nil 83 case syscall.EINVAL: 84 // On Solaris we can see EINVAL if the socket has 85 // already been accepted and closed by the server. 86 // Treat this as a successful connection--writes to 87 // the socket will see EOF. For details and a test 88 // case in C see https://golang.org/issue/6828. 89 if runtime.GOOS == "solaris" { 90 return nil, nil 91 } 92 fallthrough 93 default: 94 return nil, os.NewSyscallError("connect", err) 95 } 96 if err := fd.pfd.Init(fd.net, true); err != nil { 97 return nil, err 98 } 99 if deadline, _ := ctx.Deadline(); !deadline.IsZero() { 100 fd.pfd.SetWriteDeadline(deadline) 101 defer fd.pfd.SetWriteDeadline(noDeadline) 102 } 103 104 // Start the "interrupter" goroutine, if this context might be canceled. 105 // (The background context cannot) 106 // 107 // The interrupter goroutine waits for the context to be done and 108 // interrupts the dial (by altering the fd's write deadline, which 109 // wakes up waitWrite). 110 if ctx != context.Background() { 111 // Wait for the interrupter goroutine to exit before returning 112 // from connect. 113 done := make(chan struct{}) 114 interruptRes := make(chan error) 115 defer func() { 116 close(done) 117 if ctxErr := <-interruptRes; ctxErr != nil && ret == nil { 118 // The interrupter goroutine called SetWriteDeadline, 119 // but the connect code below had returned from 120 // waitWrite already and did a successful connect (ret 121 // == nil). Because we've now poisoned the connection 122 // by making it unwritable, don't return a successful 123 // dial. This was issue 16523. 124 ret = ctxErr 125 fd.Close() // prevent a leak 126 } 127 }() 128 go func() { 129 select { 130 case <-ctx.Done(): 131 // Force the runtime's poller to immediately give up 132 // waiting for writability, unblocking waitWrite 133 // below. 134 fd.pfd.SetWriteDeadline(aLongTimeAgo) 135 testHookCanceledDial() 136 interruptRes <- ctx.Err() 137 case <-done: 138 interruptRes <- nil 139 } 140 }() 141 } 142 143 for { 144 // Performing multiple connect system calls on a 145 // non-blocking socket under Unix variants does not 146 // necessarily result in earlier errors being 147 // returned. Instead, once runtime-integrated network 148 // poller tells us that the socket is ready, get the 149 // SO_ERROR socket option to see if the connection 150 // succeeded or failed. See issue 7474 for further 151 // details. 152 if err := fd.pfd.WaitWrite(); err != nil { 153 select { 154 case <-ctx.Done(): 155 return nil, mapErr(ctx.Err()) 156 default: 157 } 158 return nil, err 159 } 160 nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) 161 if err != nil { 162 return nil, os.NewSyscallError("getsockopt", err) 163 } 164 switch err := syscall.Errno(nerr); err { 165 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 166 case syscall.EISCONN: 167 return nil, nil 168 case syscall.Errno(0): 169 // The runtime poller can wake us up spuriously; 170 // see issues 14548 and 19289. Check that we are 171 // really connected; if not, wait again. 172 if rsa, err := syscall.Getpeername(fd.pfd.Sysfd); err == nil { 173 return rsa, nil 174 } 175 default: 176 return nil, os.NewSyscallError("connect", err) 177 } 178 runtime.KeepAlive(fd) 179 } 180} 181 182func (fd *netFD) Close() error { 183 runtime.SetFinalizer(fd, nil) 184 return fd.pfd.Close() 185} 186 187func (fd *netFD) shutdown(how int) error { 188 err := fd.pfd.Shutdown(how) 189 runtime.KeepAlive(fd) 190 return wrapSyscallError("shutdown", err) 191} 192 193func (fd *netFD) closeRead() error { 194 return fd.shutdown(syscall.SHUT_RD) 195} 196 197func (fd *netFD) closeWrite() error { 198 return fd.shutdown(syscall.SHUT_WR) 199} 200 201func (fd *netFD) Read(p []byte) (n int, err error) { 202 n, err = fd.pfd.Read(p) 203 runtime.KeepAlive(fd) 204 return n, wrapSyscallError("read", err) 205} 206 207func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 208 n, sa, err = fd.pfd.ReadFrom(p) 209 runtime.KeepAlive(fd) 210 return n, sa, wrapSyscallError("recvfrom", err) 211} 212 213func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 214 n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob) 215 runtime.KeepAlive(fd) 216 return n, oobn, flags, sa, wrapSyscallError("recvmsg", err) 217} 218 219func (fd *netFD) Write(p []byte) (nn int, err error) { 220 nn, err = fd.pfd.Write(p) 221 runtime.KeepAlive(fd) 222 return nn, wrapSyscallError("write", err) 223} 224 225func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 226 n, err = fd.pfd.WriteTo(p, sa) 227 runtime.KeepAlive(fd) 228 return n, wrapSyscallError("sendto", err) 229} 230 231func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 232 n, oobn, err = fd.pfd.WriteMsg(p, oob, sa) 233 runtime.KeepAlive(fd) 234 return n, oobn, wrapSyscallError("sendmsg", err) 235} 236 237func (fd *netFD) accept() (netfd *netFD, err error) { 238 d, rsa, errcall, err := fd.pfd.Accept() 239 if err != nil { 240 if errcall != "" { 241 err = wrapSyscallError(errcall, err) 242 } 243 return nil, err 244 } 245 246 if netfd, err = newFD(d, fd.family, fd.sotype, fd.net); err != nil { 247 poll.CloseFunc(d) 248 return nil, err 249 } 250 if err = netfd.init(); err != nil { 251 fd.Close() 252 return nil, err 253 } 254 lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd) 255 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 256 return netfd, nil 257} 258 259// Use a helper function to call fcntl. This is defined in C in 260// libgo/runtime. 261//extern __go_fcntl_uintptr 262func fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr) 263 264// tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 265// If the kernel doesn't support it, this is set to 0. 266var tryDupCloexec = int32(1) 267 268func dupCloseOnExec(fd int) (newfd int, err error) { 269 if atomic.LoadInt32(&tryDupCloexec) == 1 && syscall.F_DUPFD_CLOEXEC != 0 { 270 syscall.Entersyscall() 271 r0, errno := fcntl(uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 272 syscall.Exitsyscall() 273 e1 := syscall.Errno(errno) 274 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 275 // On OS X 10.6 and below (but we only support 276 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 277 // and fcntl there falls back (undocumented) 278 // to doing an ioctl instead, returning EBADF 279 // in this case because fd is not of the 280 // expected device fd type. Treat it as 281 // EINVAL instead, so we fall back to the 282 // normal dup path. 283 // TODO: only do this on 10.6 if we can detect 10.6 284 // cheaply. 285 e1 = syscall.EINVAL 286 } 287 switch e1 { 288 case 0: 289 return int(r0), nil 290 case syscall.EINVAL: 291 // Old kernel. Fall back to the portable way 292 // from now on. 293 atomic.StoreInt32(&tryDupCloexec, 0) 294 default: 295 return -1, os.NewSyscallError("fcntl", e1) 296 } 297 } 298 return dupCloseOnExecOld(fd) 299} 300 301// dupCloseOnExecUnixOld is the traditional way to dup an fd and 302// set its O_CLOEXEC bit, using two system calls. 303func dupCloseOnExecOld(fd int) (newfd int, err error) { 304 syscall.ForkLock.RLock() 305 defer syscall.ForkLock.RUnlock() 306 newfd, err = syscall.Dup(fd) 307 if err != nil { 308 return -1, os.NewSyscallError("dup", err) 309 } 310 syscall.CloseOnExec(newfd) 311 return 312} 313 314func (fd *netFD) dup() (f *os.File, err error) { 315 ns, err := dupCloseOnExec(fd.pfd.Sysfd) 316 if err != nil { 317 return nil, err 318 } 319 320 // We want blocking mode for the new fd, hence the double negative. 321 // This also puts the old fd into blocking mode, meaning that 322 // I/O will block the thread instead of letting us use the epoll server. 323 // Everything will still work, just with more threads. 324 if err = fd.pfd.SetBlocking(); err != nil { 325 return nil, os.NewSyscallError("setnonblock", err) 326 } 327 328 return os.NewFile(uintptr(ns), fd.name()), nil 329} 330