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

View as plain text