Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/net.go

Documentation: net

     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  /*
     6  Package net provides a portable interface for network I/O, including
     7  TCP/IP, UDP, domain name resolution, and Unix domain sockets.
     8  
     9  Although the package provides access to low-level networking
    10  primitives, most clients will need only the basic interface provided
    11  by the Dial, Listen, and Accept functions and the associated
    12  Conn and Listener interfaces. The crypto/tls package uses
    13  the same interfaces and similar Dial and Listen functions.
    14  
    15  The Dial function connects to a server:
    16  
    17  	conn, err := net.Dial("tcp", "golang.org:80")
    18  	if err != nil {
    19  		// handle error
    20  	}
    21  	fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
    22  	status, err := bufio.NewReader(conn).ReadString('\n')
    23  	// ...
    24  
    25  The Listen function creates servers:
    26  
    27  	ln, err := net.Listen("tcp", ":8080")
    28  	if err != nil {
    29  		// handle error
    30  	}
    31  	for {
    32  		conn, err := ln.Accept()
    33  		if err != nil {
    34  			// handle error
    35  		}
    36  		go handleConnection(conn)
    37  	}
    38  
    39  Name Resolution
    40  
    41  The method for resolving domain names, whether indirectly with functions like Dial
    42  or directly with functions like LookupHost and LookupAddr, varies by operating system.
    43  
    44  On Unix systems, the resolver has two options for resolving names.
    45  It can use a pure Go resolver that sends DNS requests directly to the servers
    46  listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C
    47  library routines such as getaddrinfo and getnameinfo.
    48  
    49  By default the pure Go resolver is used, because a blocked DNS request consumes
    50  only a goroutine, while a blocked C call consumes an operating system thread.
    51  When cgo is available, the cgo-based resolver is used instead under a variety of
    52  conditions: on systems that do not let programs make direct DNS requests (OS X),
    53  when the LOCALDOMAIN environment variable is present (even if empty),
    54  when the RES_OPTIONS or HOSTALIASES environment variable is non-empty,
    55  when the ASR_CONFIG environment variable is non-empty (OpenBSD only),
    56  when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the
    57  Go resolver does not implement, and when the name being looked up ends in .local
    58  or is an mDNS name.
    59  
    60  The resolver decision can be overridden by setting the netdns value of the
    61  GODEBUG environment variable (see package runtime) to go or cgo, as in:
    62  
    63  	export GODEBUG=netdns=go    # force pure Go resolver
    64  	export GODEBUG=netdns=cgo   # force cgo resolver
    65  
    66  The decision can also be forced while building the Go source tree
    67  by setting the netgo or netcgo build tag.
    68  
    69  A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver
    70  to print debugging information about its decisions.
    71  To force a particular resolver while also printing debugging information,
    72  join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
    73  
    74  On Plan 9, the resolver always accesses /net/cs and /net/dns.
    75  
    76  On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery.
    77  
    78  */
    79  package net
    80  
    81  import (
    82  	"context"
    83  	"errors"
    84  	"io"
    85  	"os"
    86  	"sync"
    87  	"syscall"
    88  	"time"
    89  )
    90  
    91  // netGo and netCgo contain the state of the build tags used
    92  // to build this binary, and whether cgo is available.
    93  // conf.go mirrors these into conf for easier testing.
    94  var (
    95  	netGo  bool // set true in cgo_stub.go for build tag "netgo" (or no cgo)
    96  	netCgo bool // set true in conf_netcgo.go for build tag "netcgo"
    97  )
    98  
    99  // Addr represents a network end point address.
   100  //
   101  // The two methods Network and String conventionally return strings
   102  // that can be passed as the arguments to Dial, but the exact form
   103  // and meaning of the strings is up to the implementation.
   104  type Addr interface {
   105  	Network() string // name of the network (for example, "tcp", "udp")
   106  	String() string  // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
   107  }
   108  
   109  // Conn is a generic stream-oriented network connection.
   110  //
   111  // Multiple goroutines may invoke methods on a Conn simultaneously.
   112  type Conn interface {
   113  	// Read reads data from the connection.
   114  	// Read can be made to time out and return an error after a fixed
   115  	// time limit; see SetDeadline and SetReadDeadline.
   116  	Read(b []byte) (n int, err error)
   117  
   118  	// Write writes data to the connection.
   119  	// Write can be made to time out and return an error after a fixed
   120  	// time limit; see SetDeadline and SetWriteDeadline.
   121  	Write(b []byte) (n int, err error)
   122  
   123  	// Close closes the connection.
   124  	// Any blocked Read or Write operations will be unblocked and return errors.
   125  	Close() error
   126  
   127  	// LocalAddr returns the local network address.
   128  	LocalAddr() Addr
   129  
   130  	// RemoteAddr returns the remote network address.
   131  	RemoteAddr() Addr
   132  
   133  	// SetDeadline sets the read and write deadlines associated
   134  	// with the connection. It is equivalent to calling both
   135  	// SetReadDeadline and SetWriteDeadline.
   136  	//
   137  	// A deadline is an absolute time after which I/O operations
   138  	// fail instead of blocking. The deadline applies to all future
   139  	// and pending I/O, not just the immediately following call to
   140  	// Read or Write. After a deadline has been exceeded, the
   141  	// connection can be refreshed by setting a deadline in the future.
   142  	//
   143  	// If the deadline is exceeded a call to Read or Write or to other
   144  	// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
   145  	// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
   146  	// The error's Timeout method will return true, but note that there
   147  	// are other possible errors for which the Timeout method will
   148  	// return true even if the deadline has not been exceeded.
   149  	//
   150  	// An idle timeout can be implemented by repeatedly extending
   151  	// the deadline after successful Read or Write calls.
   152  	//
   153  	// A zero value for t means I/O operations will not time out.
   154  	SetDeadline(t time.Time) error
   155  
   156  	// SetReadDeadline sets the deadline for future Read calls
   157  	// and any currently-blocked Read call.
   158  	// A zero value for t means Read will not time out.
   159  	SetReadDeadline(t time.Time) error
   160  
   161  	// SetWriteDeadline sets the deadline for future Write calls
   162  	// and any currently-blocked Write call.
   163  	// Even if write times out, it may return n > 0, indicating that
   164  	// some of the data was successfully written.
   165  	// A zero value for t means Write will not time out.
   166  	SetWriteDeadline(t time.Time) error
   167  }
   168  
   169  type conn struct {
   170  	fd *netFD
   171  }
   172  
   173  func (c *conn) ok() bool { return c != nil && c.fd != nil }
   174  
   175  // Implementation of the Conn interface.
   176  
   177  // Read implements the Conn Read method.
   178  func (c *conn) Read(b []byte) (int, error) {
   179  	if !c.ok() {
   180  		return 0, syscall.EINVAL
   181  	}
   182  	n, err := c.fd.Read(b)
   183  	if err != nil && err != io.EOF {
   184  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   185  	}
   186  	return n, err
   187  }
   188  
   189  // Write implements the Conn Write method.
   190  func (c *conn) Write(b []byte) (int, error) {
   191  	if !c.ok() {
   192  		return 0, syscall.EINVAL
   193  	}
   194  	n, err := c.fd.Write(b)
   195  	if err != nil {
   196  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   197  	}
   198  	return n, err
   199  }
   200  
   201  // Close closes the connection.
   202  func (c *conn) Close() error {
   203  	if !c.ok() {
   204  		return syscall.EINVAL
   205  	}
   206  	err := c.fd.Close()
   207  	if err != nil {
   208  		err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   209  	}
   210  	return err
   211  }
   212  
   213  // LocalAddr returns the local network address.
   214  // The Addr returned is shared by all invocations of LocalAddr, so
   215  // do not modify it.
   216  func (c *conn) LocalAddr() Addr {
   217  	if !c.ok() {
   218  		return nil
   219  	}
   220  	return c.fd.laddr
   221  }
   222  
   223  // RemoteAddr returns the remote network address.
   224  // The Addr returned is shared by all invocations of RemoteAddr, so
   225  // do not modify it.
   226  func (c *conn) RemoteAddr() Addr {
   227  	if !c.ok() {
   228  		return nil
   229  	}
   230  	return c.fd.raddr
   231  }
   232  
   233  // SetDeadline implements the Conn SetDeadline method.
   234  func (c *conn) SetDeadline(t time.Time) error {
   235  	if !c.ok() {
   236  		return syscall.EINVAL
   237  	}
   238  	if err := c.fd.SetDeadline(t); err != nil {
   239  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   240  	}
   241  	return nil
   242  }
   243  
   244  // SetReadDeadline implements the Conn SetReadDeadline method.
   245  func (c *conn) SetReadDeadline(t time.Time) error {
   246  	if !c.ok() {
   247  		return syscall.EINVAL
   248  	}
   249  	if err := c.fd.SetReadDeadline(t); err != nil {
   250  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   251  	}
   252  	return nil
   253  }
   254  
   255  // SetWriteDeadline implements the Conn SetWriteDeadline method.
   256  func (c *conn) SetWriteDeadline(t time.Time) error {
   257  	if !c.ok() {
   258  		return syscall.EINVAL
   259  	}
   260  	if err := c.fd.SetWriteDeadline(t); err != nil {
   261  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   262  	}
   263  	return nil
   264  }
   265  
   266  // SetReadBuffer sets the size of the operating system's
   267  // receive buffer associated with the connection.
   268  func (c *conn) SetReadBuffer(bytes int) error {
   269  	if !c.ok() {
   270  		return syscall.EINVAL
   271  	}
   272  	if err := setReadBuffer(c.fd, bytes); err != nil {
   273  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   274  	}
   275  	return nil
   276  }
   277  
   278  // SetWriteBuffer sets the size of the operating system's
   279  // transmit buffer associated with the connection.
   280  func (c *conn) SetWriteBuffer(bytes int) error {
   281  	if !c.ok() {
   282  		return syscall.EINVAL
   283  	}
   284  	if err := setWriteBuffer(c.fd, bytes); err != nil {
   285  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   286  	}
   287  	return nil
   288  }
   289  
   290  // File returns a copy of the underlying os.File.
   291  // It is the caller's responsibility to close f when finished.
   292  // Closing c does not affect f, and closing f does not affect c.
   293  //
   294  // The returned os.File's file descriptor is different from the connection's.
   295  // Attempting to change properties of the original using this duplicate
   296  // may or may not have the desired effect.
   297  func (c *conn) File() (f *os.File, err error) {
   298  	f, err = c.fd.dup()
   299  	if err != nil {
   300  		err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   301  	}
   302  	return
   303  }
   304  
   305  // PacketConn is a generic packet-oriented network connection.
   306  //
   307  // Multiple goroutines may invoke methods on a PacketConn simultaneously.
   308  type PacketConn interface {
   309  	// ReadFrom reads a packet from the connection,
   310  	// copying the payload into p. It returns the number of
   311  	// bytes copied into p and the return address that
   312  	// was on the packet.
   313  	// It returns the number of bytes read (0 <= n <= len(p))
   314  	// and any error encountered. Callers should always process
   315  	// the n > 0 bytes returned before considering the error err.
   316  	// ReadFrom can be made to time out and return an error after a
   317  	// fixed time limit; see SetDeadline and SetReadDeadline.
   318  	ReadFrom(p []byte) (n int, addr Addr, err error)
   319  
   320  	// WriteTo writes a packet with payload p to addr.
   321  	// WriteTo can be made to time out and return an Error after a
   322  	// fixed time limit; see SetDeadline and SetWriteDeadline.
   323  	// On packet-oriented connections, write timeouts are rare.
   324  	WriteTo(p []byte, addr Addr) (n int, err error)
   325  
   326  	// Close closes the connection.
   327  	// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.
   328  	Close() error
   329  
   330  	// LocalAddr returns the local network address.
   331  	LocalAddr() Addr
   332  
   333  	// SetDeadline sets the read and write deadlines associated
   334  	// with the connection. It is equivalent to calling both
   335  	// SetReadDeadline and SetWriteDeadline.
   336  	//
   337  	// A deadline is an absolute time after which I/O operations
   338  	// fail instead of blocking. The deadline applies to all future
   339  	// and pending I/O, not just the immediately following call to
   340  	// Read or Write. After a deadline has been exceeded, the
   341  	// connection can be refreshed by setting a deadline in the future.
   342  	//
   343  	// If the deadline is exceeded a call to Read or Write or to other
   344  	// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
   345  	// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
   346  	// The error's Timeout method will return true, but note that there
   347  	// are other possible errors for which the Timeout method will
   348  	// return true even if the deadline has not been exceeded.
   349  	//
   350  	// An idle timeout can be implemented by repeatedly extending
   351  	// the deadline after successful ReadFrom or WriteTo calls.
   352  	//
   353  	// A zero value for t means I/O operations will not time out.
   354  	SetDeadline(t time.Time) error
   355  
   356  	// SetReadDeadline sets the deadline for future ReadFrom calls
   357  	// and any currently-blocked ReadFrom call.
   358  	// A zero value for t means ReadFrom will not time out.
   359  	SetReadDeadline(t time.Time) error
   360  
   361  	// SetWriteDeadline sets the deadline for future WriteTo calls
   362  	// and any currently-blocked WriteTo call.
   363  	// Even if write times out, it may return n > 0, indicating that
   364  	// some of the data was successfully written.
   365  	// A zero value for t means WriteTo will not time out.
   366  	SetWriteDeadline(t time.Time) error
   367  }
   368  
   369  var listenerBacklogCache struct {
   370  	sync.Once
   371  	val int
   372  }
   373  
   374  // listenerBacklog is a caching wrapper around maxListenerBacklog.
   375  func listenerBacklog() int {
   376  	listenerBacklogCache.Do(func() { listenerBacklogCache.val = maxListenerBacklog() })
   377  	return listenerBacklogCache.val
   378  }
   379  
   380  // A Listener is a generic network listener for stream-oriented protocols.
   381  //
   382  // Multiple goroutines may invoke methods on a Listener simultaneously.
   383  type Listener interface {
   384  	// Accept waits for and returns the next connection to the listener.
   385  	Accept() (Conn, error)
   386  
   387  	// Close closes the listener.
   388  	// Any blocked Accept operations will be unblocked and return errors.
   389  	Close() error
   390  
   391  	// Addr returns the listener's network address.
   392  	Addr() Addr
   393  }
   394  
   395  // An Error represents a network error.
   396  type Error interface {
   397  	error
   398  	Timeout() bool   // Is the error a timeout?
   399  	Temporary() bool // Is the error temporary?
   400  }
   401  
   402  // Various errors contained in OpError.
   403  var (
   404  	// For connection setup operations.
   405  	errNoSuitableAddress = errors.New("no suitable address found")
   406  
   407  	// For connection setup and write operations.
   408  	errMissingAddress = errors.New("missing address")
   409  
   410  	// For both read and write operations.
   411  	errCanceled         = errors.New("operation was canceled")
   412  	ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection")
   413  )
   414  
   415  // mapErr maps from the context errors to the historical internal net
   416  // error values.
   417  //
   418  // TODO(bradfitz): get rid of this after adjusting tests and making
   419  // context.DeadlineExceeded implement net.Error?
   420  func mapErr(err error) error {
   421  	switch err {
   422  	case context.Canceled:
   423  		return errCanceled
   424  	case context.DeadlineExceeded:
   425  		return errTimeout
   426  	default:
   427  		return err
   428  	}
   429  }
   430  
   431  // OpError is the error type usually returned by functions in the net
   432  // package. It describes the operation, network type, and address of
   433  // an error.
   434  type OpError struct {
   435  	// Op is the operation which caused the error, such as
   436  	// "read" or "write".
   437  	Op string
   438  
   439  	// Net is the network type on which this error occurred,
   440  	// such as "tcp" or "udp6".
   441  	Net string
   442  
   443  	// For operations involving a remote network connection, like
   444  	// Dial, Read, or Write, Source is the corresponding local
   445  	// network address.
   446  	Source Addr
   447  
   448  	// Addr is the network address for which this error occurred.
   449  	// For local operations, like Listen or SetDeadline, Addr is
   450  	// the address of the local endpoint being manipulated.
   451  	// For operations involving a remote network connection, like
   452  	// Dial, Read, or Write, Addr is the remote address of that
   453  	// connection.
   454  	Addr Addr
   455  
   456  	// Err is the error that occurred during the operation.
   457  	// The Error method panics if the error is nil.
   458  	Err error
   459  }
   460  
   461  func (e *OpError) Unwrap() error { return e.Err }
   462  
   463  func (e *OpError) Error() string {
   464  	if e == nil {
   465  		return "<nil>"
   466  	}
   467  	s := e.Op
   468  	if e.Net != "" {
   469  		s += " " + e.Net
   470  	}
   471  	if e.Source != nil {
   472  		s += " " + e.Source.String()
   473  	}
   474  	if e.Addr != nil {
   475  		if e.Source != nil {
   476  			s += "->"
   477  		} else {
   478  			s += " "
   479  		}
   480  		s += e.Addr.String()
   481  	}
   482  	s += ": " + e.Err.Error()
   483  	return s
   484  }
   485  
   486  var (
   487  	// aLongTimeAgo is a non-zero time, far in the past, used for
   488  	// immediate cancellation of dials.
   489  	aLongTimeAgo = time.Unix(1, 0)
   490  
   491  	// nonDeadline and noCancel are just zero values for
   492  	// readability with functions taking too many parameters.
   493  	noDeadline = time.Time{}
   494  	noCancel   = (chan struct{})(nil)
   495  )
   496  
   497  type timeout interface {
   498  	Timeout() bool
   499  }
   500  
   501  func (e *OpError) Timeout() bool {
   502  	if ne, ok := e.Err.(*os.SyscallError); ok {
   503  		t, ok := ne.Err.(timeout)
   504  		return ok && t.Timeout()
   505  	}
   506  	t, ok := e.Err.(timeout)
   507  	return ok && t.Timeout()
   508  }
   509  
   510  type temporary interface {
   511  	Temporary() bool
   512  }
   513  
   514  func (e *OpError) Temporary() bool {
   515  	// Treat ECONNRESET and ECONNABORTED as temporary errors when
   516  	// they come from calling accept. See issue 6163.
   517  	if e.Op == "accept" && isConnError(e.Err) {
   518  		return true
   519  	}
   520  
   521  	if ne, ok := e.Err.(*os.SyscallError); ok {
   522  		t, ok := ne.Err.(temporary)
   523  		return ok && t.Temporary()
   524  	}
   525  	t, ok := e.Err.(temporary)
   526  	return ok && t.Temporary()
   527  }
   528  
   529  // A ParseError is the error type of literal network address parsers.
   530  type ParseError struct {
   531  	// Type is the type of string that was expected, such as
   532  	// "IP address", "CIDR address".
   533  	Type string
   534  
   535  	// Text is the malformed text string.
   536  	Text string
   537  }
   538  
   539  func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
   540  
   541  type AddrError struct {
   542  	Err  string
   543  	Addr string
   544  }
   545  
   546  func (e *AddrError) Error() string {
   547  	if e == nil {
   548  		return "<nil>"
   549  	}
   550  	s := e.Err
   551  	if e.Addr != "" {
   552  		s = "address " + e.Addr + ": " + s
   553  	}
   554  	return s
   555  }
   556  
   557  func (e *AddrError) Timeout() bool   { return false }
   558  func (e *AddrError) Temporary() bool { return false }
   559  
   560  type UnknownNetworkError string
   561  
   562  func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
   563  func (e UnknownNetworkError) Timeout() bool   { return false }
   564  func (e UnknownNetworkError) Temporary() bool { return false }
   565  
   566  type InvalidAddrError string
   567  
   568  func (e InvalidAddrError) Error() string   { return string(e) }
   569  func (e InvalidAddrError) Timeout() bool   { return false }
   570  func (e InvalidAddrError) Temporary() bool { return false }
   571  
   572  // errTimeout exists to return the historical "i/o timeout" string
   573  // for context.DeadlineExceeded. See mapErr.
   574  // It is also used when Dialer.Deadline is exceeded.
   575  //
   576  // TODO(iant): We could consider changing this to os.ErrDeadlineExceeded
   577  // in the future, but note that that would conflict with the TODO
   578  // at mapErr that suggests changing it to context.DeadlineExceeded.
   579  var errTimeout error = &timeoutError{}
   580  
   581  type timeoutError struct{}
   582  
   583  func (e *timeoutError) Error() string   { return "i/o timeout" }
   584  func (e *timeoutError) Timeout() bool   { return true }
   585  func (e *timeoutError) Temporary() bool { return true }
   586  
   587  // DNSConfigError represents an error reading the machine's DNS configuration.
   588  // (No longer used; kept for compatibility.)
   589  type DNSConfigError struct {
   590  	Err error
   591  }
   592  
   593  func (e *DNSConfigError) Unwrap() error   { return e.Err }
   594  func (e *DNSConfigError) Error() string   { return "error reading DNS config: " + e.Err.Error() }
   595  func (e *DNSConfigError) Timeout() bool   { return false }
   596  func (e *DNSConfigError) Temporary() bool { return false }
   597  
   598  // Various errors contained in DNSError.
   599  var (
   600  	errNoSuchHost = errors.New("no such host")
   601  )
   602  
   603  // DNSError represents a DNS lookup error.
   604  type DNSError struct {
   605  	Err         string // description of the error
   606  	Name        string // name looked for
   607  	Server      string // server used
   608  	IsTimeout   bool   // if true, timed out; not all timeouts set this
   609  	IsTemporary bool   // if true, error is temporary; not all errors set this
   610  	IsNotFound  bool   // if true, host could not be found
   611  }
   612  
   613  func (e *DNSError) Error() string {
   614  	if e == nil {
   615  		return "<nil>"
   616  	}
   617  	s := "lookup " + e.Name
   618  	if e.Server != "" {
   619  		s += " on " + e.Server
   620  	}
   621  	s += ": " + e.Err
   622  	return s
   623  }
   624  
   625  // Timeout reports whether the DNS lookup is known to have timed out.
   626  // This is not always known; a DNS lookup may fail due to a timeout
   627  // and return a DNSError for which Timeout returns false.
   628  func (e *DNSError) Timeout() bool { return e.IsTimeout }
   629  
   630  // Temporary reports whether the DNS error is known to be temporary.
   631  // This is not always known; a DNS lookup may fail due to a temporary
   632  // error and return a DNSError for which Temporary returns false.
   633  func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   634  
   635  type writerOnly struct {
   636  	io.Writer
   637  }
   638  
   639  // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   640  // applicable.
   641  func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
   642  	// Use wrapper to hide existing r.ReadFrom from io.Copy.
   643  	return io.Copy(writerOnly{w}, r)
   644  }
   645  
   646  // Limit the number of concurrent cgo-using goroutines, because
   647  // each will block an entire operating system thread. The usual culprit
   648  // is resolving many DNS names in separate goroutines but the DNS
   649  // server is not responding. Then the many lookups each use a different
   650  // thread, and the system or the program runs out of threads.
   651  
   652  var threadLimit chan struct{}
   653  
   654  var threadOnce sync.Once
   655  
   656  func acquireThread() {
   657  	threadOnce.Do(func() {
   658  		threadLimit = make(chan struct{}, concurrentThreadsLimit())
   659  	})
   660  	threadLimit <- struct{}{}
   661  }
   662  
   663  func releaseThread() {
   664  	<-threadLimit
   665  }
   666  
   667  // buffersWriter is the interface implemented by Conns that support a
   668  // "writev"-like batch write optimization.
   669  // writeBuffers should fully consume and write all chunks from the
   670  // provided Buffers, else it should report a non-nil error.
   671  type buffersWriter interface {
   672  	writeBuffers(*Buffers) (int64, error)
   673  }
   674  
   675  // Buffers contains zero or more runs of bytes to write.
   676  //
   677  // On certain machines, for certain types of connections, this is
   678  // optimized into an OS-specific batch write operation (such as
   679  // "writev").
   680  type Buffers [][]byte
   681  
   682  var (
   683  	_ io.WriterTo = (*Buffers)(nil)
   684  	_ io.Reader   = (*Buffers)(nil)
   685  )
   686  
   687  func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   688  	if wv, ok := w.(buffersWriter); ok {
   689  		return wv.writeBuffers(v)
   690  	}
   691  	for _, b := range *v {
   692  		nb, err := w.Write(b)
   693  		n += int64(nb)
   694  		if err != nil {
   695  			v.consume(n)
   696  			return n, err
   697  		}
   698  	}
   699  	v.consume(n)
   700  	return n, nil
   701  }
   702  
   703  func (v *Buffers) Read(p []byte) (n int, err error) {
   704  	for len(p) > 0 && len(*v) > 0 {
   705  		n0 := copy(p, (*v)[0])
   706  		v.consume(int64(n0))
   707  		p = p[n0:]
   708  		n += n0
   709  	}
   710  	if len(*v) == 0 {
   711  		err = io.EOF
   712  	}
   713  	return
   714  }
   715  
   716  func (v *Buffers) consume(n int64) {
   717  	for len(*v) > 0 {
   718  		ln0 := int64(len((*v)[0]))
   719  		if ln0 > n {
   720  			(*v)[0] = (*v)[0][n:]
   721  			return
   722  		}
   723  		n -= ln0
   724  		*v = (*v)[1:]
   725  	}
   726  }
   727  

View as plain text