Run Format

Source file src/pkg/net/tcpsock_posix.go

     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 darwin dragonfly freebsd linux netbsd openbsd windows
     6	
     7	package net
     8	
     9	import (
    10		"io"
    11		"os"
    12		"syscall"
    13		"time"
    14	)
    15	
    16	// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
    17	// both IPv4 and IPv6 connections. This is due to the fact that IPv4 traffic
    18	// will not be routed to an IPv6 socket - two separate sockets are required
    19	// if both AFs are to be supported. See inet6(4) on OpenBSD for details.
    20	
    21	func sockaddrToTCP(sa syscall.Sockaddr) Addr {
    22		switch sa := sa.(type) {
    23		case *syscall.SockaddrInet4:
    24			return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
    25		case *syscall.SockaddrInet6:
    26			return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
    27		}
    28		return nil
    29	}
    30	
    31	func (a *TCPAddr) family() int {
    32		if a == nil || len(a.IP) <= IPv4len {
    33			return syscall.AF_INET
    34		}
    35		if a.IP.To4() != nil {
    36			return syscall.AF_INET
    37		}
    38		return syscall.AF_INET6
    39	}
    40	
    41	func (a *TCPAddr) isWildcard() bool {
    42		if a == nil || a.IP == nil {
    43			return true
    44		}
    45		return a.IP.IsUnspecified()
    46	}
    47	
    48	func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
    49		if a == nil {
    50			return nil, nil
    51		}
    52		return ipToSockaddr(family, a.IP, a.Port, a.Zone)
    53	}
    54	
    55	// TCPConn is an implementation of the Conn interface for TCP network
    56	// connections.
    57	type TCPConn struct {
    58		conn
    59	}
    60	
    61	func newTCPConn(fd *netFD) *TCPConn {
    62		c := &TCPConn{conn{fd}}
    63		c.SetNoDelay(true)
    64		return c
    65	}
    66	
    67	// ReadFrom implements the io.ReaderFrom ReadFrom method.
    68	func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
    69		if n, err, handled := sendFile(c.fd, r); handled {
    70			return n, err
    71		}
    72		return genericReadFrom(c, r)
    73	}
    74	
    75	// CloseRead shuts down the reading side of the TCP connection.
    76	// Most callers should just use Close.
    77	func (c *TCPConn) CloseRead() error {
    78		if !c.ok() {
    79			return syscall.EINVAL
    80		}
    81		return c.fd.CloseRead()
    82	}
    83	
    84	// CloseWrite shuts down the writing side of the TCP connection.
    85	// Most callers should just use Close.
    86	func (c *TCPConn) CloseWrite() error {
    87		if !c.ok() {
    88			return syscall.EINVAL
    89		}
    90		return c.fd.CloseWrite()
    91	}
    92	
    93	// SetLinger sets the behavior of Close() on a connection which still
    94	// has data waiting to be sent or to be acknowledged.
    95	//
    96	// If sec < 0 (the default), Close returns immediately and the
    97	// operating system finishes sending the data in the background.
    98	//
    99	// If sec == 0, Close returns immediately and the operating system
   100	// discards any unsent or unacknowledged data.
   101	//
   102	// If sec > 0, Close blocks for at most sec seconds waiting for data
   103	// to be sent and acknowledged.
   104	func (c *TCPConn) SetLinger(sec int) error {
   105		if !c.ok() {
   106			return syscall.EINVAL
   107		}
   108		return setLinger(c.fd, sec)
   109	}
   110	
   111	// SetKeepAlive sets whether the operating system should send
   112	// keepalive messages on the connection.
   113	func (c *TCPConn) SetKeepAlive(keepalive bool) error {
   114		if !c.ok() {
   115			return syscall.EINVAL
   116		}
   117		return setKeepAlive(c.fd, keepalive)
   118	}
   119	
   120	// SetKeepAlivePeriod sets period between keep alives.
   121	func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
   122		if !c.ok() {
   123			return syscall.EINVAL
   124		}
   125		return setKeepAlivePeriod(c.fd, d)
   126	}
   127	
   128	// SetNoDelay controls whether the operating system should delay
   129	// packet transmission in hopes of sending fewer packets (Nagle's
   130	// algorithm).  The default is true (no delay), meaning that data is
   131	// sent as soon as possible after a Write.
   132	func (c *TCPConn) SetNoDelay(noDelay bool) error {
   133		if !c.ok() {
   134			return syscall.EINVAL
   135		}
   136		return setNoDelay(c.fd, noDelay)
   137	}
   138	
   139	// DialTCP connects to the remote address raddr on the network net,
   140	// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
   141	// used as the local address for the connection.
   142	func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
   143		switch net {
   144		case "tcp", "tcp4", "tcp6":
   145		default:
   146			return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
   147		}
   148		if raddr == nil {
   149			return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
   150		}
   151		return dialTCP(net, laddr, raddr, noDeadline)
   152	}
   153	
   154	func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
   155		fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
   156	
   157		// TCP has a rarely used mechanism called a 'simultaneous connection' in
   158		// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
   159		// connect to a simultaneous Dial("tcp", addr2, addr1) run on the machine
   160		// at addr2, without either machine executing Listen.  If laddr == nil,
   161		// it means we want the kernel to pick an appropriate originating local
   162		// address.  Some Linux kernels cycle blindly through a fixed range of
   163		// local ports, regardless of destination port.  If a kernel happens to
   164		// pick local port 50001 as the source for a Dial("tcp", "", "localhost:50001"),
   165		// then the Dial will succeed, having simultaneously connected to itself.
   166		// This can only happen when we are letting the kernel pick a port (laddr == nil)
   167		// and when there is no listener for the destination address.
   168		// It's hard to argue this is anything other than a kernel bug.  If we
   169		// see this happen, rather than expose the buggy effect to users, we
   170		// close the fd and try again.  If it happens twice more, we relent and
   171		// use the result.  See also:
   172		//	http://golang.org/issue/2690
   173		//	http://stackoverflow.com/questions/4949858/
   174		//
   175		// The opposite can also happen: if we ask the kernel to pick an appropriate
   176		// originating local address, sometimes it picks one that is already in use.
   177		// So if the error is EADDRNOTAVAIL, we have to try again too, just for
   178		// a different reason.
   179		//
   180		// The kernel socket code is no doubt enjoying watching us squirm.
   181		for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
   182			if err == nil {
   183				fd.Close()
   184			}
   185			fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
   186		}
   187	
   188		if err != nil {
   189			return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
   190		}
   191		return newTCPConn(fd), nil
   192	}
   193	
   194	func selfConnect(fd *netFD, err error) bool {
   195		// If the connect failed, we clearly didn't connect to ourselves.
   196		if err != nil {
   197			return false
   198		}
   199	
   200		// The socket constructor can return an fd with raddr nil under certain
   201		// unknown conditions. The errors in the calls there to Getpeername
   202		// are discarded, but we can't catch the problem there because those
   203		// calls are sometimes legally erroneous with a "socket not connected".
   204		// Since this code (selfConnect) is already trying to work around
   205		// a problem, we make sure if this happens we recognize trouble and
   206		// ask the DialTCP routine to try again.
   207		// TODO: try to understand what's really going on.
   208		if fd.laddr == nil || fd.raddr == nil {
   209			return true
   210		}
   211		l := fd.laddr.(*TCPAddr)
   212		r := fd.raddr.(*TCPAddr)
   213		return l.Port == r.Port && l.IP.Equal(r.IP)
   214	}
   215	
   216	func spuriousENOTAVAIL(err error) bool {
   217		e, ok := err.(*OpError)
   218		return ok && e.Err == syscall.EADDRNOTAVAIL
   219	}
   220	
   221	// TCPListener is a TCP network listener.  Clients should typically
   222	// use variables of type Listener instead of assuming TCP.
   223	type TCPListener struct {
   224		fd *netFD
   225	}
   226	
   227	// AcceptTCP accepts the next incoming call and returns the new
   228	// connection.
   229	func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
   230		if l == nil || l.fd == nil {
   231			return nil, syscall.EINVAL
   232		}
   233		fd, err := l.fd.accept(sockaddrToTCP)
   234		if err != nil {
   235			return nil, err
   236		}
   237		return newTCPConn(fd), nil
   238	}
   239	
   240	// Accept implements the Accept method in the Listener interface; it
   241	// waits for the next call and returns a generic Conn.
   242	func (l *TCPListener) Accept() (Conn, error) {
   243		c, err := l.AcceptTCP()
   244		if err != nil {
   245			return nil, err
   246		}
   247		return c, nil
   248	}
   249	
   250	// Close stops listening on the TCP address.
   251	// Already Accepted connections are not closed.
   252	func (l *TCPListener) Close() error {
   253		if l == nil || l.fd == nil {
   254			return syscall.EINVAL
   255		}
   256		return l.fd.Close()
   257	}
   258	
   259	// Addr returns the listener's network address, a *TCPAddr.
   260	func (l *TCPListener) Addr() Addr { return l.fd.laddr }
   261	
   262	// SetDeadline sets the deadline associated with the listener.
   263	// A zero time value disables the deadline.
   264	func (l *TCPListener) SetDeadline(t time.Time) error {
   265		if l == nil || l.fd == nil {
   266			return syscall.EINVAL
   267		}
   268		return l.fd.setDeadline(t)
   269	}
   270	
   271	// File returns a copy of the underlying os.File, set to blocking
   272	// mode.  It is the caller's responsibility to close f when finished.
   273	// Closing l does not affect f, and closing f does not affect l.
   274	//
   275	// The returned os.File's file descriptor is different from the
   276	// connection's.  Attempting to change properties of the original
   277	// using this duplicate may or may not have the desired effect.
   278	func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
   279	
   280	// ListenTCP announces on the TCP address laddr and returns a TCP
   281	// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
   282	// port of 0, ListenTCP will choose an available port.  The caller can
   283	// use the Addr method of TCPListener to retrieve the chosen address.
   284	func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
   285		switch net {
   286		case "tcp", "tcp4", "tcp6":
   287		default:
   288			return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
   289		}
   290		if laddr == nil {
   291			laddr = &TCPAddr{}
   292		}
   293		fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
   294		if err != nil {
   295			return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
   296		}
   297		return &TCPListener{fd}, nil
   298	}

View as plain text