dial.mx raw

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