...

Source file src/pkg/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 JS, NaCl and Windows, the File method of TCPConn and
    16	// TCPListener is not 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 returns an address of TCP end point.
    54	//
    55	// The network must be a TCP network name.
    56	//
    57	// If the host in the address parameter is not a literal IP address or
    58	// the port is not a literal port number, ResolveTCPAddr resolves the
    59	// address to an address of TCP end point.
    60	// Otherwise, it parses the address as a pair of literal IP address
    61	// and port number.
    62	// The address parameter can use a host name, but this is not
    63	// recommended, because it will return at most one of the host name's
    64	// IP addresses.
    65	//
    66	// See func Dial for a description of the network and address
    67	// parameters.
    68	func ResolveTCPAddr(network, address string) (*TCPAddr, error) {
    69		switch network {
    70		case "tcp", "tcp4", "tcp6":
    71		case "": // a hint wildcard for Go 1.0 undocumented behavior
    72			network = "tcp"
    73		default:
    74			return nil, UnknownNetworkError(network)
    75		}
    76		addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address)
    77		if err != nil {
    78			return nil, err
    79		}
    80		return addrs.forResolve(network, address).(*TCPAddr), nil
    81	}
    82	
    83	// TCPConn is an implementation of the Conn interface for TCP network
    84	// connections.
    85	type TCPConn struct {
    86		conn
    87	}
    88	
    89	// SyscallConn returns a raw network connection.
    90	// This implements the syscall.Conn interface.
    91	func (c *TCPConn) SyscallConn() (syscall.RawConn, error) {
    92		if !c.ok() {
    93			return nil, syscall.EINVAL
    94		}
    95		return newRawConn(c.fd)
    96	}
    97	
    98	// ReadFrom implements the io.ReaderFrom ReadFrom method.
    99	func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
   100		if !c.ok() {
   101			return 0, syscall.EINVAL
   102		}
   103		n, err := c.readFrom(r)
   104		if err != nil && err != io.EOF {
   105			err = &OpError{Op: "readfrom", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   106		}
   107		return n, err
   108	}
   109	
   110	// CloseRead shuts down the reading side of the TCP connection.
   111	// Most callers should just use Close.
   112	func (c *TCPConn) CloseRead() error {
   113		if !c.ok() {
   114			return syscall.EINVAL
   115		}
   116		if err := c.fd.closeRead(); err != nil {
   117			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   118		}
   119		return nil
   120	}
   121	
   122	// CloseWrite shuts down the writing side of the TCP connection.
   123	// Most callers should just use Close.
   124	func (c *TCPConn) CloseWrite() error {
   125		if !c.ok() {
   126			return syscall.EINVAL
   127		}
   128		if err := c.fd.closeWrite(); err != nil {
   129			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   130		}
   131		return nil
   132	}
   133	
   134	// SetLinger sets the behavior of Close on a connection which still
   135	// has data waiting to be sent or to be acknowledged.
   136	//
   137	// If sec < 0 (the default), the operating system finishes sending the
   138	// data in the background.
   139	//
   140	// If sec == 0, the operating system discards any unsent or
   141	// unacknowledged data.
   142	//
   143	// If sec > 0, the data is sent in the background as with sec < 0. On
   144	// some operating systems after sec seconds have elapsed any remaining
   145	// unsent data may be discarded.
   146	func (c *TCPConn) SetLinger(sec int) error {
   147		if !c.ok() {
   148			return syscall.EINVAL
   149		}
   150		if err := setLinger(c.fd, sec); err != nil {
   151			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   152		}
   153		return nil
   154	}
   155	
   156	// SetKeepAlive sets whether the operating system should send
   157	// keep-alive messages on the connection.
   158	func (c *TCPConn) SetKeepAlive(keepalive bool) error {
   159		if !c.ok() {
   160			return syscall.EINVAL
   161		}
   162		if err := setKeepAlive(c.fd, keepalive); err != nil {
   163			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   164		}
   165		return nil
   166	}
   167	
   168	// SetKeepAlivePeriod sets period between keep-alives.
   169	func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
   170		if !c.ok() {
   171			return syscall.EINVAL
   172		}
   173		if err := setKeepAlivePeriod(c.fd, d); err != nil {
   174			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   175		}
   176		return nil
   177	}
   178	
   179	// SetNoDelay controls whether the operating system should delay
   180	// packet transmission in hopes of sending fewer packets (Nagle's
   181	// algorithm).  The default is true (no delay), meaning that data is
   182	// sent as soon as possible after a Write.
   183	func (c *TCPConn) SetNoDelay(noDelay bool) error {
   184		if !c.ok() {
   185			return syscall.EINVAL
   186		}
   187		if err := setNoDelay(c.fd, noDelay); err != nil {
   188			return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   189		}
   190		return nil
   191	}
   192	
   193	func newTCPConn(fd *netFD) *TCPConn {
   194		c := &TCPConn{conn{fd}}
   195		setNoDelay(c.fd, true)
   196		return c
   197	}
   198	
   199	// DialTCP acts like Dial for TCP networks.
   200	//
   201	// The network must be a TCP network name; see func Dial for details.
   202	//
   203	// If laddr is nil, a local address is automatically chosen.
   204	// If the IP field of raddr is nil or an unspecified IP address, the
   205	// local system is assumed.
   206	func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
   207		switch network {
   208		case "tcp", "tcp4", "tcp6":
   209		default:
   210			return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
   211		}
   212		if raddr == nil {
   213			return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
   214		}
   215		sd := &sysDialer{network: network, address: raddr.String()}
   216		c, err := sd.dialTCP(context.Background(), laddr, raddr)
   217		if err != nil {
   218			return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   219		}
   220		return c, nil
   221	}
   222	
   223	// TCPListener is a TCP network listener. Clients should typically
   224	// use variables of type Listener instead of assuming TCP.
   225	type TCPListener struct {
   226		fd *netFD
   227		lc ListenConfig
   228	}
   229	
   230	// SyscallConn returns a raw network connection.
   231	// This implements the syscall.Conn interface.
   232	//
   233	// The returned RawConn only supports calling Control. Read and
   234	// Write return an error.
   235	func (l *TCPListener) SyscallConn() (syscall.RawConn, error) {
   236		if !l.ok() {
   237			return nil, syscall.EINVAL
   238		}
   239		return newRawListener(l.fd)
   240	}
   241	
   242	// AcceptTCP accepts the next incoming call and returns the new
   243	// connection.
   244	func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
   245		if !l.ok() {
   246			return nil, syscall.EINVAL
   247		}
   248		c, err := l.accept()
   249		if err != nil {
   250			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   251		}
   252		return c, nil
   253	}
   254	
   255	// Accept implements the Accept method in the Listener interface; it
   256	// waits for the next call and returns a generic Conn.
   257	func (l *TCPListener) Accept() (Conn, error) {
   258		if !l.ok() {
   259			return nil, syscall.EINVAL
   260		}
   261		c, err := l.accept()
   262		if err != nil {
   263			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   264		}
   265		return c, nil
   266	}
   267	
   268	// Close stops listening on the TCP address.
   269	// Already Accepted connections are not closed.
   270	func (l *TCPListener) Close() error {
   271		if !l.ok() {
   272			return syscall.EINVAL
   273		}
   274		if err := l.close(); err != nil {
   275			return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   276		}
   277		return nil
   278	}
   279	
   280	// Addr returns the listener's network address, a *TCPAddr.
   281	// The Addr returned is shared by all invocations of Addr, so
   282	// do not modify it.
   283	func (l *TCPListener) Addr() Addr { return l.fd.laddr }
   284	
   285	// SetDeadline sets the deadline associated with the listener.
   286	// A zero time value disables the deadline.
   287	func (l *TCPListener) SetDeadline(t time.Time) error {
   288		if !l.ok() {
   289			return syscall.EINVAL
   290		}
   291		if err := l.fd.pfd.SetDeadline(t); err != nil {
   292			return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   293		}
   294		return nil
   295	}
   296	
   297	// File returns a copy of the underlying os.File.
   298	// It is the caller's responsibility to close f when finished.
   299	// Closing l does not affect f, and closing f does not affect l.
   300	//
   301	// The returned os.File's file descriptor is different from the
   302	// connection's. Attempting to change properties of the original
   303	// using this duplicate may or may not have the desired effect.
   304	func (l *TCPListener) File() (f *os.File, err error) {
   305		if !l.ok() {
   306			return nil, syscall.EINVAL
   307		}
   308		f, err = l.file()
   309		if err != nil {
   310			return nil, &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   311		}
   312		return
   313	}
   314	
   315	// ListenTCP acts like Listen for TCP networks.
   316	//
   317	// The network must be a TCP network name; see func Dial for details.
   318	//
   319	// If the IP field of laddr is nil or an unspecified IP address,
   320	// ListenTCP listens on all available unicast and anycast IP addresses
   321	// of the local system.
   322	// If the Port field of laddr is 0, a port number is automatically
   323	// chosen.
   324	func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error) {
   325		switch network {
   326		case "tcp", "tcp4", "tcp6":
   327		default:
   328			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(network)}
   329		}
   330		if laddr == nil {
   331			laddr = &TCPAddr{}
   332		}
   333		sl := &sysListener{network: network, address: laddr.String()}
   334		ln, err := sl.listenTCP(context.Background(), laddr)
   335		if err != nil {
   336			return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
   337		}
   338		return ln, nil
   339	}
   340	

View as plain text