...
Run Format

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

View as plain text