diff options
Diffstat (limited to 'libgo/go/net/dial.go')
-rw-r--r-- | libgo/go/net/dial.go | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go index 55edb43..50bba5a 100644 --- a/libgo/go/net/dial.go +++ b/libgo/go/net/dial.go @@ -59,6 +59,9 @@ type Dialer struct { // that do not support keep-alives ignore this field. KeepAlive time.Duration + // Resolver optionally specifies an alternate resolver to use. + Resolver *Resolver + // Cancel is an optional channel whose closure indicates that // the dial should be canceled. Not all types of dials support // cancelation. @@ -92,6 +95,13 @@ func (d *Dialer) deadline(ctx context.Context, now time.Time) (earliest time.Tim return minNonzeroTime(earliest, d.Deadline) } +func (d *Dialer) resolver() *Resolver { + if d.Resolver != nil { + return d.Resolver + } + return DefaultResolver +} + // partialDeadline returns the deadline to use for a single address, // when multiple addresses are pending. func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) { @@ -141,7 +151,7 @@ func parseNetwork(ctx context.Context, net string) (afnet string, proto int, err switch afnet { case "ip", "ip4", "ip6": protostr := net[i+1:] - proto, i, ok := dtoi(protostr, 0) + proto, i, ok := dtoi(protostr) if !ok || i != len(protostr) { proto, err = lookupProtocol(ctx, protostr) if err != nil { @@ -153,10 +163,10 @@ func parseNetwork(ctx context.Context, net string) (afnet string, proto int, err return "", 0, UnknownNetworkError(net) } -// resolverAddrList resolves addr using hint and returns a list of +// resolveAddrList resolves addr using hint and returns a list of // addresses. The result contains at least one address when error is // nil. -func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) { +func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) { afnet, _, err := parseNetwork(ctx, network) if err != nil { return nil, err @@ -166,7 +176,6 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) ( } switch afnet { case "unix", "unixgram", "unixpacket": - // TODO(bradfitz): push down context addr, err := ResolveUnixAddr(afnet, addr) if err != nil { return nil, err @@ -176,7 +185,7 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) ( } return addrList{addr}, nil } - addrs, err := internetAddrList(ctx, afnet, addr) + addrs, err := r.internetAddrList(ctx, afnet, addr) if err != nil || op != "dial" || hint == nil { return addrs, err } @@ -221,7 +230,7 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) ( } } if len(naddrs) == 0 { - return nil, errNoSuitableAddress + return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: hint.String()} } return naddrs, nil } @@ -256,6 +265,9 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) ( // Dial("ip6:ipv6-icmp", "2001:db8::1") // // For Unix networks, the address must be a file system path. +// +// If the host is resolved to multiple addresses, +// Dial will try each address in order until one succeeds. func Dial(network, address string) (Conn, error) { var d Dialer return d.Dial(network, address) @@ -290,6 +302,14 @@ func (d *Dialer) Dial(network, address string) (Conn, error) { // 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 (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) { @@ -326,7 +346,7 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn resolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow) } - addrs, err := resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr) + addrs, err := d.resolver().resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr) if err != nil { return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err} } @@ -524,8 +544,11 @@ func dialSingle(ctx context.Context, dp *dialParam, ra Addr) (c Conn, err error) // If host is omitted, as in ":8080", Listen listens on all available interfaces // instead of just the interface with the given host address. // See Dial for more details about address syntax. +// +// Listening on a hostname is not recommended because this creates a socket +// for at most one of its IP addresses. func Listen(net, laddr string) (Listener, error) { - addrs, err := resolveAddrList(context.Background(), "listen", net, laddr, nil) + addrs, err := DefaultResolver.resolveAddrList(context.Background(), "listen", net, laddr, nil) if err != nil { return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err} } @@ -551,8 +574,11 @@ func Listen(net, laddr string) (Listener, error) { // If host is omitted, as in ":8080", ListenPacket listens on all available interfaces // instead of just the interface with the given host address. // See Dial for the syntax of laddr. +// +// Listening on a hostname is not recommended because this creates a socket +// for at most one of its IP addresses. func ListenPacket(net, laddr string) (PacketConn, error) { - addrs, err := resolveAddrList(context.Background(), "listen", net, laddr, nil) + addrs, err := DefaultResolver.resolveAddrList(context.Background(), "listen", net, laddr, nil) if err != nil { return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err} } |