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

View as plain text