github.com/cbeuw/gotfo@v0.0.0-20180331191851-f2b091af84de/util.go (about)

     1  package gotfo
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  	"syscall"
     8  	"time"
     9  	"unsafe"
    10  )
    11  
    12  var (
    13  	errTimeout   = errors.New("operation timed out")
    14  	errCanceled  = errors.New("operation was canceled")
    15  	errClosing   = errors.New("use of closed network connection")
    16  	aLongTimeAgo = time.Unix(1, 0)
    17  	noDeadline   = time.Time{}
    18  )
    19  
    20  type conn struct {
    21  	fd *netFD
    22  }
    23  
    24  type TCPConn struct {
    25  	conn
    26  }
    27  
    28  type TCPListener struct {
    29  	fd *netFD
    30  }
    31  
    32  // ipv4 only
    33  func sockaddrToTCPAddr(sa syscall.Sockaddr) net.Addr {
    34  	addr := sa.(*syscall.SockaddrInet4)
    35  	return &net.TCPAddr{IP: addr.Addr[0:], Port: addr.Port}
    36  }
    37  
    38  // ipv4 only
    39  func tcpAddrToSockaddr(addr *net.TCPAddr) syscall.Sockaddr {
    40  	sa := &syscall.SockaddrInet4{Port: addr.Port}
    41  	copy(sa.Addr[:], addr.IP.To4())
    42  	return sa
    43  }
    44  
    45  func mapErr(err error) error {
    46  	switch err {
    47  	case context.Canceled:
    48  		return errCanceled
    49  	case context.DeadlineExceeded:
    50  		return errTimeout
    51  	default:
    52  		return err
    53  	}
    54  }
    55  
    56  func newTCPConn(fd *netFD) *net.TCPConn {
    57  	dummyConn := &TCPConn{}
    58  	dummyConn.conn.fd = fd
    59  
    60  	if fd.incref() == nil {
    61  		syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1)
    62  		fd.decref()
    63  	}
    64  
    65  	conn := (*net.TCPConn)(unsafe.Pointer(dummyConn))
    66  
    67  	return conn
    68  }
    69  
    70  func newTCPListener(fd *netFD, returnWrapper bool) net.Listener {
    71  	dummyListener := &TCPListener{}
    72  	dummyListener.fd = fd
    73  
    74  	listener := (*net.TCPListener)(unsafe.Pointer(dummyListener))
    75  
    76  	if returnWrapper {
    77  		return &TFOListener{listener, fd}
    78  	}
    79  
    80  	return listener
    81  }