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