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

View as plain text