github.com/cbeuw/gotfo@v0.0.0-20180331191851-f2b091af84de/fd_go19_unix.go (about) 1 // +build go1.9,!go1.10 2 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris 3 4 package gotfo 5 6 import "syscall" 7 import "net" 8 9 type pollFD struct { 10 // Lock sysfd and serialize access to Read and Write methods. 11 fdmu fdMutex 12 13 // System file descriptor. Immutable until Close. 14 sysfd int 15 16 // I/O poller. 17 pd pollDesc 18 19 // Writev cache. 20 iovecs *[]syscall.Iovec 21 22 // Whether this is a streaming descriptor, as opposed to a 23 // packet-based descriptor like a UDP socket. Immutable. 24 IsStream bool 25 26 // Whether a zero byte read indicates EOF. This is false for a 27 // message based socket connection. 28 ZeroReadIsEOF bool 29 30 // Whether this is a file rather than a network socket. 31 isFile bool 32 } 33 34 // Network file descriptor. 35 type netFD struct { 36 pollFD 37 38 // immutable until Close 39 family int 40 sotype int 41 isConnected bool 42 net string 43 laddr net.Addr 44 raddr net.Addr 45 } 46 47 func newFD(fd int) *netFD { 48 nfd := &netFD{ 49 pollFD: pollFD{ 50 sysfd: fd, 51 IsStream: true, 52 ZeroReadIsEOF: true, 53 }, 54 family: syscall.AF_INET, 55 sotype: syscall.SOCK_STREAM, 56 net: "tcp", 57 } 58 59 return nfd 60 } 61 62 func (fd *netFD) init() error { 63 return fd.pd.init(fd) 64 } 65 66 func (fd *pollFD) incref() error { 67 if !fd.fdmu.incref() { 68 return errClosing 69 } 70 return nil 71 } 72 73 // decref removes a reference from fd. 74 // It also closes fd when the state of fd is set to closed and there 75 // is no remaining reference. 76 func (fd *pollFD) decref() error { 77 if fd.fdmu.decref() { 78 return fd.destroy() 79 } 80 return nil 81 } 82 83 // Destroy closes the file descriptor. This is called when there are 84 // no remaining references. 85 func (fd *pollFD) destroy() error { 86 // Poller may want to unregister fd in readiness notification mechanism, 87 // so this must be executed before CloseFunc. 88 fd.pd.close() 89 err := syscall.Close(fd.sysfd) 90 fd.sysfd = -1 91 return err 92 } 93 94 // Shutdown wraps the shutdown network call. 95 func (fd *pollFD) Shutdown(how int) error { 96 if err := fd.incref(); err != nil { 97 return err 98 } 99 defer fd.decref() 100 return syscall.Shutdown(fd.sysfd, how) 101 }