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

View as plain text