Source file src/net/dial.go

     1  // Copyright 2010 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  package net
     6  
     7  import (
     8  	"context"
     9  	"internal/bytealg"
    10  	"internal/godebug"
    11  	"internal/nettrace"
    12  	"syscall"
    13  	"time"
    14  )
    15  
    16  const (
    17  	// defaultTCPKeepAliveIdle is a default constant value for TCP_KEEPIDLE.
    18  	// See go.dev/issue/31510 for details.
    19  	defaultTCPKeepAliveIdle = 15 * time.Second
    20  
    21  	// defaultTCPKeepAliveInterval is a default constant value for TCP_KEEPINTVL.
    22  	// It is the same as defaultTCPKeepAliveIdle, see go.dev/issue/31510 for details.
    23  	defaultTCPKeepAliveInterval = 15 * time.Second
    24  
    25  	// defaultTCPKeepAliveCount is a default constant value for TCP_KEEPCNT.
    26  	defaultTCPKeepAliveCount = 9
    27  
    28  	// For the moment, MultiPath TCP is not used by default
    29  	// See go.dev/issue/56539
    30  	defaultMPTCPEnabled = false
    31  )
    32  
    33  var multipathtcp = godebug.New("multipathtcp")
    34  
    35  // mptcpStatus is a tristate for Multipath TCP, see go.dev/issue/56539
    36  type mptcpStatus uint8
    37  
    38  const (
    39  	// The value 0 is the system default, linked to defaultMPTCPEnabled
    40  	mptcpUseDefault mptcpStatus = iota
    41  	mptcpEnabled
    42  	mptcpDisabled
    43  )
    44  
    45  func (m *mptcpStatus) get() bool {
    46  	switch *m {
    47  	case mptcpEnabled:
    48  		return true
    49  	case mptcpDisabled:
    50  		return false
    51  	}
    52  
    53  	// If MPTCP is forced via GODEBUG=multipathtcp=1
    54  	if multipathtcp.Value() == "1" {
    55  		multipathtcp.IncNonDefault()
    56  
    57  		return true
    58  	}
    59  
    60  	return defaultMPTCPEnabled
    61  }
    62  
    63  func (m *mptcpStatus) set(use bool) {
    64  	if use {
    65  		*m = mptcpEnabled
    66  	} else {
    67  		*m = mptcpDisabled
    68  	}
    69  }
    70  
    71  // A Dialer contains options for connecting to an address.
    72  //
    73  // The zero value for each field is equivalent to dialing
    74  // without that option. Dialing with the zero value of Dialer
    75  // is therefore equivalent to just calling the [Dial] function.
    76  //
    77  // It is safe to call Dialer's methods concurrently.
    78  type Dialer struct {
    79  	// Timeout is the maximum amount of time a dial will wait for
    80  	// a connect to complete. If Deadline is also set, it may fail
    81  	// earlier.
    82  	//
    83  	// The default is no timeout.
    84  	//
    85  	// When using TCP and dialing a host name with multiple IP
    86  	// addresses, the timeout may be divided between them.
    87  	//
    88  	// With or without a timeout, the operating system may impose
    89  	// its own earlier timeout. For instance, TCP timeouts are
    90  	// often around 3 minutes.
    91  	Timeout time.Duration
    92  
    93  	// Deadline is the absolute point in time after which dials
    94  	// will fail. If Timeout is set, it may fail earlier.
    95  	// Zero means no deadline, or dependent on the operating system
    96  	// as with the Timeout option.
    97  	Deadline time.Time
    98  
    99  	// LocalAddr is the local address to use when dialing an
   100  	// address. The address must be of a compatible type for the
   101  	// network being dialed.
   102  	// If nil, a local address is automatically chosen.
   103  	LocalAddr Addr
   104  
   105  	// DualStack previously enabled RFC 6555 Fast Fallback
   106  	// support, also known as "Happy Eyeballs", in which IPv4 is
   107  	// tried soon if IPv6 appears to be misconfigured and
   108  	// hanging.
   109  	//
   110  	// Deprecated: Fast Fallback is enabled by default. To
   111  	// disable, set FallbackDelay to a negative value.
   112  	DualStack bool
   113  
   114  	// FallbackDelay specifies the length of time to wait before
   115  	// spawning a RFC 6555 Fast Fallback connection. That is, this
   116  	// is the amount of time to wait for IPv6 to succeed before
   117  	// assuming that IPv6 is misconfigured and falling back to
   118  	// IPv4.
   119  	//
   120  	// If zero, a default delay of 300ms is used.
   121  	// A negative value disables Fast Fallback support.
   122  	FallbackDelay time.Duration
   123  
   124  	// KeepAlive specifies the interval between keep-alive
   125  	// probes for an active network connection.
   126  	//
   127  	// KeepAlive is ignored if KeepAliveConfig.Enable is true.
   128  	//
   129  	// If zero, keep-alive probes are sent with a default value
   130  	// (currently 15 seconds), if supported by the protocol and operating
   131  	// system. Network protocols or operating systems that do
   132  	// not support keep-alive ignore this field.
   133  	// If negative, keep-alive probes are disabled.
   134  	KeepAlive time.Duration
   135  
   136  	// KeepAliveConfig specifies the keep-alive probe configuration
   137  	// for an active network connection, when supported by the
   138  	// protocol and operating system.
   139  	//
   140  	// If KeepAliveConfig.Enable is true, keep-alive probes are enabled.
   141  	// If KeepAliveConfig.Enable is false and KeepAlive is negative,
   142  	// keep-alive probes are disabled.
   143  	KeepAliveConfig KeepAliveConfig
   144  
   145  	// Resolver optionally specifies an alternate resolver to use.
   146  	Resolver *Resolver
   147  
   148  	// Cancel is an optional channel whose closure indicates that
   149  	// the dial should be canceled. Not all types of dials support
   150  	// cancellation.
   151  	//
   152  	// Deprecated: Use DialContext instead.
   153  	Cancel <-chan struct{}
   154  
   155  	// If Control is not nil, it is called after creating the network
   156  	// connection but before actually dialing.
   157  	//
   158  	// Network and address parameters passed to Control function are not
   159  	// necessarily the ones passed to Dial. For example, passing "tcp" to Dial
   160  	// will cause the Control function to be called with "tcp4" or "tcp6".
   161  	//
   162  	// Control is ignored if ControlContext is not nil.
   163  	Control func(network, address string, c syscall.RawConn) error
   164  
   165  	// If ControlContext is not nil, it is called after creating the network
   166  	// connection but before actually dialing.
   167  	//
   168  	// Network and address parameters passed to ControlContext function are not
   169  	// necessarily the ones passed to Dial. For example, passing "tcp" to Dial
   170  	// will cause the ControlContext function to be called with "tcp4" or "tcp6".
   171  	//
   172  	// If ControlContext is not nil, Control is ignored.
   173  	ControlContext func(ctx context.Context, network, address string, c syscall.RawConn) error
   174  
   175  	// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
   176  	// used, any call to Dial with "tcp(4|6)" as network will use MPTCP if
   177  	// supported by the operating system.
   178  	mptcpStatus mptcpStatus
   179  }
   180  
   181  func (d *Dialer) dualStack() bool { return d.FallbackDelay >= 0 }
   182  
   183  func minNonzeroTime(a, b time.Time) time.Time {
   184  	if a.IsZero() {
   185  		return b
   186  	}
   187  	if b.IsZero() || a.Before(b) {
   188  		return a
   189  	}
   190  	return b
   191  }
   192  
   193  // deadline returns the earliest of:
   194  //   - now+Timeout
   195  //   - d.Deadline
   196  //   - the context's deadline
   197  //
   198  // Or zero, if none of Timeout, Deadline, or context's deadline is set.
   199  func (d *Dialer) deadline(ctx context.Context, now time.Time) (earliest time.Time) {
   200  	if d.Timeout != 0 { // including negative, for historical reasons
   201  		earliest = now.Add(d.Timeout)
   202  	}
   203  	if d, ok := ctx.Deadline(); ok {
   204  		earliest = minNonzeroTime(earliest, d)
   205  	}
   206  	return minNonzeroTime(earliest, d.Deadline)
   207  }
   208  
   209  func (d *Dialer) resolver() *Resolver {
   210  	if d.Resolver != nil {
   211  		return d.Resolver
   212  	}
   213  	return DefaultResolver
   214  }
   215  
   216  // partialDeadline returns the deadline to use for a single address,
   217  // when multiple addresses are pending.
   218  func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
   219  	if deadline.IsZero() {
   220  		return deadline, nil
   221  	}
   222  	timeRemaining := deadline.Sub(now)
   223  	if timeRemaining <= 0 {
   224  		return time.Time{}, errTimeout
   225  	}
   226  	// Tentatively allocate equal time to each remaining address.
   227  	timeout := timeRemaining / time.Duration(addrsRemaining)
   228  	// If the time per address is too short, steal from the end of the list.
   229  	const saneMinimum = 2 * time.Second
   230  	if timeout < saneMinimum {
   231  		if timeRemaining < saneMinimum {
   232  			timeout = timeRemaining
   233  		} else {
   234  			timeout = saneMinimum
   235  		}
   236  	}
   237  	return now.Add(timeout), nil
   238  }
   239  
   240  func (d *Dialer) fallbackDelay() time.Duration {
   241  	if d.FallbackDelay > 0 {
   242  		return d.FallbackDelay
   243  	} else {
   244  		return 300 * time.Millisecond
   245  	}
   246  }
   247  
   248  func parseNetwork(ctx context.Context, network string, needsProto bool) (afnet string, proto int, err error) {
   249  	i := bytealg.LastIndexByteString(network, ':')
   250  	if i < 0 { // no colon
   251  		switch network {
   252  		case "tcp", "tcp4", "tcp6":
   253  		case "udp", "udp4", "udp6":
   254  		case "ip", "ip4", "ip6":
   255  			if needsProto {
   256  				return "", 0, UnknownNetworkError(network)
   257  			}
   258  		case "unix", "unixgram", "unixpacket":
   259  		default:
   260  			return "", 0, UnknownNetworkError(network)
   261  		}
   262  		return network, 0, nil
   263  	}
   264  	afnet = network[:i]
   265  	switch afnet {
   266  	case "ip", "ip4", "ip6":
   267  		protostr := network[i+1:]
   268  		proto, i, ok := dtoi(protostr)
   269  		if !ok || i != len(protostr) {
   270  			proto, err = lookupProtocol(ctx, protostr)
   271  			if err != nil {
   272  				return "", 0, err
   273  			}
   274  		}
   275  		return afnet, proto, nil
   276  	}
   277  	return "", 0, UnknownNetworkError(network)
   278  }
   279  
   280  // resolveAddrList resolves addr using hint and returns a list of
   281  // addresses. The result contains at least one address when error is
   282  // nil.
   283  func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) {
   284  	afnet, _, err := parseNetwork(ctx, network, true)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	if op == "dial" && addr == "" {
   289  		return nil, errMissingAddress
   290  	}
   291  	switch afnet {
   292  	case "unix", "unixgram", "unixpacket":
   293  		addr, err := ResolveUnixAddr(afnet, addr)
   294  		if err != nil {
   295  			return nil, err
   296  		}
   297  		if op == "dial" && hint != nil && addr.Network() != hint.Network() {
   298  			return nil, &AddrError{Err: "mismatched local address type", Addr: hint.String()}
   299  		}
   300  		return addrList{addr}, nil
   301  	}
   302  	addrs, err := r.internetAddrList(ctx, afnet, addr)
   303  	if err != nil || op != "dial" || hint == nil {
   304  		return addrs, err
   305  	}
   306  	var (
   307  		tcp      *TCPAddr
   308  		udp      *UDPAddr
   309  		ip       *IPAddr
   310  		wildcard bool
   311  	)
   312  	switch hint := hint.(type) {
   313  	case *TCPAddr:
   314  		tcp = hint
   315  		wildcard = tcp.isWildcard()
   316  	case *UDPAddr:
   317  		udp = hint
   318  		wildcard = udp.isWildcard()
   319  	case *IPAddr:
   320  		ip = hint
   321  		wildcard = ip.isWildcard()
   322  	}
   323  	naddrs := addrs[:0]
   324  	for _, addr := range addrs {
   325  		if addr.Network() != hint.Network() {
   326  			return nil, &AddrError{Err: "mismatched local address type", Addr: hint.String()}
   327  		}
   328  		switch addr := addr.(type) {
   329  		case *TCPAddr:
   330  			if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(tcp.IP) {
   331  				continue
   332  			}
   333  			naddrs = append(naddrs, addr)
   334  		case *UDPAddr:
   335  			if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(udp.IP) {
   336  				continue
   337  			}
   338  			naddrs = append(naddrs, addr)
   339  		case *IPAddr:
   340  			if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(ip.IP) {
   341  				continue
   342  			}
   343  			naddrs = append(naddrs, addr)
   344  		}
   345  	}
   346  	if len(naddrs) == 0 {
   347  		return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: hint.String()}
   348  	}
   349  	return naddrs, nil
   350  }
   351  
   352  // MultipathTCP reports whether MPTCP will be used.
   353  //
   354  // This method doesn't check if MPTCP is supported by the operating
   355  // system or not.
   356  func (d *Dialer) MultipathTCP() bool {
   357  	return d.mptcpStatus.get()
   358  }
   359  
   360  // SetMultipathTCP directs the [Dial] methods to use, or not use, MPTCP,
   361  // if supported by the operating system. This method overrides the
   362  // system default and the GODEBUG=multipathtcp=... setting if any.
   363  //
   364  // If MPTCP is not available on the host or not supported by the server,
   365  // the Dial methods will fall back to TCP.
   366  func (d *Dialer) SetMultipathTCP(use bool) {
   367  	d.mptcpStatus.set(use)
   368  }
   369  
   370  // Dial connects to the address on the named network.
   371  //
   372  // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
   373  // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
   374  // (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
   375  // "unixpacket".
   376  //
   377  // For TCP and UDP networks, the address has the form "host:port".
   378  // The host must be a literal IP address, or a host name that can be
   379  // resolved to IP addresses.
   380  // The port must be a literal port number or a service name.
   381  // If the host is a literal IPv6 address it must be enclosed in square
   382  // brackets, as in "[2001:db8::1]:80" or "[fe80::1%zone]:80".
   383  // The zone specifies the scope of the literal IPv6 address as defined
   384  // in RFC 4007.
   385  // The functions [JoinHostPort] and [SplitHostPort] manipulate a pair of
   386  // host and port in this form.
   387  // When using TCP, and the host resolves to multiple IP addresses,
   388  // Dial will try each IP address in order until one succeeds.
   389  //
   390  // Examples:
   391  //
   392  //	Dial("tcp", "golang.org:http")
   393  //	Dial("tcp", "192.0.2.1:http")
   394  //	Dial("tcp", "198.51.100.1:80")
   395  //	Dial("udp", "[2001:db8::1]:domain")
   396  //	Dial("udp", "[fe80::1%lo0]:53")
   397  //	Dial("tcp", ":80")
   398  //
   399  // For IP networks, the network must be "ip", "ip4" or "ip6" followed
   400  // by a colon and a literal protocol number or a protocol name, and
   401  // the address has the form "host". The host must be a literal IP
   402  // address or a literal IPv6 address with zone.
   403  // It depends on each operating system how the operating system
   404  // behaves with a non-well known protocol number such as "0" or "255".
   405  //
   406  // Examples:
   407  //
   408  //	Dial("ip4:1", "192.0.2.1")
   409  //	Dial("ip6:ipv6-icmp", "2001:db8::1")
   410  //	Dial("ip6:58", "fe80::1%lo0")
   411  //
   412  // For TCP, UDP and IP networks, if the host is empty or a literal
   413  // unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80" for
   414  // TCP and UDP, "", "0.0.0.0" or "::" for IP, the local system is
   415  // assumed.
   416  //
   417  // For Unix networks, the address must be a file system path.
   418  func Dial(network, address string) (Conn, error) {
   419  	var d Dialer
   420  	return d.Dial(network, address)
   421  }
   422  
   423  // DialTimeout acts like [Dial] but takes a timeout.
   424  //
   425  // The timeout includes name resolution, if required.
   426  // When using TCP, and the host in the address parameter resolves to
   427  // multiple IP addresses, the timeout is spread over each consecutive
   428  // dial, such that each is given an appropriate fraction of the time
   429  // to connect.
   430  //
   431  // See func Dial for a description of the network and address
   432  // parameters.
   433  func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
   434  	d := Dialer{Timeout: timeout}
   435  	return d.Dial(network, address)
   436  }
   437  
   438  // sysDialer contains a Dial's parameters and configuration.
   439  type sysDialer struct {
   440  	Dialer
   441  	network, address string
   442  	testHookDialTCP  func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error)
   443  }
   444  
   445  // Dial connects to the address on the named network.
   446  //
   447  // See func Dial for a description of the network and address
   448  // parameters.
   449  //
   450  // Dial uses [context.Background] internally; to specify the context, use
   451  // [Dialer.DialContext].
   452  func (d *Dialer) Dial(network, address string) (Conn, error) {
   453  	return d.DialContext(context.Background(), network, address)
   454  }
   455  
   456  // DialContext connects to the address on the named network using
   457  // the provided context.
   458  //
   459  // The provided Context must be non-nil. If the context expires before
   460  // the connection is complete, an error is returned. Once successfully
   461  // connected, any expiration of the context will not affect the
   462  // connection.
   463  //
   464  // When using TCP, and the host in the address parameter resolves to multiple
   465  // network addresses, any dial timeout (from d.Timeout or ctx) is spread
   466  // over each consecutive dial, such that each is given an appropriate
   467  // fraction of the time to connect.
   468  // For example, if a host has 4 IP addresses and the timeout is 1 minute,
   469  // the connect to each single address will be given 15 seconds to complete
   470  // before trying the next one.
   471  //
   472  // See func [Dial] for a description of the network and address
   473  // parameters.
   474  func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) {
   475  	if ctx == nil {
   476  		panic("nil context")
   477  	}
   478  	deadline := d.deadline(ctx, time.Now())
   479  	if !deadline.IsZero() {
   480  		testHookStepTime()
   481  		if d, ok := ctx.Deadline(); !ok || deadline.Before(d) {
   482  			subCtx, cancel := context.WithDeadline(ctx, deadline)
   483  			defer cancel()
   484  			ctx = subCtx
   485  		}
   486  	}
   487  	if oldCancel := d.Cancel; oldCancel != nil {
   488  		subCtx, cancel := context.WithCancel(ctx)
   489  		defer cancel()
   490  		go func() {
   491  			select {
   492  			case <-oldCancel:
   493  				cancel()
   494  			case <-subCtx.Done():
   495  			}
   496  		}()
   497  		ctx = subCtx
   498  	}
   499  
   500  	// Shadow the nettrace (if any) during resolve so Connect events don't fire for DNS lookups.
   501  	resolveCtx := ctx
   502  	if trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace); trace != nil {
   503  		shadow := *trace
   504  		shadow.ConnectStart = nil
   505  		shadow.ConnectDone = nil
   506  		resolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow)
   507  	}
   508  
   509  	addrs, err := d.resolver().resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)
   510  	if err != nil {
   511  		return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
   512  	}
   513  
   514  	sd := &sysDialer{
   515  		Dialer:  *d,
   516  		network: network,
   517  		address: address,
   518  	}
   519  
   520  	var primaries, fallbacks addrList
   521  	if d.dualStack() && network == "tcp" {
   522  		primaries, fallbacks = addrs.partition(isIPv4)
   523  	} else {
   524  		primaries = addrs
   525  	}
   526  
   527  	return sd.dialParallel(ctx, primaries, fallbacks)
   528  }
   529  
   530  // dialParallel races two copies of dialSerial, giving the first a
   531  // head start. It returns the first established connection and
   532  // closes the others. Otherwise it returns an error from the first
   533  // primary address.
   534  func (sd *sysDialer) dialParallel(ctx context.Context, primaries, fallbacks addrList) (Conn, error) {
   535  	if len(fallbacks) == 0 {
   536  		return sd.dialSerial(ctx, primaries)
   537  	}
   538  
   539  	returned := make(chan struct{})
   540  	defer close(returned)
   541  
   542  	type dialResult struct {
   543  		Conn
   544  		error
   545  		primary bool
   546  		done    bool
   547  	}
   548  	results := make(chan dialResult) // unbuffered
   549  
   550  	startRacer := func(ctx context.Context, primary bool) {
   551  		ras := primaries
   552  		if !primary {
   553  			ras = fallbacks
   554  		}
   555  		c, err := sd.dialSerial(ctx, ras)
   556  		select {
   557  		case results <- dialResult{Conn: c, error: err, primary: primary, done: true}:
   558  		case <-returned:
   559  			if c != nil {
   560  				c.Close()
   561  			}
   562  		}
   563  	}
   564  
   565  	var primary, fallback dialResult
   566  
   567  	// Start the main racer.
   568  	primaryCtx, primaryCancel := context.WithCancel(ctx)
   569  	defer primaryCancel()
   570  	go startRacer(primaryCtx, true)
   571  
   572  	// Start the timer for the fallback racer.
   573  	fallbackTimer := time.NewTimer(sd.fallbackDelay())
   574  	defer fallbackTimer.Stop()
   575  
   576  	for {
   577  		select {
   578  		case <-fallbackTimer.C:
   579  			fallbackCtx, fallbackCancel := context.WithCancel(ctx)
   580  			defer fallbackCancel()
   581  			go startRacer(fallbackCtx, false)
   582  
   583  		case res := <-results:
   584  			if res.error == nil {
   585  				return res.Conn, nil
   586  			}
   587  			if res.primary {
   588  				primary = res
   589  			} else {
   590  				fallback = res
   591  			}
   592  			if primary.done && fallback.done {
   593  				return nil, primary.error
   594  			}
   595  			if res.primary && fallbackTimer.Stop() {
   596  				// If we were able to stop the timer, that means it
   597  				// was running (hadn't yet started the fallback), but
   598  				// we just got an error on the primary path, so start
   599  				// the fallback immediately (in 0 nanoseconds).
   600  				fallbackTimer.Reset(0)
   601  			}
   602  		}
   603  	}
   604  }
   605  
   606  // dialSerial connects to a list of addresses in sequence, returning
   607  // either the first successful connection, or the first error.
   608  func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) {
   609  	var firstErr error // The error from the first address is most relevant.
   610  
   611  	for i, ra := range ras {
   612  		select {
   613  		case <-ctx.Done():
   614  			return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())}
   615  		default:
   616  		}
   617  
   618  		dialCtx := ctx
   619  		if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
   620  			partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i)
   621  			if err != nil {
   622  				// Ran out of time.
   623  				if firstErr == nil {
   624  					firstErr = &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err}
   625  				}
   626  				break
   627  			}
   628  			if partialDeadline.Before(deadline) {
   629  				var cancel context.CancelFunc
   630  				dialCtx, cancel = context.WithDeadline(ctx, partialDeadline)
   631  				defer cancel()
   632  			}
   633  		}
   634  
   635  		c, err := sd.dialSingle(dialCtx, ra)
   636  		if err == nil {
   637  			return c, nil
   638  		}
   639  		if firstErr == nil {
   640  			firstErr = err
   641  		}
   642  	}
   643  
   644  	if firstErr == nil {
   645  		firstErr = &OpError{Op: "dial", Net: sd.network, Source: nil, Addr: nil, Err: errMissingAddress}
   646  	}
   647  	return nil, firstErr
   648  }
   649  
   650  // dialSingle attempts to establish and returns a single connection to
   651  // the destination address.
   652  func (sd *sysDialer) dialSingle(ctx context.Context, ra Addr) (c Conn, err error) {
   653  	trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
   654  	if trace != nil {
   655  		raStr := ra.String()
   656  		if trace.ConnectStart != nil {
   657  			trace.ConnectStart(sd.network, raStr)
   658  		}
   659  		if trace.ConnectDone != nil {
   660  			defer func() { trace.ConnectDone(sd.network, raStr, err) }()
   661  		}
   662  	}
   663  	la := sd.LocalAddr
   664  	switch ra := ra.(type) {
   665  	case *TCPAddr:
   666  		la, _ := la.(*TCPAddr)
   667  		if sd.MultipathTCP() {
   668  			c, err = sd.dialMPTCP(ctx, la, ra)
   669  		} else {
   670  			c, err = sd.dialTCP(ctx, la, ra)
   671  		}
   672  	case *UDPAddr:
   673  		la, _ := la.(*UDPAddr)
   674  		c, err = sd.dialUDP(ctx, la, ra)
   675  	case *IPAddr:
   676  		la, _ := la.(*IPAddr)
   677  		c, err = sd.dialIP(ctx, la, ra)
   678  	case *UnixAddr:
   679  		la, _ := la.(*UnixAddr)
   680  		c, err = sd.dialUnix(ctx, la, ra)
   681  	default:
   682  		return nil, &OpError{Op: "dial", Net: sd.network, Source: la, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: sd.address}}
   683  	}
   684  	if err != nil {
   685  		return nil, &OpError{Op: "dial", Net: sd.network, Source: la, Addr: ra, Err: err} // c is non-nil interface containing nil pointer
   686  	}
   687  	return c, nil
   688  }
   689  
   690  // ListenConfig contains options for listening to an address.
   691  type ListenConfig struct {
   692  	// If Control is not nil, it is called after creating the network
   693  	// connection but before binding it to the operating system.
   694  	//
   695  	// Network and address parameters passed to Control method are not
   696  	// necessarily the ones passed to Listen. For example, passing "tcp" to
   697  	// Listen will cause the Control function to be called with "tcp4" or "tcp6".
   698  	Control func(network, address string, c syscall.RawConn) error
   699  
   700  	// KeepAlive specifies the keep-alive period for network
   701  	// connections accepted by this listener.
   702  	//
   703  	// KeepAlive is ignored if KeepAliveConfig.Enable is true.
   704  	//
   705  	// If zero, keep-alive are enabled if supported by the protocol
   706  	// and operating system. Network protocols or operating systems
   707  	// that do not support keep-alive ignore this field.
   708  	// If negative, keep-alive are disabled.
   709  	KeepAlive time.Duration
   710  
   711  	// KeepAliveConfig specifies the keep-alive probe configuration
   712  	// for an active network connection, when supported by the
   713  	// protocol and operating system.
   714  	//
   715  	// If KeepAliveConfig.Enable is true, keep-alive probes are enabled.
   716  	// If KeepAliveConfig.Enable is false and KeepAlive is negative,
   717  	// keep-alive probes are disabled.
   718  	KeepAliveConfig KeepAliveConfig
   719  
   720  	// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
   721  	// used, any call to Listen with "tcp(4|6)" as network will use MPTCP if
   722  	// supported by the operating system.
   723  	mptcpStatus mptcpStatus
   724  }
   725  
   726  // MultipathTCP reports whether MPTCP will be used.
   727  //
   728  // This method doesn't check if MPTCP is supported by the operating
   729  // system or not.
   730  func (lc *ListenConfig) MultipathTCP() bool {
   731  	return lc.mptcpStatus.get()
   732  }
   733  
   734  // SetMultipathTCP directs the [Listen] method to use, or not use, MPTCP,
   735  // if supported by the operating system. This method overrides the
   736  // system default and the GODEBUG=multipathtcp=... setting if any.
   737  //
   738  // If MPTCP is not available on the host or not supported by the client,
   739  // the Listen method will fall back to TCP.
   740  func (lc *ListenConfig) SetMultipathTCP(use bool) {
   741  	lc.mptcpStatus.set(use)
   742  }
   743  
   744  // Listen announces on the local network address.
   745  //
   746  // See func Listen for a description of the network and address
   747  // parameters.
   748  func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (Listener, error) {
   749  	addrs, err := DefaultResolver.resolveAddrList(ctx, "listen", network, address, nil)
   750  	if err != nil {
   751  		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: err}
   752  	}
   753  	sl := &sysListener{
   754  		ListenConfig: *lc,
   755  		network:      network,
   756  		address:      address,
   757  	}
   758  	var l Listener
   759  	la := addrs.first(isIPv4)
   760  	switch la := la.(type) {
   761  	case *TCPAddr:
   762  		if sl.MultipathTCP() {
   763  			l, err = sl.listenMPTCP(ctx, la)
   764  		} else {
   765  			l, err = sl.listenTCP(ctx, la)
   766  		}
   767  	case *UnixAddr:
   768  		l, err = sl.listenUnix(ctx, la)
   769  	default:
   770  		return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: address}}
   771  	}
   772  	if err != nil {
   773  		return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: err} // l is non-nil interface containing nil pointer
   774  	}
   775  	return l, nil
   776  }
   777  
   778  // ListenPacket announces on the local network address.
   779  //
   780  // See func ListenPacket for a description of the network and address
   781  // parameters.
   782  func (lc *ListenConfig) ListenPacket(ctx context.Context, network, address string) (PacketConn, error) {
   783  	addrs, err := DefaultResolver.resolveAddrList(ctx, "listen", network, address, nil)
   784  	if err != nil {
   785  		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: err}
   786  	}
   787  	sl := &sysListener{
   788  		ListenConfig: *lc,
   789  		network:      network,
   790  		address:      address,
   791  	}
   792  	var c PacketConn
   793  	la := addrs.first(isIPv4)
   794  	switch la := la.(type) {
   795  	case *UDPAddr:
   796  		c, err = sl.listenUDP(ctx, la)
   797  	case *IPAddr:
   798  		c, err = sl.listenIP(ctx, la)
   799  	case *UnixAddr:
   800  		c, err = sl.listenUnixgram(ctx, la)
   801  	default:
   802  		return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: address}}
   803  	}
   804  	if err != nil {
   805  		return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: err} // c is non-nil interface containing nil pointer
   806  	}
   807  	return c, nil
   808  }
   809  
   810  // sysListener contains a Listen's parameters and configuration.
   811  type sysListener struct {
   812  	ListenConfig
   813  	network, address string
   814  }
   815  
   816  // Listen announces on the local network address.
   817  //
   818  // The network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
   819  //
   820  // For TCP networks, if the host in the address parameter is empty or
   821  // a literal unspecified IP address, Listen listens on all available
   822  // unicast and anycast IP addresses of the local system.
   823  // To only use IPv4, use network "tcp4".
   824  // The address can use a host name, but this is not recommended,
   825  // because it will create a listener for at most one of the host's IP
   826  // addresses.
   827  // If the port in the address parameter is empty or "0", as in
   828  // "127.0.0.1:" or "[::1]:0", a port number is automatically chosen.
   829  // The [Addr] method of [Listener] can be used to discover the chosen
   830  // port.
   831  //
   832  // See func [Dial] for a description of the network and address
   833  // parameters.
   834  //
   835  // Listen uses context.Background internally; to specify the context, use
   836  // [ListenConfig.Listen].
   837  func Listen(network, address string) (Listener, error) {
   838  	var lc ListenConfig
   839  	return lc.Listen(context.Background(), network, address)
   840  }
   841  
   842  // ListenPacket announces on the local network address.
   843  //
   844  // The network must be "udp", "udp4", "udp6", "unixgram", or an IP
   845  // transport. The IP transports are "ip", "ip4", or "ip6" followed by
   846  // a colon and a literal protocol number or a protocol name, as in
   847  // "ip:1" or "ip:icmp".
   848  //
   849  // For UDP and IP networks, if the host in the address parameter is
   850  // empty or a literal unspecified IP address, ListenPacket listens on
   851  // all available IP addresses of the local system except multicast IP
   852  // addresses.
   853  // To only use IPv4, use network "udp4" or "ip4:proto".
   854  // The address can use a host name, but this is not recommended,
   855  // because it will create a listener for at most one of the host's IP
   856  // addresses.
   857  // If the port in the address parameter is empty or "0", as in
   858  // "127.0.0.1:" or "[::1]:0", a port number is automatically chosen.
   859  // The LocalAddr method of [PacketConn] can be used to discover the
   860  // chosen port.
   861  //
   862  // See func [Dial] for a description of the network and address
   863  // parameters.
   864  //
   865  // ListenPacket uses context.Background internally; to specify the context, use
   866  // [ListenConfig.ListenPacket].
   867  func ListenPacket(network, address string) (PacketConn, error) {
   868  	var lc ListenConfig
   869  	return lc.ListenPacket(context.Background(), network, address)
   870  }
   871  

View as plain text