...
Run Format

Source file src/net/tcpsock.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	package net
     6	
     7	import (
     8		"context"
     9		"io"
    10		"os"
    11		"syscall"
    12		"time"
    13	)
    14	
    15	// BUG(mikio): On Windows, the File method of TCPListener is not
    16	// implemented.
    17	
    18	// TCPAddr represents the address of a TCP end point.
    19	type TCPAddr struct {
    20		IP   IP
    21		Port int
    22		Zone string // IPv6 scoped addressing zone
    23	}
    24	
    25	// Network returns the address's network name, "tcp".
    26	func (a *TCPAddr) Network() string { return "tcp" }
    27	
    28	func (a *TCPAddr) String() string {
    29		if a == nil {
    30			return "<nil>"
    31		}
    32		ip := ipEmptyString(a.IP)
    33		if a.Zone != "" {
    34			return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
    35		}
    36		return JoinHostPort(ip, itoa(a.Port))
    37	}
    38	
    39	func (a *TCPAddr) isWildcard() bool {
    40		if a == nil || a.IP == nil {
    41			return true
    42		}
    43		return a.IP.IsUnspecified()
    44	}
    45	
    46	func (a *TCPAddr) opAddr() Addr {
    47		if a == nil {
    48			return nil
    49		}
    50		return a
    51	}
    52	
    53	// ResolveTCPAddr parses addr as a TCP address of the form "host:port"
    54	// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
    55	// port name on the network net, which must be "tcp", "tcp4" or
    56	// "tcp6".  A literal address or host name for IPv6 must be enclosed
    57	// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
    58	// "[ipv6-host%zone]:80".
    59	//
    60	// Resolving a hostname is not recommended because this returns at most
    61	// one of its IP addresses.
    62	func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
    63		switch net {
    64		case "tcp", "tcp4", "tcp6":
    65		case "": // a hint wildcard for Go 1.0 undocumented behavior
    66			net = "tcp"
    67		default:
    68			return nil, UnknownNetworkError(net)
    69		}
    70		addrs, err := DefaultResolver.internetAddrList(context.Background(), net, addr)
    71		if err != nil {
    72			return nil, err
    73		}
    74		return addrs.first(isIPv4).(*TCPAddr), nil
    75	}
    76	
    77	// TCPConn is an implementation of the Conn interface for TCP network
    78	// connections.
    79	type TCPConn struct {
    80		conn
    81	}
    82	
    83	// ReadFrom implements the io.ReaderFrom ReadFrom method.
    84	func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
    85		if !c.ok() {
    86			return 0, syscall.EINVAL
    87		}
    88		n, err := c.readFrom(r)
    89		if err != nil && err != io.EOF {
    90			err = &OpError{Op: "readfrom", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    91		}
    92		return n, err
    93	}
    94	
    95	// CloseRead shuts down the reading side of the TCP connection.
    96	// Most callers should just use Close.
    97	func (c *TCPConn) CloseRead() error {
    98		if !c.ok() {
    99			return syscall.EINVAL
   100		}
   101		if err := c.fd.closeRead(); err != nil {
   102			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   103		}
   104		return nil
   105	}
   106	
   107	// CloseWrite shuts down the writing side of the TCP connection.
   108	// Most callers should just use Close.
   109	func (c *TCPConn) CloseWrite() error {
   110		if !c.ok() {
   111			return syscall.EINVAL
   112		}
   113		if err := c.fd.closeWrite(); err != nil {
   114			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   115		}
   116		return nil
   117	}
   118	
   119	// SetLinger sets the behavior of Close on a connection which still
   120	// has data waiting to be sent or to be acknowledged.
   121	//
   122	// If sec < 0 (the default), the operating system finishes sending the
   123	// data in the background.
   124	//
   125	// If sec == 0, the operating system discards any unsent or
   126	// unacknowledged data.
   127	//
   128	// If sec > 0, the data is sent in the background as with sec < 0. On
   129	// some operating systems after sec seconds have elapsed any remaining
   130	// unsent data may be discarded.
   131	func (c *TCPConn) SetLinger(sec int) error {
   132		if !c.ok() {
   133			return syscall.EINVAL
   134		}
   135		if err := setLinger(c.fd, sec); 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	// SetKeepAlive sets whether the operating system should send
   142	// keepalive messages on the connection.
   143	func (c *TCPConn) SetKeepAlive(keepalive bool) error {
   144		if !c.ok() {
   145			return syscall.EINVAL
   146		}
   147		if err := setKeepAlive(c.fd, keepalive); err != nil {
   148			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   149		}
   150		return nil
   151	}
   152	
   153	// SetKeepAlivePeriod sets period between keep alives.
   154	func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
   155		if !c.ok() {
   156			return syscall.EINVAL
   157		}
   158		if err := setKeepAlivePeriod(c.fd, d); err != nil {
   159			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   160		}
   161		return nil
   162	}
   163	
   164	// SetNoDelay controls whether the operating system should delay
   165	// packet transmission in hopes of sending fewer packets (Nagle's
   166	// algorithm).  The default is true (no delay), meaning that data is
   167	// sent as soon as possible after a Write.
   168	func (c *TCPConn) SetNoDelay(noDelay bool) error {
   169		if !c.ok() {
   170			return syscall.EINVAL
   171		}
   172		if err := setNoDelay(c.fd, noDelay); err != nil {
   173			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   174		}
   175		return nil
   176	}
   177	
   178	func newTCPConn(fd *netFD) *TCPConn {
   179		c := &TCPConn{conn{fd}}
   180		setNoDelay(c.fd, true)
   181		return c
   182	}
   183	
   184	// DialTCP connects to the remote address raddr on the network net,
   185	// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
   186	// used as the local address for the connection.
   187	func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
   188		switch net {
   189		case "tcp", "tcp4", "tcp6":
   190		default:
   191			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
   192		}
   193		if raddr == nil {
   194			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
   195		}
   196		c, err := dialTCP(context.Background(), net, laddr, raddr)
   197		if err != nil {
   198			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   199		}
   200		return c, nil
   201	}
   202	
   203	// TCPListener is a TCP network listener. Clients should typically
   204	// use variables of type Listener instead of assuming TCP.
   205	type TCPListener struct {
   206		fd *netFD
   207	}
   208	
   209	// AcceptTCP accepts the next incoming call and returns the new
   210	// connection.
   211	func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
   212		if !l.ok() {
   213			return nil, syscall.EINVAL
   214		}
   215		c, err := l.accept()
   216		if err != nil {
   217			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   218		}
   219		return c, nil
   220	}
   221	
   222	// Accept implements the Accept method in the Listener interface; it
   223	// waits for the next call and returns a generic Conn.
   224	func (l *TCPListener) Accept() (Conn, error) {
   225		if !l.ok() {
   226			return nil, syscall.EINVAL
   227		}
   228		c, err := l.accept()
   229		if err != nil {
   230			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   231		}
   232		return c, nil
   233	}
   234	
   235	// Close stops listening on the TCP address.
   236	// Already Accepted connections are not closed.
   237	func (l *TCPListener) Close() error {
   238		if !l.ok() {
   239			return syscall.EINVAL
   240		}
   241		if err := l.close(); err != nil {
   242			return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   243		}
   244		return nil
   245	}
   246	
   247	// Addr returns the listener's network address, a *TCPAddr.
   248	// The Addr returned is shared by all invocations of Addr, so
   249	// do not modify it.
   250	func (l *TCPListener) Addr() Addr { return l.fd.laddr }
   251	
   252	// SetDeadline sets the deadline associated with the listener.
   253	// A zero time value disables the deadline.
   254	func (l *TCPListener) SetDeadline(t time.Time) error {
   255		if !l.ok() {
   256			return syscall.EINVAL
   257		}
   258		if err := l.fd.setDeadline(t); err != nil {
   259			return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   260		}
   261		return nil
   262	}
   263	
   264	// File returns a copy of the underlying os.File, set to blocking
   265	// mode. It is the caller's responsibility to close f when finished.
   266	// Closing l does not affect f, and closing f does not affect l.
   267	//
   268	// The returned os.File's file descriptor is different from the
   269	// connection's. Attempting to change properties of the original
   270	// using this duplicate may or may not have the desired effect.
   271	func (l *TCPListener) File() (f *os.File, err error) {
   272		if !l.ok() {
   273			return nil, syscall.EINVAL
   274		}
   275		f, err = l.file()
   276		if err != nil {
   277			return nil, &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   278		}
   279		return
   280	}
   281	
   282	// ListenTCP announces on the TCP address laddr and returns a TCP
   283	// listener. Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
   284	// port of 0, ListenTCP will choose an available port. The caller can
   285	// use the Addr method of TCPListener to retrieve the chosen address.
   286	func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
   287		switch net {
   288		case "tcp", "tcp4", "tcp6":
   289		default:
   290			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
   291		}
   292		if laddr == nil {
   293			laddr = &TCPAddr{}
   294		}
   295		ln, err := listenTCP(context.Background(), net, laddr)
   296		if err != nil {
   297			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
   298		}
   299		return ln, nil
   300	}
   301	

View as plain text