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  On Unix the pure Go resolver is preferred over the cgo resolver, because a blocked DNS
    50  request consumes 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.
    58  
    59  On all systems (except Plan 9), when the cgo resolver is being used
    60  this package applies a concurrent cgo lookup limit to prevent the system
    61  from running out of system threads. Currently, it is limited to 500 concurrent lookups.
    62  
    63  The resolver decision can be overridden by setting the netdns value of the
    64  GODEBUG environment variable (see package runtime) to go or cgo, as in:
    65  
    66  	export GODEBUG=netdns=go    # force pure Go resolver
    67  	export GODEBUG=netdns=cgo   # force native resolver (cgo, win32)
    68  
    69  The decision can also be forced while building the Go source tree
    70  by setting the netgo or netcgo build tag.
    71  
    72  A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver
    73  to print debugging information about its decisions.
    74  To force a particular resolver while also printing debugging information,
    75  join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
    76  
    77  On macOS, if Go code that uses the net package is built with
    78  -buildmode=c-archive, linking the resulting archive into a C program
    79  requires passing -lresolv when linking the C code.
    80  
    81  On Plan 9, the resolver always accesses /net/cs and /net/dns.
    82  
    83  On Windows, in Go 1.18.x and earlier, the resolver always used C
    84  library functions, such as GetAddrInfo and DnsQuery.
    85  */
    86  package net
    87  
    88  import (
    89  	"context"
    90  	"errors"
    91  	"internal/poll"
    92  	"io"
    93  	"os"
    94  	"sync"
    95  	"syscall"
    96  	"time"
    97  )
    98  
    99  // Addr represents a network end point address.
   100  //
   101  // The two methods [Addr.Network] and [Addr.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, if known.
   128  	LocalAddr() Addr
   129  
   130  	// RemoteAddr returns the remote network address, if known.
   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, if known.
   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  
   400  	// Deprecated: Temporary errors are not well-defined.
   401  	// Most "temporary" errors are timeouts, and the few exceptions are surprising.
   402  	// Do not use this method.
   403  	Temporary() bool
   404  }
   405  
   406  // Various errors contained in OpError.
   407  var (
   408  	// For connection setup operations.
   409  	errNoSuitableAddress = errors.New("no suitable address found")
   410  
   411  	// For connection setup and write operations.
   412  	errMissingAddress = errors.New("missing address")
   413  
   414  	// For both read and write operations.
   415  	errCanceled         = canceledError{}
   416  	ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection")
   417  )
   418  
   419  // canceledError lets us return the same error string we have always
   420  // returned, while still being Is context.Canceled.
   421  type canceledError struct{}
   422  
   423  func (canceledError) Error() string { return "operation was canceled" }
   424  
   425  func (canceledError) Is(err error) bool { return err == context.Canceled }
   426  
   427  // mapErr maps from the context errors to the historical internal net
   428  // error values.
   429  func mapErr(err error) error {
   430  	switch err {
   431  	case context.Canceled:
   432  		return errCanceled
   433  	case context.DeadlineExceeded:
   434  		return errTimeout
   435  	default:
   436  		return err
   437  	}
   438  }
   439  
   440  // OpError is the error type usually returned by functions in the net
   441  // package. It describes the operation, network type, and address of
   442  // an error.
   443  type OpError struct {
   444  	// Op is the operation which caused the error, such as
   445  	// "read" or "write".
   446  	Op string
   447  
   448  	// Net is the network type on which this error occurred,
   449  	// such as "tcp" or "udp6".
   450  	Net string
   451  
   452  	// For operations involving a remote network connection, like
   453  	// Dial, Read, or Write, Source is the corresponding local
   454  	// network address.
   455  	Source Addr
   456  
   457  	// Addr is the network address for which this error occurred.
   458  	// For local operations, like Listen or SetDeadline, Addr is
   459  	// the address of the local endpoint being manipulated.
   460  	// For operations involving a remote network connection, like
   461  	// Dial, Read, or Write, Addr is the remote address of that
   462  	// connection.
   463  	Addr Addr
   464  
   465  	// Err is the error that occurred during the operation.
   466  	// The Error method panics if the error is nil.
   467  	Err error
   468  }
   469  
   470  func (e *OpError) Unwrap() error { return e.Err }
   471  
   472  func (e *OpError) Error() string {
   473  	if e == nil {
   474  		return "<nil>"
   475  	}
   476  	s := e.Op
   477  	if e.Net != "" {
   478  		s += " " + e.Net
   479  	}
   480  	if e.Source != nil {
   481  		s += " " + e.Source.String()
   482  	}
   483  	if e.Addr != nil {
   484  		if e.Source != nil {
   485  			s += "->"
   486  		} else {
   487  			s += " "
   488  		}
   489  		s += e.Addr.String()
   490  	}
   491  	s += ": " + e.Err.Error()
   492  	return s
   493  }
   494  
   495  var (
   496  	// aLongTimeAgo is a non-zero time, far in the past, used for
   497  	// immediate cancellation of dials.
   498  	aLongTimeAgo = time.Unix(1, 0)
   499  
   500  	// noDeadline and noCancel are just zero values for
   501  	// readability with functions taking too many parameters.
   502  	noDeadline = time.Time{}
   503  	noCancel   = (chan struct{})(nil)
   504  )
   505  
   506  type timeout interface {
   507  	Timeout() bool
   508  }
   509  
   510  func (e *OpError) Timeout() bool {
   511  	if ne, ok := e.Err.(*os.SyscallError); ok {
   512  		t, ok := ne.Err.(timeout)
   513  		return ok && t.Timeout()
   514  	}
   515  	t, ok := e.Err.(timeout)
   516  	return ok && t.Timeout()
   517  }
   518  
   519  type temporary interface {
   520  	Temporary() bool
   521  }
   522  
   523  func (e *OpError) Temporary() bool {
   524  	// Treat ECONNRESET and ECONNABORTED as temporary errors when
   525  	// they come from calling accept. See issue 6163.
   526  	if e.Op == "accept" && isConnError(e.Err) {
   527  		return true
   528  	}
   529  
   530  	if ne, ok := e.Err.(*os.SyscallError); ok {
   531  		t, ok := ne.Err.(temporary)
   532  		return ok && t.Temporary()
   533  	}
   534  	t, ok := e.Err.(temporary)
   535  	return ok && t.Temporary()
   536  }
   537  
   538  // A ParseError is the error type of literal network address parsers.
   539  type ParseError struct {
   540  	// Type is the type of string that was expected, such as
   541  	// "IP address", "CIDR address".
   542  	Type string
   543  
   544  	// Text is the malformed text string.
   545  	Text string
   546  }
   547  
   548  func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
   549  
   550  func (e *ParseError) Timeout() bool   { return false }
   551  func (e *ParseError) Temporary() bool { return false }
   552  
   553  type AddrError struct {
   554  	Err  string
   555  	Addr string
   556  }
   557  
   558  func (e *AddrError) Error() string {
   559  	if e == nil {
   560  		return "<nil>"
   561  	}
   562  	s := e.Err
   563  	if e.Addr != "" {
   564  		s = "address " + e.Addr + ": " + s
   565  	}
   566  	return s
   567  }
   568  
   569  func (e *AddrError) Timeout() bool   { return false }
   570  func (e *AddrError) Temporary() bool { return false }
   571  
   572  type UnknownNetworkError string
   573  
   574  func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
   575  func (e UnknownNetworkError) Timeout() bool   { return false }
   576  func (e UnknownNetworkError) Temporary() bool { return false }
   577  
   578  type InvalidAddrError string
   579  
   580  func (e InvalidAddrError) Error() string   { return string(e) }
   581  func (e InvalidAddrError) Timeout() bool   { return false }
   582  func (e InvalidAddrError) Temporary() bool { return false }
   583  
   584  // errTimeout exists to return the historical "i/o timeout" string
   585  // for context.DeadlineExceeded. See mapErr.
   586  // It is also used when Dialer.Deadline is exceeded.
   587  // error.Is(errTimeout, context.DeadlineExceeded) returns true.
   588  //
   589  // TODO(iant): We could consider changing this to os.ErrDeadlineExceeded
   590  // in the future, if we make
   591  //
   592  //	errors.Is(os.ErrDeadlineExceeded, context.DeadlineExceeded)
   593  //
   594  // return true.
   595  var errTimeout error = &timeoutError{}
   596  
   597  type timeoutError struct{}
   598  
   599  func (e *timeoutError) Error() string   { return "i/o timeout" }
   600  func (e *timeoutError) Timeout() bool   { return true }
   601  func (e *timeoutError) Temporary() bool { return true }
   602  
   603  func (e *timeoutError) Is(err error) bool {
   604  	return err == context.DeadlineExceeded
   605  }
   606  
   607  // DNSConfigError represents an error reading the machine's DNS configuration.
   608  // (No longer used; kept for compatibility.)
   609  type DNSConfigError struct {
   610  	Err error
   611  }
   612  
   613  func (e *DNSConfigError) Unwrap() error   { return e.Err }
   614  func (e *DNSConfigError) Error() string   { return "error reading DNS config: " + e.Err.Error() }
   615  func (e *DNSConfigError) Timeout() bool   { return false }
   616  func (e *DNSConfigError) Temporary() bool { return false }
   617  
   618  // Various errors contained in DNSError.
   619  var (
   620  	errNoSuchHost = errors.New("no such host")
   621  )
   622  
   623  // DNSError represents a DNS lookup error.
   624  type DNSError struct {
   625  	Err         string // description of the error
   626  	Name        string // name looked for
   627  	Server      string // server used
   628  	IsTimeout   bool   // if true, timed out; not all timeouts set this
   629  	IsTemporary bool   // if true, error is temporary; not all errors set this
   630  
   631  	// IsNotFound is set to true when the requested name does not
   632  	// contain any records of the requested type (data not found),
   633  	// or the name itself was not found (NXDOMAIN).
   634  	IsNotFound bool
   635  }
   636  
   637  func (e *DNSError) Error() string {
   638  	if e == nil {
   639  		return "<nil>"
   640  	}
   641  	s := "lookup " + e.Name
   642  	if e.Server != "" {
   643  		s += " on " + e.Server
   644  	}
   645  	s += ": " + e.Err
   646  	return s
   647  }
   648  
   649  // Timeout reports whether the DNS lookup is known to have timed out.
   650  // This is not always known; a DNS lookup may fail due to a timeout
   651  // and return a [DNSError] for which Timeout returns false.
   652  func (e *DNSError) Timeout() bool { return e.IsTimeout }
   653  
   654  // Temporary reports whether the DNS error is known to be temporary.
   655  // This is not always known; a DNS lookup may fail due to a temporary
   656  // error and return a [DNSError] for which Temporary returns false.
   657  func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   658  
   659  // errClosed exists just so that the docs for ErrClosed don't mention
   660  // the internal package poll.
   661  var errClosed = poll.ErrNetClosing
   662  
   663  // ErrClosed is the error returned by an I/O call on a network
   664  // connection that has already been closed, or that is closed by
   665  // another goroutine before the I/O is completed. This may be wrapped
   666  // in another error, and should normally be tested using
   667  // errors.Is(err, net.ErrClosed).
   668  var ErrClosed error = errClosed
   669  
   670  // noReadFrom can be embedded alongside another type to
   671  // hide the ReadFrom method of that other type.
   672  type noReadFrom struct{}
   673  
   674  // ReadFrom hides another ReadFrom method.
   675  // It should never be called.
   676  func (noReadFrom) ReadFrom(io.Reader) (int64, error) {
   677  	panic("can't happen")
   678  }
   679  
   680  // tcpConnWithoutReadFrom implements all the methods of *TCPConn other
   681  // than ReadFrom. This is used to permit ReadFrom to call io.Copy
   682  // without leading to a recursive call to ReadFrom.
   683  type tcpConnWithoutReadFrom struct {
   684  	noReadFrom
   685  	*TCPConn
   686  }
   687  
   688  // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   689  // applicable.
   690  func genericReadFrom(c *TCPConn, r io.Reader) (n int64, err error) {
   691  	// Use wrapper to hide existing r.ReadFrom from io.Copy.
   692  	return io.Copy(tcpConnWithoutReadFrom{TCPConn: c}, r)
   693  }
   694  
   695  // noWriteTo can be embedded alongside another type to
   696  // hide the WriteTo method of that other type.
   697  type noWriteTo struct{}
   698  
   699  // WriteTo hides another WriteTo method.
   700  // It should never be called.
   701  func (noWriteTo) WriteTo(io.Writer) (int64, error) {
   702  	panic("can't happen")
   703  }
   704  
   705  // tcpConnWithoutWriteTo implements all the methods of *TCPConn other
   706  // than WriteTo. This is used to permit WriteTo to call io.Copy
   707  // without leading to a recursive call to WriteTo.
   708  type tcpConnWithoutWriteTo struct {
   709  	noWriteTo
   710  	*TCPConn
   711  }
   712  
   713  // Fallback implementation of io.WriterTo's WriteTo, when zero-copy isn't applicable.
   714  func genericWriteTo(c *TCPConn, w io.Writer) (n int64, err error) {
   715  	// Use wrapper to hide existing w.WriteTo from io.Copy.
   716  	return io.Copy(w, tcpConnWithoutWriteTo{TCPConn: c})
   717  }
   718  
   719  // Limit the number of concurrent cgo-using goroutines, because
   720  // each will block an entire operating system thread. The usual culprit
   721  // is resolving many DNS names in separate goroutines but the DNS
   722  // server is not responding. Then the many lookups each use a different
   723  // thread, and the system or the program runs out of threads.
   724  
   725  var threadLimit chan struct{}
   726  
   727  var threadOnce sync.Once
   728  
   729  func acquireThread(ctx context.Context) error {
   730  	threadOnce.Do(func() {
   731  		threadLimit = make(chan struct{}, concurrentThreadsLimit())
   732  	})
   733  	select {
   734  	case threadLimit <- struct{}{}:
   735  		return nil
   736  	case <-ctx.Done():
   737  		return ctx.Err()
   738  	}
   739  }
   740  
   741  func releaseThread() {
   742  	<-threadLimit
   743  }
   744  
   745  // buffersWriter is the interface implemented by Conns that support a
   746  // "writev"-like batch write optimization.
   747  // writeBuffers should fully consume and write all chunks from the
   748  // provided Buffers, else it should report a non-nil error.
   749  type buffersWriter interface {
   750  	writeBuffers(*Buffers) (int64, error)
   751  }
   752  
   753  // Buffers contains zero or more runs of bytes to write.
   754  //
   755  // On certain machines, for certain types of connections, this is
   756  // optimized into an OS-specific batch write operation (such as
   757  // "writev").
   758  type Buffers [][]byte
   759  
   760  var (
   761  	_ io.WriterTo = (*Buffers)(nil)
   762  	_ io.Reader   = (*Buffers)(nil)
   763  )
   764  
   765  // WriteTo writes contents of the buffers to w.
   766  //
   767  // WriteTo implements [io.WriterTo] for [Buffers].
   768  //
   769  // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
   770  // but does not modify v[i][j] for any i, j.
   771  func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   772  	if wv, ok := w.(buffersWriter); ok {
   773  		return wv.writeBuffers(v)
   774  	}
   775  	for _, b := range *v {
   776  		nb, err := w.Write(b)
   777  		n += int64(nb)
   778  		if err != nil {
   779  			v.consume(n)
   780  			return n, err
   781  		}
   782  	}
   783  	v.consume(n)
   784  	return n, nil
   785  }
   786  
   787  // Read from the buffers.
   788  //
   789  // Read implements [io.Reader] for [Buffers].
   790  //
   791  // Read modifies the slice v as well as v[i] for 0 <= i < len(v),
   792  // but does not modify v[i][j] for any i, j.
   793  func (v *Buffers) Read(p []byte) (n int, err error) {
   794  	for len(p) > 0 && len(*v) > 0 {
   795  		n0 := copy(p, (*v)[0])
   796  		v.consume(int64(n0))
   797  		p = p[n0:]
   798  		n += n0
   799  	}
   800  	if len(*v) == 0 {
   801  		err = io.EOF
   802  	}
   803  	return
   804  }
   805  
   806  func (v *Buffers) consume(n int64) {
   807  	for len(*v) > 0 {
   808  		ln0 := int64(len((*v)[0]))
   809  		if ln0 > n {
   810  			(*v)[0] = (*v)[0][n:]
   811  			return
   812  		}
   813  		n -= ln0
   814  		(*v)[0] = nil
   815  		*v = (*v)[1:]
   816  	}
   817  }
   818  

View as plain text