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  = &notFoundError{"no such host"}
   621  	errUnknownPort = &notFoundError{"unknown port"}
   622  )
   623  
   624  // notFoundError is a special error understood by the newDNSError function,
   625  // which causes a creation of a DNSError with IsNotFound field set to true.
   626  type notFoundError struct{ s string }
   627  
   628  func (e *notFoundError) Error() string { return e.s }
   629  
   630  // temporaryError is an error type that implements the [Error] interface.
   631  // It returns true from the Temporary method.
   632  type temporaryError struct{ s string }
   633  
   634  func (e *temporaryError) Error() string   { return e.s }
   635  func (e *temporaryError) Temporary() bool { return true }
   636  func (e *temporaryError) Timeout() bool   { return false }
   637  
   638  // DNSError represents a DNS lookup error.
   639  type DNSError struct {
   640  	UnwrapErr   error  // error returned by the [DNSError.Unwrap] method, might be nil
   641  	Err         string // description of the error
   642  	Name        string // name looked for
   643  	Server      string // server used
   644  	IsTimeout   bool   // if true, timed out; not all timeouts set this
   645  	IsTemporary bool   // if true, error is temporary; not all errors set this
   646  
   647  	// IsNotFound is set to true when the requested name does not
   648  	// contain any records of the requested type (data not found),
   649  	// or the name itself was not found (NXDOMAIN).
   650  	IsNotFound bool
   651  }
   652  
   653  // newDNSError creates a new *DNSError.
   654  // Based on the err, it sets the UnwrapErr, IsTimeout, IsTemporary, IsNotFound fields.
   655  func newDNSError(err error, name, server string) *DNSError {
   656  	var (
   657  		isTimeout   bool
   658  		isTemporary bool
   659  		unwrapErr   error
   660  	)
   661  
   662  	if err, ok := err.(Error); ok {
   663  		isTimeout = err.Timeout()
   664  		isTemporary = err.Temporary()
   665  	}
   666  
   667  	// At this time, the only errors we wrap are context errors, to allow
   668  	// users to check for canceled/timed out requests.
   669  	if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
   670  		unwrapErr = err
   671  	}
   672  
   673  	_, isNotFound := err.(*notFoundError)
   674  	return &DNSError{
   675  		UnwrapErr:   unwrapErr,
   676  		Err:         err.Error(),
   677  		Name:        name,
   678  		Server:      server,
   679  		IsTimeout:   isTimeout,
   680  		IsTemporary: isTemporary,
   681  		IsNotFound:  isNotFound,
   682  	}
   683  }
   684  
   685  // Unwrap returns e.UnwrapErr.
   686  func (e *DNSError) Unwrap() error { return e.UnwrapErr }
   687  
   688  func (e *DNSError) Error() string {
   689  	if e == nil {
   690  		return "<nil>"
   691  	}
   692  	s := "lookup " + e.Name
   693  	if e.Server != "" {
   694  		s += " on " + e.Server
   695  	}
   696  	s += ": " + e.Err
   697  	return s
   698  }
   699  
   700  // Timeout reports whether the DNS lookup is known to have timed out.
   701  // This is not always known; a DNS lookup may fail due to a timeout
   702  // and return a [DNSError] for which Timeout returns false.
   703  func (e *DNSError) Timeout() bool { return e.IsTimeout }
   704  
   705  // Temporary reports whether the DNS error is known to be temporary.
   706  // This is not always known; a DNS lookup may fail due to a temporary
   707  // error and return a [DNSError] for which Temporary returns false.
   708  func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   709  
   710  // errClosed exists just so that the docs for ErrClosed don't mention
   711  // the internal package poll.
   712  var errClosed = poll.ErrNetClosing
   713  
   714  // ErrClosed is the error returned by an I/O call on a network
   715  // connection that has already been closed, or that is closed by
   716  // another goroutine before the I/O is completed. This may be wrapped
   717  // in another error, and should normally be tested using
   718  // errors.Is(err, net.ErrClosed).
   719  var ErrClosed error = errClosed
   720  
   721  // noReadFrom can be embedded alongside another type to
   722  // hide the ReadFrom method of that other type.
   723  type noReadFrom struct{}
   724  
   725  // ReadFrom hides another ReadFrom method.
   726  // It should never be called.
   727  func (noReadFrom) ReadFrom(io.Reader) (int64, error) {
   728  	panic("can't happen")
   729  }
   730  
   731  // tcpConnWithoutReadFrom implements all the methods of *TCPConn other
   732  // than ReadFrom. This is used to permit ReadFrom to call io.Copy
   733  // without leading to a recursive call to ReadFrom.
   734  type tcpConnWithoutReadFrom struct {
   735  	noReadFrom
   736  	*TCPConn
   737  }
   738  
   739  // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   740  // applicable.
   741  func genericReadFrom(c *TCPConn, r io.Reader) (n int64, err error) {
   742  	// Use wrapper to hide existing r.ReadFrom from io.Copy.
   743  	return io.Copy(tcpConnWithoutReadFrom{TCPConn: c}, r)
   744  }
   745  
   746  // noWriteTo can be embedded alongside another type to
   747  // hide the WriteTo method of that other type.
   748  type noWriteTo struct{}
   749  
   750  // WriteTo hides another WriteTo method.
   751  // It should never be called.
   752  func (noWriteTo) WriteTo(io.Writer) (int64, error) {
   753  	panic("can't happen")
   754  }
   755  
   756  // tcpConnWithoutWriteTo implements all the methods of *TCPConn other
   757  // than WriteTo. This is used to permit WriteTo to call io.Copy
   758  // without leading to a recursive call to WriteTo.
   759  type tcpConnWithoutWriteTo struct {
   760  	noWriteTo
   761  	*TCPConn
   762  }
   763  
   764  // Fallback implementation of io.WriterTo's WriteTo, when zero-copy isn't applicable.
   765  func genericWriteTo(c *TCPConn, w io.Writer) (n int64, err error) {
   766  	// Use wrapper to hide existing w.WriteTo from io.Copy.
   767  	return io.Copy(w, tcpConnWithoutWriteTo{TCPConn: c})
   768  }
   769  
   770  // Limit the number of concurrent cgo-using goroutines, because
   771  // each will block an entire operating system thread. The usual culprit
   772  // is resolving many DNS names in separate goroutines but the DNS
   773  // server is not responding. Then the many lookups each use a different
   774  // thread, and the system or the program runs out of threads.
   775  
   776  var threadLimit chan struct{}
   777  
   778  var threadOnce sync.Once
   779  
   780  func acquireThread(ctx context.Context) error {
   781  	threadOnce.Do(func() {
   782  		threadLimit = make(chan struct{}, concurrentThreadsLimit())
   783  	})
   784  	select {
   785  	case threadLimit <- struct{}{}:
   786  		return nil
   787  	case <-ctx.Done():
   788  		return ctx.Err()
   789  	}
   790  }
   791  
   792  func releaseThread() {
   793  	<-threadLimit
   794  }
   795  
   796  // buffersWriter is the interface implemented by Conns that support a
   797  // "writev"-like batch write optimization.
   798  // writeBuffers should fully consume and write all chunks from the
   799  // provided Buffers, else it should report a non-nil error.
   800  type buffersWriter interface {
   801  	writeBuffers(*Buffers) (int64, error)
   802  }
   803  
   804  // Buffers contains zero or more runs of bytes to write.
   805  //
   806  // On certain machines, for certain types of connections, this is
   807  // optimized into an OS-specific batch write operation (such as
   808  // "writev").
   809  type Buffers [][]byte
   810  
   811  var (
   812  	_ io.WriterTo = (*Buffers)(nil)
   813  	_ io.Reader   = (*Buffers)(nil)
   814  )
   815  
   816  // WriteTo writes contents of the buffers to w.
   817  //
   818  // WriteTo implements [io.WriterTo] for [Buffers].
   819  //
   820  // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
   821  // but does not modify v[i][j] for any i, j.
   822  func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   823  	if wv, ok := w.(buffersWriter); ok {
   824  		return wv.writeBuffers(v)
   825  	}
   826  	for _, b := range *v {
   827  		nb, err := w.Write(b)
   828  		n += int64(nb)
   829  		if err != nil {
   830  			v.consume(n)
   831  			return n, err
   832  		}
   833  	}
   834  	v.consume(n)
   835  	return n, nil
   836  }
   837  
   838  // Read from the buffers.
   839  //
   840  // Read implements [io.Reader] for [Buffers].
   841  //
   842  // Read modifies the slice v as well as v[i] for 0 <= i < len(v),
   843  // but does not modify v[i][j] for any i, j.
   844  func (v *Buffers) Read(p []byte) (n int, err error) {
   845  	for len(p) > 0 && len(*v) > 0 {
   846  		n0 := copy(p, (*v)[0])
   847  		v.consume(int64(n0))
   848  		p = p[n0:]
   849  		n += n0
   850  	}
   851  	if len(*v) == 0 {
   852  		err = io.EOF
   853  	}
   854  	return
   855  }
   856  
   857  func (v *Buffers) consume(n int64) {
   858  	for len(*v) > 0 {
   859  		ln0 := int64(len((*v)[0]))
   860  		if ln0 > n {
   861  			(*v)[0] = (*v)[0][n:]
   862  			return
   863  		}
   864  		n -= ln0
   865  		(*v)[0] = nil
   866  		*v = (*v)[1:]
   867  	}
   868  }
   869  

View as plain text