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

View as plain text