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  The netgo build tag disables entirely the use of the native (CGO) resolver,
    72  meaning the Go resolver is the only one that can be used.
    73  With the netcgo build tag the native and the pure Go resolver are compiled into the binary,
    74  but the native (CGO) resolver is preferred over the Go resolver.
    75  With netcgo, the Go resolver can still be forced at runtime with GODEBUG=netdns=go.
    76  
    77  A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver
    78  to print debugging information about its decisions.
    79  To force a particular resolver while also printing debugging information,
    80  join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
    81  
    82  The Go resolver will send an EDNS0 additional header with a DNS request,
    83  to signal a willingness to accept a larger DNS packet size.
    84  This can reportedly cause sporadic failures with the DNS server run
    85  by some modems and routers. Setting GODEBUG=netedns0=0 will disable
    86  sending the additional header.
    87  
    88  On macOS, if Go code that uses the net package is built with
    89  -buildmode=c-archive, linking the resulting archive into a C program
    90  requires passing -lresolv when linking the C code.
    91  
    92  On Plan 9, the resolver always accesses /net/cs and /net/dns.
    93  
    94  On Windows, in Go 1.18.x and earlier, the resolver always used C
    95  library functions, such as GetAddrInfo and DnsQuery.
    96  */
    97  package net
    98  
    99  import (
   100  	"context"
   101  	"errors"
   102  	"internal/poll"
   103  	"io"
   104  	"os"
   105  	"sync"
   106  	"syscall"
   107  	"time"
   108  	_ "unsafe" // for linkname
   109  )
   110  
   111  // Addr represents a network end point address.
   112  //
   113  // The two methods [Addr.Network] and [Addr.String] conventionally return strings
   114  // that can be passed as the arguments to [Dial], but the exact form
   115  // and meaning of the strings is up to the implementation.
   116  type Addr interface {
   117  	Network() string // name of the network (for example, "tcp", "udp")
   118  	String() string  // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
   119  }
   120  
   121  // Conn is a generic stream-oriented network connection.
   122  //
   123  // Multiple goroutines may invoke methods on a Conn simultaneously.
   124  type Conn interface {
   125  	// Read reads data from the connection.
   126  	// Read can be made to time out and return an error after a fixed
   127  	// time limit; see SetDeadline and SetReadDeadline.
   128  	Read(b []byte) (n int, err error)
   129  
   130  	// Write writes data to the connection.
   131  	// Write can be made to time out and return an error after a fixed
   132  	// time limit; see SetDeadline and SetWriteDeadline.
   133  	Write(b []byte) (n int, err error)
   134  
   135  	// Close closes the connection.
   136  	// Any blocked Read or Write operations will be unblocked and return errors.
   137  	Close() error
   138  
   139  	// LocalAddr returns the local network address, if known.
   140  	LocalAddr() Addr
   141  
   142  	// RemoteAddr returns the remote network address, if known.
   143  	RemoteAddr() Addr
   144  
   145  	// SetDeadline sets the read and write deadlines associated
   146  	// with the connection. It is equivalent to calling both
   147  	// SetReadDeadline and SetWriteDeadline.
   148  	//
   149  	// A deadline is an absolute time after which I/O operations
   150  	// fail instead of blocking. The deadline applies to all future
   151  	// and pending I/O, not just the immediately following call to
   152  	// Read or Write. After a deadline has been exceeded, the
   153  	// connection can be refreshed by setting a deadline in the future.
   154  	//
   155  	// If the deadline is exceeded a call to Read or Write or to other
   156  	// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
   157  	// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
   158  	// The error's Timeout method will return true, but note that there
   159  	// are other possible errors for which the Timeout method will
   160  	// return true even if the deadline has not been exceeded.
   161  	//
   162  	// An idle timeout can be implemented by repeatedly extending
   163  	// the deadline after successful Read or Write calls.
   164  	//
   165  	// A zero value for t means I/O operations will not time out.
   166  	SetDeadline(t time.Time) error
   167  
   168  	// SetReadDeadline sets the deadline for future Read calls
   169  	// and any currently-blocked Read call.
   170  	// A zero value for t means Read will not time out.
   171  	SetReadDeadline(t time.Time) error
   172  
   173  	// SetWriteDeadline sets the deadline for future Write calls
   174  	// and any currently-blocked Write call.
   175  	// Even if write times out, it may return n > 0, indicating that
   176  	// some of the data was successfully written.
   177  	// A zero value for t means Write will not time out.
   178  	SetWriteDeadline(t time.Time) error
   179  }
   180  
   181  type conn struct {
   182  	fd *netFD
   183  }
   184  
   185  func (c *conn) ok() bool { return c != nil && c.fd != nil }
   186  
   187  // Implementation of the Conn interface.
   188  
   189  // Read implements the Conn Read method.
   190  func (c *conn) Read(b []byte) (int, error) {
   191  	if !c.ok() {
   192  		return 0, syscall.EINVAL
   193  	}
   194  	n, err := c.fd.Read(b)
   195  	if err != nil && err != io.EOF {
   196  		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   197  	}
   198  	return n, err
   199  }
   200  
   201  // Write implements the Conn Write method.
   202  func (c *conn) Write(b []byte) (int, error) {
   203  	if !c.ok() {
   204  		return 0, syscall.EINVAL
   205  	}
   206  	n, err := c.fd.Write(b)
   207  	if err != nil {
   208  		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   209  	}
   210  	return n, err
   211  }
   212  
   213  // Close closes the connection.
   214  func (c *conn) Close() error {
   215  	if !c.ok() {
   216  		return syscall.EINVAL
   217  	}
   218  	err := c.fd.Close()
   219  	if err != nil {
   220  		err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   221  	}
   222  	return err
   223  }
   224  
   225  // LocalAddr returns the local network address.
   226  // The Addr returned is shared by all invocations of LocalAddr, so
   227  // do not modify it.
   228  func (c *conn) LocalAddr() Addr {
   229  	if !c.ok() {
   230  		return nil
   231  	}
   232  	return c.fd.laddr
   233  }
   234  
   235  // RemoteAddr returns the remote network address.
   236  // The Addr returned is shared by all invocations of RemoteAddr, so
   237  // do not modify it.
   238  func (c *conn) RemoteAddr() Addr {
   239  	if !c.ok() {
   240  		return nil
   241  	}
   242  	return c.fd.raddr
   243  }
   244  
   245  // SetDeadline implements the Conn SetDeadline method.
   246  func (c *conn) SetDeadline(t time.Time) error {
   247  	if !c.ok() {
   248  		return syscall.EINVAL
   249  	}
   250  	if err := c.fd.SetDeadline(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  // SetReadDeadline implements the Conn SetReadDeadline method.
   257  func (c *conn) SetReadDeadline(t time.Time) error {
   258  	if !c.ok() {
   259  		return syscall.EINVAL
   260  	}
   261  	if err := c.fd.SetReadDeadline(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  // SetWriteDeadline implements the Conn SetWriteDeadline method.
   268  func (c *conn) SetWriteDeadline(t time.Time) error {
   269  	if !c.ok() {
   270  		return syscall.EINVAL
   271  	}
   272  	if err := c.fd.SetWriteDeadline(t); 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  // SetReadBuffer sets the size of the operating system's
   279  // receive buffer associated with the connection.
   280  func (c *conn) SetReadBuffer(bytes int) error {
   281  	if !c.ok() {
   282  		return syscall.EINVAL
   283  	}
   284  	if err := setReadBuffer(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  // SetWriteBuffer sets the size of the operating system's
   291  // transmit buffer associated with the connection.
   292  func (c *conn) SetWriteBuffer(bytes int) error {
   293  	if !c.ok() {
   294  		return syscall.EINVAL
   295  	}
   296  	if err := setWriteBuffer(c.fd, bytes); err != nil {
   297  		return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
   298  	}
   299  	return nil
   300  }
   301  
   302  // File returns a copy of the underlying [os.File].
   303  // It is the caller's responsibility to close f when finished.
   304  // Closing c does not affect f, and closing f does not affect c.
   305  //
   306  // The returned os.File's file descriptor is different from the connection's.
   307  // Attempting to change properties of the original using this duplicate
   308  // may or may not have the desired effect.
   309  func (c *conn) File() (f *os.File, err error) {
   310  	f, err = c.fd.dup()
   311  	if err != nil {
   312  		err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   313  	}
   314  	return
   315  }
   316  
   317  // PacketConn is a generic packet-oriented network connection.
   318  //
   319  // Multiple goroutines may invoke methods on a PacketConn simultaneously.
   320  type PacketConn interface {
   321  	// ReadFrom reads a packet from the connection,
   322  	// copying the payload into p. It returns the number of
   323  	// bytes copied into p and the return address that
   324  	// was on the packet.
   325  	// It returns the number of bytes read (0 <= n <= len(p))
   326  	// and any error encountered. Callers should always process
   327  	// the n > 0 bytes returned before considering the error err.
   328  	// ReadFrom can be made to time out and return an error after a
   329  	// fixed time limit; see SetDeadline and SetReadDeadline.
   330  	ReadFrom(p []byte) (n int, addr Addr, err error)
   331  
   332  	// WriteTo writes a packet with payload p to addr.
   333  	// WriteTo can be made to time out and return an Error after a
   334  	// fixed time limit; see SetDeadline and SetWriteDeadline.
   335  	// On packet-oriented connections, write timeouts are rare.
   336  	WriteTo(p []byte, addr Addr) (n int, err error)
   337  
   338  	// Close closes the connection.
   339  	// Any blocked ReadFrom or WriteTo operations will be unblocked and return errors.
   340  	Close() error
   341  
   342  	// LocalAddr returns the local network address, if known.
   343  	LocalAddr() Addr
   344  
   345  	// SetDeadline sets the read and write deadlines associated
   346  	// with the connection. It is equivalent to calling both
   347  	// SetReadDeadline and SetWriteDeadline.
   348  	//
   349  	// A deadline is an absolute time after which I/O operations
   350  	// fail instead of blocking. The deadline applies to all future
   351  	// and pending I/O, not just the immediately following call to
   352  	// Read or Write. After a deadline has been exceeded, the
   353  	// connection can be refreshed by setting a deadline in the future.
   354  	//
   355  	// If the deadline is exceeded a call to Read or Write or to other
   356  	// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
   357  	// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
   358  	// The error's Timeout method will return true, but note that there
   359  	// are other possible errors for which the Timeout method will
   360  	// return true even if the deadline has not been exceeded.
   361  	//
   362  	// An idle timeout can be implemented by repeatedly extending
   363  	// the deadline after successful ReadFrom or WriteTo calls.
   364  	//
   365  	// A zero value for t means I/O operations will not time out.
   366  	SetDeadline(t time.Time) error
   367  
   368  	// SetReadDeadline sets the deadline for future ReadFrom calls
   369  	// and any currently-blocked ReadFrom call.
   370  	// A zero value for t means ReadFrom will not time out.
   371  	SetReadDeadline(t time.Time) error
   372  
   373  	// SetWriteDeadline sets the deadline for future WriteTo calls
   374  	// and any currently-blocked WriteTo call.
   375  	// Even if write times out, it may return n > 0, indicating that
   376  	// some of the data was successfully written.
   377  	// A zero value for t means WriteTo will not time out.
   378  	SetWriteDeadline(t time.Time) error
   379  }
   380  
   381  var listenerBacklogCache struct {
   382  	sync.Once
   383  	val int
   384  }
   385  
   386  // listenerBacklog is a caching wrapper around maxListenerBacklog.
   387  //
   388  // listenerBacklog should be an internal detail,
   389  // but widely used packages access it using linkname.
   390  // Notable members of the hall of shame include:
   391  //   - github.com/database64128/tfo-go/v2
   392  //   - github.com/metacubex/tfo-go
   393  //   - github.com/sagernet/tfo-go
   394  //
   395  // Do not remove or change the type signature.
   396  // See go.dev/issue/67401.
   397  //
   398  //go:linkname listenerBacklog
   399  func listenerBacklog() int {
   400  	listenerBacklogCache.Do(func() { listenerBacklogCache.val = maxListenerBacklog() })
   401  	return listenerBacklogCache.val
   402  }
   403  
   404  // A Listener is a generic network listener for stream-oriented protocols.
   405  //
   406  // Multiple goroutines may invoke methods on a Listener simultaneously.
   407  type Listener interface {
   408  	// Accept waits for and returns the next connection to the listener.
   409  	Accept() (Conn, error)
   410  
   411  	// Close closes the listener.
   412  	// Any blocked Accept operations will be unblocked and return errors.
   413  	Close() error
   414  
   415  	// Addr returns the listener's network address.
   416  	Addr() Addr
   417  }
   418  
   419  // An Error represents a network error.
   420  type Error interface {
   421  	error
   422  	Timeout() bool // Is the error a timeout?
   423  
   424  	// Deprecated: Temporary errors are not well-defined.
   425  	// Most "temporary" errors are timeouts, and the few exceptions are surprising.
   426  	// Do not use this method.
   427  	Temporary() bool
   428  }
   429  
   430  // Various errors contained in OpError.
   431  var (
   432  	// For connection setup operations.
   433  	errNoSuitableAddress = errors.New("no suitable address found")
   434  
   435  	// For connection setup and write operations.
   436  	errMissingAddress = errors.New("missing address")
   437  
   438  	// For both read and write operations.
   439  	errCanceled         = canceledError{}
   440  	ErrWriteToConnected = errors.New("use of WriteTo with pre-connected connection")
   441  )
   442  
   443  // canceledError lets us return the same error string we have always
   444  // returned, while still being Is context.Canceled.
   445  type canceledError struct{}
   446  
   447  func (canceledError) Error() string { return "operation was canceled" }
   448  
   449  func (canceledError) Is(err error) bool { return err == context.Canceled }
   450  
   451  // mapErr maps from the context errors to the historical internal net
   452  // error values.
   453  func mapErr(err error) error {
   454  	switch err {
   455  	case context.Canceled:
   456  		return errCanceled
   457  	case context.DeadlineExceeded:
   458  		return errTimeout
   459  	default:
   460  		return err
   461  	}
   462  }
   463  
   464  // OpError is the error type usually returned by functions in the net
   465  // package. It describes the operation, network type, and address of
   466  // an error.
   467  type OpError struct {
   468  	// Op is the operation which caused the error, such as
   469  	// "read" or "write".
   470  	Op string
   471  
   472  	// Net is the network type on which this error occurred,
   473  	// such as "tcp" or "udp6".
   474  	Net string
   475  
   476  	// For operations involving a remote network connection, like
   477  	// Dial, Read, or Write, Source is the corresponding local
   478  	// network address.
   479  	Source Addr
   480  
   481  	// Addr is the network address for which this error occurred.
   482  	// For local operations, like Listen or SetDeadline, Addr is
   483  	// the address of the local endpoint being manipulated.
   484  	// For operations involving a remote network connection, like
   485  	// Dial, Read, or Write, Addr is the remote address of that
   486  	// connection.
   487  	Addr Addr
   488  
   489  	// Err is the error that occurred during the operation.
   490  	// The Error method panics if the error is nil.
   491  	Err error
   492  }
   493  
   494  func (e *OpError) Unwrap() error { return e.Err }
   495  
   496  func (e *OpError) Error() string {
   497  	if e == nil {
   498  		return "<nil>"
   499  	}
   500  	s := e.Op
   501  	if e.Net != "" {
   502  		s += " " + e.Net
   503  	}
   504  	if e.Source != nil {
   505  		s += " " + e.Source.String()
   506  	}
   507  	if e.Addr != nil {
   508  		if e.Source != nil {
   509  			s += "->"
   510  		} else {
   511  			s += " "
   512  		}
   513  		s += e.Addr.String()
   514  	}
   515  	s += ": " + e.Err.Error()
   516  	return s
   517  }
   518  
   519  var (
   520  	// aLongTimeAgo is a non-zero time, far in the past, used for
   521  	// immediate cancellation of dials.
   522  	aLongTimeAgo = time.Unix(1, 0)
   523  
   524  	// noDeadline and noCancel are just zero values for
   525  	// readability with functions taking too many parameters.
   526  	noDeadline = time.Time{}
   527  	noCancel   = (chan struct{})(nil)
   528  )
   529  
   530  type timeout interface {
   531  	Timeout() bool
   532  }
   533  
   534  func (e *OpError) Timeout() bool {
   535  	if ne, ok := e.Err.(*os.SyscallError); ok {
   536  		t, ok := ne.Err.(timeout)
   537  		return ok && t.Timeout()
   538  	}
   539  	t, ok := e.Err.(timeout)
   540  	return ok && t.Timeout()
   541  }
   542  
   543  type temporary interface {
   544  	Temporary() bool
   545  }
   546  
   547  func (e *OpError) Temporary() bool {
   548  	// Treat ECONNRESET and ECONNABORTED as temporary errors when
   549  	// they come from calling accept. See issue 6163.
   550  	if e.Op == "accept" && isConnError(e.Err) {
   551  		return true
   552  	}
   553  
   554  	if ne, ok := e.Err.(*os.SyscallError); ok {
   555  		t, ok := ne.Err.(temporary)
   556  		return ok && t.Temporary()
   557  	}
   558  	t, ok := e.Err.(temporary)
   559  	return ok && t.Temporary()
   560  }
   561  
   562  // A ParseError is the error type of literal network address parsers.
   563  type ParseError struct {
   564  	// Type is the type of string that was expected, such as
   565  	// "IP address", "CIDR address".
   566  	Type string
   567  
   568  	// Text is the malformed text string.
   569  	Text string
   570  }
   571  
   572  func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
   573  
   574  func (e *ParseError) Timeout() bool   { return false }
   575  func (e *ParseError) Temporary() bool { return false }
   576  
   577  type AddrError struct {
   578  	Err  string
   579  	Addr string
   580  }
   581  
   582  func (e *AddrError) Error() string {
   583  	if e == nil {
   584  		return "<nil>"
   585  	}
   586  	s := e.Err
   587  	if e.Addr != "" {
   588  		s = "address " + e.Addr + ": " + s
   589  	}
   590  	return s
   591  }
   592  
   593  func (e *AddrError) Timeout() bool   { return false }
   594  func (e *AddrError) Temporary() bool { return false }
   595  
   596  type UnknownNetworkError string
   597  
   598  func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
   599  func (e UnknownNetworkError) Timeout() bool   { return false }
   600  func (e UnknownNetworkError) Temporary() bool { return false }
   601  
   602  type InvalidAddrError string
   603  
   604  func (e InvalidAddrError) Error() string   { return string(e) }
   605  func (e InvalidAddrError) Timeout() bool   { return false }
   606  func (e InvalidAddrError) Temporary() bool { return false }
   607  
   608  // errTimeout exists to return the historical "i/o timeout" string
   609  // for context.DeadlineExceeded. See mapErr.
   610  // It is also used when Dialer.Deadline is exceeded.
   611  // error.Is(errTimeout, context.DeadlineExceeded) returns true.
   612  //
   613  // TODO(iant): We could consider changing this to os.ErrDeadlineExceeded
   614  // in the future, if we make
   615  //
   616  //	errors.Is(os.ErrDeadlineExceeded, context.DeadlineExceeded)
   617  //
   618  // return true.
   619  var errTimeout error = &timeoutError{}
   620  
   621  type timeoutError struct{}
   622  
   623  func (e *timeoutError) Error() string   { return "i/o timeout" }
   624  func (e *timeoutError) Timeout() bool   { return true }
   625  func (e *timeoutError) Temporary() bool { return true }
   626  
   627  func (e *timeoutError) Is(err error) bool {
   628  	return err == context.DeadlineExceeded
   629  }
   630  
   631  // DNSConfigError represents an error reading the machine's DNS configuration.
   632  // (No longer used; kept for compatibility.)
   633  type DNSConfigError struct {
   634  	Err error
   635  }
   636  
   637  func (e *DNSConfigError) Unwrap() error   { return e.Err }
   638  func (e *DNSConfigError) Error() string   { return "error reading DNS config: " + e.Err.Error() }
   639  func (e *DNSConfigError) Timeout() bool   { return false }
   640  func (e *DNSConfigError) Temporary() bool { return false }
   641  
   642  // Various errors contained in DNSError.
   643  var (
   644  	errNoSuchHost  = &notFoundError{"no such host"}
   645  	errUnknownPort = &notFoundError{"unknown port"}
   646  )
   647  
   648  // notFoundError is a special error understood by the newDNSError function,
   649  // which causes a creation of a DNSError with IsNotFound field set to true.
   650  type notFoundError struct{ s string }
   651  
   652  func (e *notFoundError) Error() string { return e.s }
   653  
   654  // temporaryError is an error type that implements the [Error] interface.
   655  // It returns true from the Temporary method.
   656  type temporaryError struct{ s string }
   657  
   658  func (e *temporaryError) Error() string   { return e.s }
   659  func (e *temporaryError) Temporary() bool { return true }
   660  func (e *temporaryError) Timeout() bool   { return false }
   661  
   662  // DNSError represents a DNS lookup error.
   663  type DNSError struct {
   664  	UnwrapErr   error  // error returned by the [DNSError.Unwrap] method, might be nil
   665  	Err         string // description of the error
   666  	Name        string // name looked for
   667  	Server      string // server used
   668  	IsTimeout   bool   // if true, timed out; not all timeouts set this
   669  	IsTemporary bool   // if true, error is temporary; not all errors set this
   670  
   671  	// IsNotFound is set to true when the requested name does not
   672  	// contain any records of the requested type (data not found),
   673  	// or the name itself was not found (NXDOMAIN).
   674  	IsNotFound bool
   675  }
   676  
   677  // newDNSError creates a new *DNSError.
   678  // Based on the err, it sets the UnwrapErr, IsTimeout, IsTemporary, IsNotFound fields.
   679  func newDNSError(err error, name, server string) *DNSError {
   680  	var (
   681  		isTimeout   bool
   682  		isTemporary bool
   683  		unwrapErr   error
   684  	)
   685  
   686  	if err, ok := err.(Error); ok {
   687  		isTimeout = err.Timeout()
   688  		isTemporary = err.Temporary()
   689  	}
   690  
   691  	// At this time, the only errors we wrap are context errors, to allow
   692  	// users to check for canceled/timed out requests.
   693  	if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
   694  		unwrapErr = err
   695  	}
   696  
   697  	_, isNotFound := err.(*notFoundError)
   698  	return &DNSError{
   699  		UnwrapErr:   unwrapErr,
   700  		Err:         err.Error(),
   701  		Name:        name,
   702  		Server:      server,
   703  		IsTimeout:   isTimeout,
   704  		IsTemporary: isTemporary,
   705  		IsNotFound:  isNotFound,
   706  	}
   707  }
   708  
   709  // Unwrap returns e.UnwrapErr.
   710  func (e *DNSError) Unwrap() error { return e.UnwrapErr }
   711  
   712  func (e *DNSError) Error() string {
   713  	if e == nil {
   714  		return "<nil>"
   715  	}
   716  	s := "lookup " + e.Name
   717  	if e.Server != "" {
   718  		s += " on " + e.Server
   719  	}
   720  	s += ": " + e.Err
   721  	return s
   722  }
   723  
   724  // Timeout reports whether the DNS lookup is known to have timed out.
   725  // This is not always known; a DNS lookup may fail due to a timeout
   726  // and return a [DNSError] for which Timeout returns false.
   727  func (e *DNSError) Timeout() bool { return e.IsTimeout }
   728  
   729  // Temporary reports whether the DNS error is known to be temporary.
   730  // This is not always known; a DNS lookup may fail due to a temporary
   731  // error and return a [DNSError] for which Temporary returns false.
   732  func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
   733  
   734  // errClosed exists just so that the docs for ErrClosed don't mention
   735  // the internal package poll.
   736  var errClosed = poll.ErrNetClosing
   737  
   738  // ErrClosed is the error returned by an I/O call on a network
   739  // connection that has already been closed, or that is closed by
   740  // another goroutine before the I/O is completed. This may be wrapped
   741  // in another error, and should normally be tested using
   742  // errors.Is(err, net.ErrClosed).
   743  var ErrClosed error = errClosed
   744  
   745  // noReadFrom can be embedded alongside another type to
   746  // hide the ReadFrom method of that other type.
   747  type noReadFrom struct{}
   748  
   749  // ReadFrom hides another ReadFrom method.
   750  // It should never be called.
   751  func (noReadFrom) ReadFrom(io.Reader) (int64, error) {
   752  	panic("can't happen")
   753  }
   754  
   755  // tcpConnWithoutReadFrom implements all the methods of *TCPConn other
   756  // than ReadFrom. This is used to permit ReadFrom to call io.Copy
   757  // without leading to a recursive call to ReadFrom.
   758  type tcpConnWithoutReadFrom struct {
   759  	noReadFrom
   760  	*TCPConn
   761  }
   762  
   763  // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
   764  // applicable.
   765  func genericReadFrom(c *TCPConn, r io.Reader) (n int64, err error) {
   766  	// Use wrapper to hide existing r.ReadFrom from io.Copy.
   767  	return io.Copy(tcpConnWithoutReadFrom{TCPConn: c}, r)
   768  }
   769  
   770  // noWriteTo can be embedded alongside another type to
   771  // hide the WriteTo method of that other type.
   772  type noWriteTo struct{}
   773  
   774  // WriteTo hides another WriteTo method.
   775  // It should never be called.
   776  func (noWriteTo) WriteTo(io.Writer) (int64, error) {
   777  	panic("can't happen")
   778  }
   779  
   780  // tcpConnWithoutWriteTo implements all the methods of *TCPConn other
   781  // than WriteTo. This is used to permit WriteTo to call io.Copy
   782  // without leading to a recursive call to WriteTo.
   783  type tcpConnWithoutWriteTo struct {
   784  	noWriteTo
   785  	*TCPConn
   786  }
   787  
   788  // Fallback implementation of io.WriterTo's WriteTo, when zero-copy isn't applicable.
   789  func genericWriteTo(c *TCPConn, w io.Writer) (n int64, err error) {
   790  	// Use wrapper to hide existing w.WriteTo from io.Copy.
   791  	return io.Copy(w, tcpConnWithoutWriteTo{TCPConn: c})
   792  }
   793  
   794  // Limit the number of concurrent cgo-using goroutines, because
   795  // each will block an entire operating system thread. The usual culprit
   796  // is resolving many DNS names in separate goroutines but the DNS
   797  // server is not responding. Then the many lookups each use a different
   798  // thread, and the system or the program runs out of threads.
   799  
   800  var threadLimit chan struct{}
   801  
   802  var threadOnce sync.Once
   803  
   804  func acquireThread(ctx context.Context) error {
   805  	threadOnce.Do(func() {
   806  		threadLimit = make(chan struct{}, concurrentThreadsLimit())
   807  	})
   808  	select {
   809  	case threadLimit <- struct{}{}:
   810  		return nil
   811  	case <-ctx.Done():
   812  		return ctx.Err()
   813  	}
   814  }
   815  
   816  func releaseThread() {
   817  	<-threadLimit
   818  }
   819  
   820  // buffersWriter is the interface implemented by Conns that support a
   821  // "writev"-like batch write optimization.
   822  // writeBuffers should fully consume and write all chunks from the
   823  // provided Buffers, else it should report a non-nil error.
   824  type buffersWriter interface {
   825  	writeBuffers(*Buffers) (int64, error)
   826  }
   827  
   828  // Buffers contains zero or more runs of bytes to write.
   829  //
   830  // On certain machines, for certain types of connections, this is
   831  // optimized into an OS-specific batch write operation (such as
   832  // "writev").
   833  type Buffers [][]byte
   834  
   835  var (
   836  	_ io.WriterTo = (*Buffers)(nil)
   837  	_ io.Reader   = (*Buffers)(nil)
   838  )
   839  
   840  // WriteTo writes contents of the buffers to w.
   841  //
   842  // WriteTo implements [io.WriterTo] for [Buffers].
   843  //
   844  // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
   845  // but does not modify v[i][j] for any i, j.
   846  func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
   847  	if wv, ok := w.(buffersWriter); ok {
   848  		return wv.writeBuffers(v)
   849  	}
   850  	for _, b := range *v {
   851  		nb, err := w.Write(b)
   852  		n += int64(nb)
   853  		if err != nil {
   854  			v.consume(n)
   855  			return n, err
   856  		}
   857  	}
   858  	v.consume(n)
   859  	return n, nil
   860  }
   861  
   862  // Read from the buffers.
   863  //
   864  // Read implements [io.Reader] for [Buffers].
   865  //
   866  // Read modifies the slice v as well as v[i] for 0 <= i < len(v),
   867  // but does not modify v[i][j] for any i, j.
   868  func (v *Buffers) Read(p []byte) (n int, err error) {
   869  	for len(p) > 0 && len(*v) > 0 {
   870  		n0 := copy(p, (*v)[0])
   871  		v.consume(int64(n0))
   872  		p = p[n0:]
   873  		n += n0
   874  	}
   875  	if len(*v) == 0 {
   876  		err = io.EOF
   877  	}
   878  	return
   879  }
   880  
   881  func (v *Buffers) consume(n int64) {
   882  	for len(*v) > 0 {
   883  		ln0 := int64(len((*v)[0]))
   884  		if ln0 > n {
   885  			(*v)[0] = (*v)[0][n:]
   886  			return
   887  		}
   888  		n -= ln0
   889  		(*v)[0] = nil
   890  		*v = (*v)[1:]
   891  	}
   892  }
   893  

View as plain text