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