Home | History | Annotate | Download | only in 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 	"errors"
      9 	"time"
     10 )
     11 
     12 // A Dialer contains options for connecting to an address.
     13 //
     14 // The zero value for each field is equivalent to dialing
     15 // without that option. Dialing with the zero value of Dialer
     16 // is therefore equivalent to just calling the Dial function.
     17 type Dialer struct {
     18 	// Timeout is the maximum amount of time a dial will wait for
     19 	// a connect to complete. If Deadline is also set, it may fail
     20 	// earlier.
     21 	//
     22 	// The default is no timeout.
     23 	//
     24 	// When dialing a name with multiple IP addresses, the timeout
     25 	// may be divided between them.
     26 	//
     27 	// With or without a timeout, the operating system may impose
     28 	// its own earlier timeout. For instance, TCP timeouts are
     29 	// often around 3 minutes.
     30 	Timeout time.Duration
     31 
     32 	// Deadline is the absolute point in time after which dials
     33 	// will fail. If Timeout is set, it may fail earlier.
     34 	// Zero means no deadline, or dependent on the operating system
     35 	// as with the Timeout option.
     36 	Deadline time.Time
     37 
     38 	// LocalAddr is the local address to use when dialing an
     39 	// address. The address must be of a compatible type for the
     40 	// network being dialed.
     41 	// If nil, a local address is automatically chosen.
     42 	LocalAddr Addr
     43 
     44 	// DualStack enables RFC 6555-compliant "Happy Eyeballs" dialing
     45 	// when the network is "tcp" and the destination is a host name
     46 	// with both IPv4 and IPv6 addresses. This allows a client to
     47 	// tolerate networks where one address family is silently broken.
     48 	DualStack bool
     49 
     50 	// FallbackDelay specifies the length of time to wait before
     51 	// spawning a fallback connection, when DualStack is enabled.
     52 	// If zero, a default delay of 300ms is used.
     53 	FallbackDelay time.Duration
     54 
     55 	// KeepAlive specifies the keep-alive period for an active
     56 	// network connection.
     57 	// If zero, keep-alives are not enabled. Network protocols
     58 	// that do not support keep-alives ignore this field.
     59 	KeepAlive time.Duration
     60 }
     61 
     62 // Return either now+Timeout or Deadline, whichever comes first.
     63 // Or zero, if neither is set.
     64 func (d *Dialer) deadline(now time.Time) time.Time {
     65 	if d.Timeout == 0 {
     66 		return d.Deadline
     67 	}
     68 	timeoutDeadline := now.Add(d.Timeout)
     69 	if d.Deadline.IsZero() || timeoutDeadline.Before(d.Deadline) {
     70 		return timeoutDeadline
     71 	} else {
     72 		return d.Deadline
     73 	}
     74 }
     75 
     76 // partialDeadline returns the deadline to use for a single address,
     77 // when multiple addresses are pending.
     78 func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
     79 	if deadline.IsZero() {
     80 		return deadline, nil
     81 	}
     82 	timeRemaining := deadline.Sub(now)
     83 	if timeRemaining <= 0 {
     84 		return time.Time{}, errTimeout
     85 	}
     86 	// Tentatively allocate equal time to each remaining address.
     87 	timeout := timeRemaining / time.Duration(addrsRemaining)
     88 	// If the time per address is too short, steal from the end of the list.
     89 	const saneMinimum = 2 * time.Second
     90 	if timeout < saneMinimum {
     91 		if timeRemaining < saneMinimum {
     92 			timeout = timeRemaining
     93 		} else {
     94 			timeout = saneMinimum
     95 		}
     96 	}
     97 	return now.Add(timeout), nil
     98 }
     99 
    100 func (d *Dialer) fallbackDelay() time.Duration {
    101 	if d.FallbackDelay > 0 {
    102 		return d.FallbackDelay
    103 	} else {
    104 		return 300 * time.Millisecond
    105 	}
    106 }
    107 
    108 func parseNetwork(net string) (afnet string, proto int, err error) {
    109 	i := last(net, ':')
    110 	if i < 0 { // no colon
    111 		switch net {
    112 		case "tcp", "tcp4", "tcp6":
    113 		case "udp", "udp4", "udp6":
    114 		case "ip", "ip4", "ip6":
    115 		case "unix", "unixgram", "unixpacket":
    116 		default:
    117 			return "", 0, UnknownNetworkError(net)
    118 		}
    119 		return net, 0, nil
    120 	}
    121 	afnet = net[:i]
    122 	switch afnet {
    123 	case "ip", "ip4", "ip6":
    124 		protostr := net[i+1:]
    125 		proto, i, ok := dtoi(protostr, 0)
    126 		if !ok || i != len(protostr) {
    127 			proto, err = lookupProtocol(protostr)
    128 			if err != nil {
    129 				return "", 0, err
    130 			}
    131 		}
    132 		return afnet, proto, nil
    133 	}
    134 	return "", 0, UnknownNetworkError(net)
    135 }
    136 
    137 func resolveAddrList(op, net, addr string, deadline time.Time) (addrList, error) {
    138 	afnet, _, err := parseNetwork(net)
    139 	if err != nil {
    140 		return nil, err
    141 	}
    142 	if op == "dial" && addr == "" {
    143 		return nil, errMissingAddress
    144 	}
    145 	switch afnet {
    146 	case "unix", "unixgram", "unixpacket":
    147 		addr, err := ResolveUnixAddr(afnet, addr)
    148 		if err != nil {
    149 			return nil, err
    150 		}
    151 		return addrList{addr}, nil
    152 	}
    153 	return internetAddrList(afnet, addr, deadline)
    154 }
    155 
    156 // Dial connects to the address on the named network.
    157 //
    158 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
    159 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
    160 // (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
    161 // "unixpacket".
    162 //
    163 // For TCP and UDP networks, addresses have the form host:port.
    164 // If host is a literal IPv6 address it must be enclosed
    165 // in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
    166 // The functions JoinHostPort and SplitHostPort manipulate addresses
    167 // in this form.
    168 //
    169 // Examples:
    170 //	Dial("tcp", "12.34.56.78:80")
    171 //	Dial("tcp", "google.com:http")
    172 //	Dial("tcp", "[2001:db8::1]:http")
    173 //	Dial("tcp", "[fe80::1%lo0]:80")
    174 //
    175 // For IP networks, the network must be "ip", "ip4" or "ip6" followed
    176 // by a colon and a protocol number or name and the addr must be a
    177 // literal IP address.
    178 //
    179 // Examples:
    180 //	Dial("ip4:1", "127.0.0.1")
    181 //	Dial("ip6:ospf", "::1")
    182 //
    183 // For Unix networks, the address must be a file system path.
    184 func Dial(network, address string) (Conn, error) {
    185 	var d Dialer
    186 	return d.Dial(network, address)
    187 }
    188 
    189 // DialTimeout acts like Dial but takes a timeout.
    190 // The timeout includes name resolution, if required.
    191 func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
    192 	d := Dialer{Timeout: timeout}
    193 	return d.Dial(network, address)
    194 }
    195 
    196 // dialContext holds common state for all dial operations.
    197 type dialContext struct {
    198 	Dialer
    199 	network, address string
    200 	finalDeadline    time.Time
    201 }
    202 
    203 // Dial connects to the address on the named network.
    204 //
    205 // See func Dial for a description of the network and address
    206 // parameters.
    207 func (d *Dialer) Dial(network, address string) (Conn, error) {
    208 	finalDeadline := d.deadline(time.Now())
    209 	addrs, err := resolveAddrList("dial", network, address, finalDeadline)
    210 	if err != nil {
    211 		return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
    212 	}
    213 
    214 	ctx := &dialContext{
    215 		Dialer:        *d,
    216 		network:       network,
    217 		address:       address,
    218 		finalDeadline: finalDeadline,
    219 	}
    220 
    221 	var primaries, fallbacks addrList
    222 	if d.DualStack && network == "tcp" {
    223 		primaries, fallbacks = addrs.partition(isIPv4)
    224 	} else {
    225 		primaries = addrs
    226 	}
    227 
    228 	var c Conn
    229 	if len(fallbacks) == 0 {
    230 		// dialParallel can accept an empty fallbacks list,
    231 		// but this shortcut avoids the goroutine/channel overhead.
    232 		c, err = dialSerial(ctx, primaries, nil)
    233 	} else {
    234 		c, err = dialParallel(ctx, primaries, fallbacks)
    235 	}
    236 
    237 	if d.KeepAlive > 0 && err == nil {
    238 		if tc, ok := c.(*TCPConn); ok {
    239 			setKeepAlive(tc.fd, true)
    240 			setKeepAlivePeriod(tc.fd, d.KeepAlive)
    241 			testHookSetKeepAlive()
    242 		}
    243 	}
    244 	return c, err
    245 }
    246 
    247 // dialParallel races two copies of dialSerial, giving the first a
    248 // head start. It returns the first established connection and
    249 // closes the others. Otherwise it returns an error from the first
    250 // primary address.
    251 func dialParallel(ctx *dialContext, primaries, fallbacks addrList) (Conn, error) {
    252 	results := make(chan dialResult) // unbuffered, so dialSerialAsync can detect race loss & cleanup
    253 	cancel := make(chan struct{})
    254 	defer close(cancel)
    255 
    256 	// Spawn the primary racer.
    257 	go dialSerialAsync(ctx, primaries, nil, cancel, results)
    258 
    259 	// Spawn the fallback racer.
    260 	fallbackTimer := time.NewTimer(ctx.fallbackDelay())
    261 	go dialSerialAsync(ctx, fallbacks, fallbackTimer, cancel, results)
    262 
    263 	var primaryErr error
    264 	for nracers := 2; nracers > 0; nracers-- {
    265 		res := <-results
    266 		// If we're still waiting for a connection, then hasten the delay.
    267 		// Otherwise, disable the Timer and let cancel take over.
    268 		if fallbackTimer.Stop() && res.error != nil {
    269 			fallbackTimer.Reset(0)
    270 		}
    271 		if res.error == nil {
    272 			return res.Conn, nil
    273 		}
    274 		if res.primary {
    275 			primaryErr = res.error
    276 		}
    277 	}
    278 	return nil, primaryErr
    279 }
    280 
    281 type dialResult struct {
    282 	Conn
    283 	error
    284 	primary bool
    285 }
    286 
    287 // dialSerialAsync runs dialSerial after some delay, and returns the
    288 // resulting connection through a channel. When racing two connections,
    289 // the primary goroutine uses a nil timer to omit the delay.
    290 func dialSerialAsync(ctx *dialContext, ras addrList, timer *time.Timer, cancel <-chan struct{}, results chan<- dialResult) {
    291 	if timer != nil {
    292 		// We're in the fallback goroutine; sleep before connecting.
    293 		select {
    294 		case <-timer.C:
    295 		case <-cancel:
    296 			return
    297 		}
    298 	}
    299 	c, err := dialSerial(ctx, ras, cancel)
    300 	select {
    301 	case results <- dialResult{c, err, timer == nil}:
    302 		// We won the race.
    303 	case <-cancel:
    304 		// The other goroutine won the race.
    305 		if c != nil {
    306 			c.Close()
    307 		}
    308 	}
    309 }
    310 
    311 // dialSerial connects to a list of addresses in sequence, returning
    312 // either the first successful connection, or the first error.
    313 func dialSerial(ctx *dialContext, ras addrList, cancel <-chan struct{}) (Conn, error) {
    314 	var firstErr error // The error from the first address is most relevant.
    315 
    316 	for i, ra := range ras {
    317 		select {
    318 		case <-cancel:
    319 			return nil, &OpError{Op: "dial", Net: ctx.network, Source: ctx.LocalAddr, Addr: ra, Err: errCanceled}
    320 		default:
    321 		}
    322 
    323 		partialDeadline, err := partialDeadline(time.Now(), ctx.finalDeadline, len(ras)-i)
    324 		if err != nil {
    325 			// Ran out of time.
    326 			if firstErr == nil {
    327 				firstErr = &OpError{Op: "dial", Net: ctx.network, Source: ctx.LocalAddr, Addr: ra, Err: err}
    328 			}
    329 			break
    330 		}
    331 
    332 		// dialTCP does not support cancelation (see golang.org/issue/11225),
    333 		// so if cancel fires, we'll continue trying to connect until the next
    334 		// timeout, or return a spurious connection for the caller to close.
    335 		dialer := func(d time.Time) (Conn, error) {
    336 			return dialSingle(ctx, ra, d)
    337 		}
    338 		c, err := dial(ctx.network, ra, dialer, partialDeadline)
    339 		if err == nil {
    340 			return c, nil
    341 		}
    342 		if firstErr == nil {
    343 			firstErr = err
    344 		}
    345 	}
    346 
    347 	if firstErr == nil {
    348 		firstErr = &OpError{Op: "dial", Net: ctx.network, Source: nil, Addr: nil, Err: errMissingAddress}
    349 	}
    350 	return nil, firstErr
    351 }
    352 
    353 // dialSingle attempts to establish and returns a single connection to
    354 // the destination address. This must be called through the OS-specific
    355 // dial function, because some OSes don't implement the deadline feature.
    356 func dialSingle(ctx *dialContext, ra Addr, deadline time.Time) (c Conn, err error) {
    357 	la := ctx.LocalAddr
    358 	if la != nil && la.Network() != ra.Network() {
    359 		return nil, &OpError{Op: "dial", Net: ctx.network, Source: la, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
    360 	}
    361 	switch ra := ra.(type) {
    362 	case *TCPAddr:
    363 		la, _ := la.(*TCPAddr)
    364 		c, err = testHookDialTCP(ctx.network, la, ra, deadline)
    365 	case *UDPAddr:
    366 		la, _ := la.(*UDPAddr)
    367 		c, err = dialUDP(ctx.network, la, ra, deadline)
    368 	case *IPAddr:
    369 		la, _ := la.(*IPAddr)
    370 		c, err = dialIP(ctx.network, la, ra, deadline)
    371 	case *UnixAddr:
    372 		la, _ := la.(*UnixAddr)
    373 		c, err = dialUnix(ctx.network, la, ra, deadline)
    374 	default:
    375 		return nil, &OpError{Op: "dial", Net: ctx.network, Source: la, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: ctx.address}}
    376 	}
    377 	if err != nil {
    378 		return nil, err // c is non-nil interface containing nil pointer
    379 	}
    380 	return c, nil
    381 }
    382 
    383 // Listen announces on the local network address laddr.
    384 // The network net must be a stream-oriented network: "tcp", "tcp4",
    385 // "tcp6", "unix" or "unixpacket".
    386 // See Dial for the syntax of laddr.
    387 func Listen(net, laddr string) (Listener, error) {
    388 	addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
    389 	if err != nil {
    390 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
    391 	}
    392 	var l Listener
    393 	switch la := addrs.first(isIPv4).(type) {
    394 	case *TCPAddr:
    395 		l, err = ListenTCP(net, la)
    396 	case *UnixAddr:
    397 		l, err = ListenUnix(net, la)
    398 	default:
    399 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
    400 	}
    401 	if err != nil {
    402 		return nil, err // l is non-nil interface containing nil pointer
    403 	}
    404 	return l, nil
    405 }
    406 
    407 // ListenPacket announces on the local network address laddr.
    408 // The network net must be a packet-oriented network: "udp", "udp4",
    409 // "udp6", "ip", "ip4", "ip6" or "unixgram".
    410 // See Dial for the syntax of laddr.
    411 func ListenPacket(net, laddr string) (PacketConn, error) {
    412 	addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
    413 	if err != nil {
    414 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
    415 	}
    416 	var l PacketConn
    417 	switch la := addrs.first(isIPv4).(type) {
    418 	case *UDPAddr:
    419 		l, err = ListenUDP(net, la)
    420 	case *IPAddr:
    421 		l, err = ListenIP(net, la)
    422 	case *UnixAddr:
    423 		l, err = ListenUnixgram(net, la)
    424 	default:
    425 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
    426 	}
    427 	if err != nil {
    428 		return nil, err // l is non-nil interface containing nil pointer
    429 	}
    430 	return l, nil
    431 }
    432