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  }