Copyright 2010 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package net

import (
	
	
	
	
)
defaultTCPKeepAlive is a default constant value for TCPKeepAlive times See golang.org/issue/31510
const (
	defaultTCPKeepAlive = 15 * time.Second
)
A Dialer contains options for connecting to an address. The zero value for each field is equivalent to dialing without that option. Dialing with the zero value of Dialer is therefore equivalent to just calling the Dial function. It is safe to call Dialer's methods concurrently.
Timeout is the maximum amount of time a dial will wait for a connect to complete. If Deadline is also set, it may fail earlier. The default is no timeout. When using TCP and dialing a host name with multiple IP addresses, the timeout may be divided between them. With or without a timeout, the operating system may impose its own earlier timeout. For instance, TCP timeouts are often around 3 minutes.
Deadline is the absolute point in time after which dials will fail. If Timeout is set, it may fail earlier. Zero means no deadline, or dependent on the operating system as with the Timeout option.
LocalAddr is the local address to use when dialing an address. The address must be of a compatible type for the network being dialed. If nil, a local address is automatically chosen.
DualStack previously enabled RFC 6555 Fast Fallback support, also known as "Happy Eyeballs", in which IPv4 is tried soon if IPv6 appears to be misconfigured and hanging. Deprecated: Fast Fallback is enabled by default. To disable, set FallbackDelay to a negative value.
FallbackDelay specifies the length of time to wait before spawning a RFC 6555 Fast Fallback connection. That is, this is the amount of time to wait for IPv6 to succeed before assuming that IPv6 is misconfigured and falling back to IPv4. If zero, a default delay of 300ms is used. A negative value disables Fast Fallback support.
KeepAlive specifies the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled.
Resolver optionally specifies an alternate resolver to use.
Cancel is an optional channel whose closure indicates that the dial should be canceled. Not all types of dials support cancellation. Deprecated: Use DialContext instead.
	Cancel <-chan struct{}
If Control is not nil, it is called after creating the network connection but before actually dialing. Network and address parameters passed to Control method are not necessarily the ones passed to Dial. For example, passing "tcp" to Dial will cause the Control function to be called with "tcp4" or "tcp6".
	Control func(network, address string, c syscall.RawConn) error
}

func ( *Dialer) () bool { return .FallbackDelay >= 0 }

func (,  time.Time) time.Time {
	if .IsZero() {
		return 
	}
	if .IsZero() || .Before() {
		return 
	}
	return 
}
deadline returns the earliest of: - now+Timeout - d.Deadline - the context's deadline Or zero, if none of Timeout, Deadline, or context's deadline is set.
func ( *Dialer) ( context.Context,  time.Time) ( time.Time) {
	if .Timeout != 0 { // including negative, for historical reasons
		 = .Add(.Timeout)
	}
	if ,  := .Deadline();  {
		 = minNonzeroTime(, )
	}
	return minNonzeroTime(, .Deadline)
}

func ( *Dialer) () *Resolver {
	if .Resolver != nil {
		return .Resolver
	}
	return DefaultResolver
}
partialDeadline returns the deadline to use for a single address, when multiple addresses are pending.
func (,  time.Time,  int) (time.Time, error) {
	if .IsZero() {
		return , nil
	}
	 := .Sub()
	if  <= 0 {
		return time.Time{}, errTimeout
Tentatively allocate equal time to each remaining address.
If the time per address is too short, steal from the end of the list.
	const  = 2 * time.Second
	if  <  {
		if  <  {
			 = 
		} else {
			 = 
		}
	}
	return .Add(), nil
}

func ( *Dialer) () time.Duration {
	if .FallbackDelay > 0 {
		return .FallbackDelay
	} else {
		return 300 * time.Millisecond
	}
}

func ( context.Context,  string,  bool) ( string,  int,  error) {
	 := last(, ':')
	if  < 0 { // no colon
		switch  {
		case "tcp", "tcp4", "tcp6":
		case "udp", "udp4", "udp6":
		case "ip", "ip4", "ip6":
			if  {
				return "", 0, UnknownNetworkError()
			}
		case "unix", "unixgram", "unixpacket":
		default:
			return "", 0, UnknownNetworkError()
		}
		return , 0, nil
	}
	 = [:]
	switch  {
	case "ip", "ip4", "ip6":
		 := [+1:]
		, ,  := dtoi()
		if ! ||  != len() {
			,  = lookupProtocol(, )
			if  != nil {
				return "", 0, 
			}
		}
		return , , nil
	}
	return "", 0, UnknownNetworkError()
}
resolveAddrList resolves addr using hint and returns a list of addresses. The result contains at least one address when error is nil.
func ( *Resolver) ( context.Context, , ,  string,  Addr) (addrList, error) {
	, ,  := parseNetwork(, , true)
	if  != nil {
		return nil, 
	}
	if  == "dial" &&  == "" {
		return nil, errMissingAddress
	}
	switch  {
	case "unix", "unixgram", "unixpacket":
		,  := ResolveUnixAddr(, )
		if  != nil {
			return nil, 
		}
		if  == "dial" &&  != nil && .Network() != .Network() {
			return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
		}
		return addrList{}, nil
	}
	,  := .internetAddrList(, , )
	if  != nil ||  != "dial" ||  == nil {
		return , 
	}
	var (
		      *TCPAddr
		      *UDPAddr
		       *IPAddr
		 bool
	)
	switch hint := .(type) {
	case *TCPAddr:
		 = 
		 = .isWildcard()
	case *UDPAddr:
		 = 
		 = .isWildcard()
	case *IPAddr:
		 = 
		 = .isWildcard()
	}
	 := [:0]
	for ,  := range  {
		if .Network() != .Network() {
			return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
		}
		switch addr := .(type) {
		case *TCPAddr:
			if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
				continue
			}
			 = append(, )
		case *UDPAddr:
			if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
				continue
			}
			 = append(, )
		case *IPAddr:
			if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
				continue
			}
			 = append(, )
		}
	}
	if len() == 0 {
		return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: .String()}
	}
	return , nil
}
Dial connects to the address on the named network. Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4" (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket". For TCP and UDP networks, the address has the form "host:port". The host must be a literal IP address, or a host name that can be resolved to IP addresses. The port must be a literal port number or a service name. If the host is a literal IPv6 address it must be enclosed in square brackets, as in "[2001:db8::1]:80" or "[fe80::1%zone]:80". The zone specifies the scope of the literal IPv6 address as defined in RFC 4007. The functions JoinHostPort and SplitHostPort manipulate a pair of host and port in this form. When using TCP, and the host resolves to multiple IP addresses, Dial will try each IP address in order until one succeeds. Examples: Dial("tcp", "golang.org:http") Dial("tcp", "192.0.2.1:http") Dial("tcp", "198.51.100.1:80") Dial("udp", "[2001:db8::1]:domain") Dial("udp", "[fe80::1%lo0]:53") Dial("tcp", ":80") For IP networks, the network must be "ip", "ip4" or "ip6" followed by a colon and a literal protocol number or a protocol name, and the address has the form "host". The host must be a literal IP address or a literal IPv6 address with zone. It depends on each operating system how the operating system behaves with a non-well known protocol number such as "0" or "255". Examples: Dial("ip4:1", "192.0.2.1") Dial("ip6:ipv6-icmp", "2001:db8::1") Dial("ip6:58", "fe80::1%lo0") For TCP, UDP and IP networks, if the host is empty or a literal unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80" for TCP and UDP, "", "0.0.0.0" or "::" for IP, the local system is assumed. For Unix networks, the address must be a file system path.
func (,  string) (Conn, error) {
	var  Dialer
	return .Dial(, )
}
DialTimeout acts like Dial but takes a timeout. The timeout includes name resolution, if required. When using TCP, and the host in the address parameter resolves to multiple IP addresses, the timeout is spread over each consecutive dial, such that each is given an appropriate fraction of the time to connect. See func Dial for a description of the network and address parameters.
func (,  string,  time.Duration) (Conn, error) {
	 := Dialer{Timeout: }
	return .Dial(, )
}
sysDialer contains a Dial's parameters and configuration.
Dial connects to the address on the named network. See func Dial for a description of the network and address parameters.
func ( *Dialer) (,  string) (Conn, error) {
	return .DialContext(context.Background(), , )
}
DialContext connects to the address on the named network using the provided context. The provided Context must be non-nil. If the context expires before the connection is complete, an error is returned. Once successfully connected, any expiration of the context will not affect the connection. When using TCP, and the host in the address parameter resolves to multiple network addresses, any dial timeout (from d.Timeout or ctx) is spread over each consecutive dial, such that each is given an appropriate fraction of the time to connect. For example, if a host has 4 IP addresses and the timeout is 1 minute, the connect to each single address will be given 15 seconds to complete before trying the next one. See func Dial for a description of the network and address parameters.
func ( *Dialer) ( context.Context, ,  string) (Conn, error) {
	if  == nil {
		panic("nil context")
	}
	 := .deadline(, time.Now())
	if !.IsZero() {
		if ,  := .Deadline(); ! || .Before() {
			,  := context.WithDeadline(, )
			defer ()
			 = 
		}
	}
	if  := .Cancel;  != nil {
		,  := context.WithCancel()
		defer ()
		go func() {
			select {
			case <-:
				()
			case <-.Done():
			}
		}()
		 = 
	}
Shadow the nettrace (if any) during resolve so Connect events don't fire for DNS lookups.
	 := 
	if ,  := .Value(nettrace.TraceKey{}).(*nettrace.Trace);  != nil {
		 := *
		.ConnectStart = nil
		.ConnectDone = nil
		 = context.WithValue(, nettrace.TraceKey{}, &)
	}

	,  := .resolver().resolveAddrList(, "dial", , , .LocalAddr)
	if  != nil {
		return nil, &OpError{Op: "dial", Net: , Source: nil, Addr: nil, Err: }
	}

	 := &sysDialer{
		Dialer:  *,
		network: ,
		address: ,
	}

	var ,  addrList
	if .dualStack() &&  == "tcp" {
		,  = .partition(isIPv4)
	} else {
		 = 
	}

	var  Conn
	if len() > 0 {
		,  = .dialParallel(, , )
	} else {
		,  = .dialSerial(, )
	}
	if  != nil {
		return nil, 
	}

	if ,  := .(*TCPConn);  && .KeepAlive >= 0 {
		setKeepAlive(.fd, true)
		 := .KeepAlive
		if .KeepAlive == 0 {
			 = defaultTCPKeepAlive
		}
		setKeepAlivePeriod(.fd, )
		testHookSetKeepAlive()
	}
	return , nil
}
dialParallel races two copies of dialSerial, giving the first a head start. It returns the first established connection and closes the others. Otherwise it returns an error from the first primary address.
func ( *sysDialer) ( context.Context, ,  addrList) (Conn, error) {
	if len() == 0 {
		return .dialSerial(, )
	}

	 := make(chan struct{})
	defer close()

	type  struct {
		Conn
		error
		 bool
		    bool
	}
	 := make(chan ) // unbuffered

	 := func( context.Context,  bool) {
		 := 
		if ! {
			 = 
		}
		,  := .dialSerial(, )
		select {
		case  <- {: , : , : , : true}:
		case <-:
			if  != nil {
				.Close()
			}
		}
	}

	var ,  
Start the main racer.
	,  := context.WithCancel()
	defer ()
	go (, true)
Start the timer for the fallback racer.
	 := time.NewTimer(.fallbackDelay())
	defer .Stop()

	for {
		select {
		case <-.C:
			,  := context.WithCancel()
			defer ()
			go (, false)

		case  := <-:
			if . == nil {
				return ., nil
			}
			if . {
				 = 
			} else {
				 = 
			}
			if . && . {
				return nil, .
			}
If we were able to stop the timer, that means it was running (hadn't yet started the fallback), but we just got an error on the primary path, so start the fallback immediately (in 0 nanoseconds).
				.Reset(0)
			}
		}
	}
}
dialSerial connects to a list of addresses in sequence, returning either the first successful connection, or the first error.
func ( *sysDialer) ( context.Context,  addrList) (Conn, error) {
	var  error // The error from the first address is most relevant.

	for ,  := range  {
		select {
		case <-.Done():
			return nil, &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: mapErr(.Err())}
		default:
		}

		 := 
		if ,  := .Deadline();  {
			,  := partialDeadline(time.Now(), , len()-)
Ran out of time.
				if  == nil {
					 = &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: }
				}
				break
			}
			if .Before() {
				var  context.CancelFunc
				,  = context.WithDeadline(, )
				defer ()
			}
		}

		,  := .dialSingle(, )
		if  == nil {
			return , nil
		}
		if  == nil {
			 = 
		}
	}

	if  == nil {
		 = &OpError{Op: "dial", Net: .network, Source: nil, Addr: nil, Err: errMissingAddress}
	}
	return nil, 
}
dialSingle attempts to establish and returns a single connection to the destination address.
func ( *sysDialer) ( context.Context,  Addr) ( Conn,  error) {
	,  := .Value(nettrace.TraceKey{}).(*nettrace.Trace)
	if  != nil {
		 := .String()
		if .ConnectStart != nil {
			.ConnectStart(.network, )
		}
		if .ConnectDone != nil {
			defer func() { .ConnectDone(.network, , ) }()
		}
	}
	 := .LocalAddr
	switch ra := .(type) {
	case *TCPAddr:
		,  := .(*TCPAddr)
		,  = .dialTCP(, , )
	case *UDPAddr:
		,  := .(*UDPAddr)
		,  = .dialUDP(, , )
	case *IPAddr:
		,  := .(*IPAddr)
		,  = .dialIP(, , )
	case *UnixAddr:
		,  := .(*UnixAddr)
		,  = .dialUnix(, , )
	default:
		return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: &AddrError{Err: "unexpected address type", Addr: .address}}
	}
	if  != nil {
		return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: } // c is non-nil interface containing nil pointer
	}
	return , nil
}
ListenConfig contains options for listening to an address.
If Control is not nil, it is called after creating the network connection but before binding it to the operating system. Network and address parameters passed to Control method are not necessarily the ones passed to Listen. For example, passing "tcp" to Listen will cause the Control function to be called with "tcp4" or "tcp6".
	Control func(network, address string, c syscall.RawConn) error
KeepAlive specifies the keep-alive period for network connections accepted by this listener. If zero, keep-alives are enabled if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alives are disabled.
Listen announces on the local network address. See func Listen for a description of the network and address parameters.
func ( *ListenConfig) ( context.Context, ,  string) (Listener, error) {
	,  := DefaultResolver.resolveAddrList(, "listen", , , nil)
	if  != nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
	}
	 := &sysListener{
		ListenConfig: *,
		network:      ,
		address:      ,
	}
	var  Listener
	 := .first(isIPv4)
	switch la := .(type) {
	case *TCPAddr:
		,  = .listenTCP(, )
	case *UnixAddr:
		,  = .listenUnix(, )
	default:
		return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
	}
	if  != nil {
		return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // l is non-nil interface containing nil pointer
	}
	return , nil
}
ListenPacket announces on the local network address. See func ListenPacket for a description of the network and address parameters.
func ( *ListenConfig) ( context.Context, ,  string) (PacketConn, error) {
	,  := DefaultResolver.resolveAddrList(, "listen", , , nil)
	if  != nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
	}
	 := &sysListener{
		ListenConfig: *,
		network:      ,
		address:      ,
	}
	var  PacketConn
	 := .first(isIPv4)
	switch la := .(type) {
	case *UDPAddr:
		,  = .listenUDP(, )
	case *IPAddr:
		,  = .listenIP(, )
	case *UnixAddr:
		,  = .listenUnixgram(, )
	default:
		return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
	}
	if  != nil {
		return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // c is non-nil interface containing nil pointer
	}
	return , nil
}
sysListener contains a Listen's parameters and configuration.
Listen announces on the local network address. The network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket". For TCP networks, if the host in the address parameter is empty or a literal unspecified IP address, Listen listens on all available unicast and anycast IP addresses of the local system. To only use IPv4, use network "tcp4". The address can use a host name, but this is not recommended, because it will create a listener for at most one of the host's IP addresses. If the port in the address parameter is empty or "0", as in "127.0.0.1:" or "[::1]:0", a port number is automatically chosen. The Addr method of Listener can be used to discover the chosen port. See func Dial for a description of the network and address parameters.
func (,  string) (Listener, error) {
	var  ListenConfig
	return .Listen(context.Background(), , )
}
ListenPacket announces on the local network address. The network must be "udp", "udp4", "udp6", "unixgram", or an IP transport. The IP transports are "ip", "ip4", or "ip6" followed by a colon and a literal protocol number or a protocol name, as in "ip:1" or "ip:icmp". For UDP and IP networks, if the host in the address parameter is empty or a literal unspecified IP address, ListenPacket listens on all available IP addresses of the local system except multicast IP addresses. To only use IPv4, use network "udp4" or "ip4:proto". The address can use a host name, but this is not recommended, because it will create a listener for at most one of the host's IP addresses. If the port in the address parameter is empty or "0", as in "127.0.0.1:" or "[::1]:0", a port number is automatically chosen. The LocalAddr method of PacketConn can be used to discover the chosen port. See func Dial for a description of the network and address parameters.
func (,  string) (PacketConn, error) {
	var  ListenConfig
	return .ListenPacket(context.Background(), , )