...
Run Format

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

View as plain text