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

View as plain text