Source file src/net/dial.go

Documentation: net

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

View as plain text