Source file
src/net/dial.go
1
2
3
4
5 package net
6
7 import (
8 "context"
9 "internal/nettrace"
10 "syscall"
11 "time"
12 )
13
14
15
16 const (
17 defaultTCPKeepAlive = 15 * time.Second
18 )
19
20
21
22
23
24
25
26
27 type Dialer struct {
28
29
30
31
32
33
34
35
36
37
38
39
40 Timeout time.Duration
41
42
43
44
45
46 Deadline time.Time
47
48
49
50
51
52 LocalAddr Addr
53
54
55
56
57
58
59
60
61 DualStack bool
62
63
64
65
66
67
68
69
70
71 FallbackDelay time.Duration
72
73
74
75
76
77
78
79
80 KeepAlive time.Duration
81
82
83 Resolver *Resolver
84
85
86
87
88
89
90 Cancel <-chan struct{}
91
92
93
94
95
96
97
98 Control func(network, address string, c syscall.RawConn) error
99 }
100
101 func (d *Dialer) dualStack() bool { return d.FallbackDelay >= 0 }
102
103 func minNonzeroTime(a, b time.Time) time.Time {
104 if a.IsZero() {
105 return b
106 }
107 if b.IsZero() || a.Before(b) {
108 return a
109 }
110 return b
111 }
112
113
114
115
116
117
118
119 func (d *Dialer) deadline(ctx context.Context, now time.Time) (earliest time.Time) {
120 if d.Timeout != 0 {
121 earliest = now.Add(d.Timeout)
122 }
123 if d, ok := ctx.Deadline(); ok {
124 earliest = minNonzeroTime(earliest, d)
125 }
126 return minNonzeroTime(earliest, d.Deadline)
127 }
128
129 func (d *Dialer) resolver() *Resolver {
130 if d.Resolver != nil {
131 return d.Resolver
132 }
133 return DefaultResolver
134 }
135
136
137
138 func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
139 if deadline.IsZero() {
140 return deadline, nil
141 }
142 timeRemaining := deadline.Sub(now)
143 if timeRemaining <= 0 {
144 return time.Time{}, errTimeout
145 }
146
147 timeout := timeRemaining / time.Duration(addrsRemaining)
148
149 const saneMinimum = 2 * time.Second
150 if timeout < saneMinimum {
151 if timeRemaining < saneMinimum {
152 timeout = timeRemaining
153 } else {
154 timeout = saneMinimum
155 }
156 }
157 return now.Add(timeout), nil
158 }
159
160 func (d *Dialer) fallbackDelay() time.Duration {
161 if d.FallbackDelay > 0 {
162 return d.FallbackDelay
163 } else {
164 return 300 * time.Millisecond
165 }
166 }
167
168 func parseNetwork(ctx context.Context, network string, needsProto bool) (afnet string, proto int, err error) {
169 i := last(network, ':')
170 if i < 0 {
171 switch network {
172 case "tcp", "tcp4", "tcp6":
173 case "udp", "udp4", "udp6":
174 case "ip", "ip4", "ip6":
175 if needsProto {
176 return "", 0, UnknownNetworkError(network)
177 }
178 case "unix", "unixgram", "unixpacket":
179 default:
180 return "", 0, UnknownNetworkError(network)
181 }
182 return network, 0, nil
183 }
184 afnet = network[:i]
185 switch afnet {
186 case "ip", "ip4", "ip6":
187 protostr := network[i+1:]
188 proto, i, ok := dtoi(protostr)
189 if !ok || i != len(protostr) {
190 proto, err = lookupProtocol(ctx, protostr)
191 if err != nil {
192 return "", 0, err
193 }
194 }
195 return afnet, proto, nil
196 }
197 return "", 0, UnknownNetworkError(network)
198 }
199
200
201
202
203 func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) {
204 afnet, _, err := parseNetwork(ctx, network, true)
205 if err != nil {
206 return nil, err
207 }
208 if op == "dial" && addr == "" {
209 return nil, errMissingAddress
210 }
211 switch afnet {
212 case "unix", "unixgram", "unixpacket":
213 addr, err := ResolveUnixAddr(afnet, addr)
214 if err != nil {
215 return nil, err
216 }
217 if op == "dial" && hint != nil && addr.Network() != hint.Network() {
218 return nil, &AddrError{Err: "mismatched local address type", Addr: hint.String()}
219 }
220 return addrList{addr}, nil
221 }
222 addrs, err := r.internetAddrList(ctx, afnet, addr)
223 if err != nil || op != "dial" || hint == nil {
224 return addrs, err
225 }
226 var (
227 tcp *TCPAddr
228 udp *UDPAddr
229 ip *IPAddr
230 wildcard bool
231 )
232 switch hint := hint.(type) {
233 case *TCPAddr:
234 tcp = hint
235 wildcard = tcp.isWildcard()
236 case *UDPAddr:
237 udp = hint
238 wildcard = udp.isWildcard()
239 case *IPAddr:
240 ip = hint
241 wildcard = ip.isWildcard()
242 }
243 naddrs := addrs[:0]
244 for _, addr := range addrs {
245 if addr.Network() != hint.Network() {
246 return nil, &AddrError{Err: "mismatched local address type", Addr: hint.String()}
247 }
248 switch addr := addr.(type) {
249 case *TCPAddr:
250 if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(tcp.IP) {
251 continue
252 }
253 naddrs = append(naddrs, addr)
254 case *UDPAddr:
255 if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(udp.IP) {
256 continue
257 }
258 naddrs = append(naddrs, addr)
259 case *IPAddr:
260 if !wildcard && !addr.isWildcard() && !addr.IP.matchAddrFamily(ip.IP) {
261 continue
262 }
263 naddrs = append(naddrs, addr)
264 }
265 }
266 if len(naddrs) == 0 {
267 return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: hint.String()}
268 }
269 return naddrs, nil
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 func Dial(network, address string) (Conn, error) {
321 var d Dialer
322 return d.Dial(network, address)
323 }
324
325
326
327
328
329
330
331
332
333
334
335 func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
336 d := Dialer{Timeout: timeout}
337 return d.Dial(network, address)
338 }
339
340
341 type sysDialer struct {
342 Dialer
343 network, address string
344 }
345
346
347
348
349
350
351
352
353 func (d *Dialer) Dial(network, address string) (Conn, error) {
354 return d.DialContext(context.Background(), network, address)
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) {
376 if ctx == nil {
377 panic("nil context")
378 }
379 deadline := d.deadline(ctx, time.Now())
380 if !deadline.IsZero() {
381 if d, ok := ctx.Deadline(); !ok || deadline.Before(d) {
382 subCtx, cancel := context.WithDeadline(ctx, deadline)
383 defer cancel()
384 ctx = subCtx
385 }
386 }
387 if oldCancel := d.Cancel; oldCancel != nil {
388 subCtx, cancel := context.WithCancel(ctx)
389 defer cancel()
390 go func() {
391 select {
392 case <-oldCancel:
393 cancel()
394 case <-subCtx.Done():
395 }
396 }()
397 ctx = subCtx
398 }
399
400
401 resolveCtx := ctx
402 if trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace); trace != nil {
403 shadow := *trace
404 shadow.ConnectStart = nil
405 shadow.ConnectDone = nil
406 resolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow)
407 }
408
409 addrs, err := d.resolver().resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)
410 if err != nil {
411 return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
412 }
413
414 sd := &sysDialer{
415 Dialer: *d,
416 network: network,
417 address: address,
418 }
419
420 var primaries, fallbacks addrList
421 if d.dualStack() && network == "tcp" {
422 primaries, fallbacks = addrs.partition(isIPv4)
423 } else {
424 primaries = addrs
425 }
426
427 c, err := sd.dialParallel(ctx, primaries, fallbacks)
428 if err != nil {
429 return nil, err
430 }
431
432 if tc, ok := c.(*TCPConn); ok && d.KeepAlive >= 0 {
433 setKeepAlive(tc.fd, true)
434 ka := d.KeepAlive
435 if d.KeepAlive == 0 {
436 ka = defaultTCPKeepAlive
437 }
438 setKeepAlivePeriod(tc.fd, ka)
439 testHookSetKeepAlive(ka)
440 }
441 return c, nil
442 }
443
444
445
446
447
448 func (sd *sysDialer) dialParallel(ctx context.Context, primaries, fallbacks addrList) (Conn, error) {
449 if len(fallbacks) == 0 {
450 return sd.dialSerial(ctx, primaries)
451 }
452
453 returned := make(chan struct{})
454 defer close(returned)
455
456 type dialResult struct {
457 Conn
458 error
459 primary bool
460 done bool
461 }
462 results := make(chan dialResult)
463
464 startRacer := func(ctx context.Context, primary bool) {
465 ras := primaries
466 if !primary {
467 ras = fallbacks
468 }
469 c, err := sd.dialSerial(ctx, ras)
470 select {
471 case results <- dialResult{Conn: c, error: err, primary: primary, done: true}:
472 case <-returned:
473 if c != nil {
474 c.Close()
475 }
476 }
477 }
478
479 var primary, fallback dialResult
480
481
482 primaryCtx, primaryCancel := context.WithCancel(ctx)
483 defer primaryCancel()
484 go startRacer(primaryCtx, true)
485
486
487 fallbackTimer := time.NewTimer(sd.fallbackDelay())
488 defer fallbackTimer.Stop()
489
490 for {
491 select {
492 case <-fallbackTimer.C:
493 fallbackCtx, fallbackCancel := context.WithCancel(ctx)
494 defer fallbackCancel()
495 go startRacer(fallbackCtx, false)
496
497 case res := <-results:
498 if res.error == nil {
499 return res.Conn, nil
500 }
501 if res.primary {
502 primary = res
503 } else {
504 fallback = res
505 }
506 if primary.done && fallback.done {
507 return nil, primary.error
508 }
509 if res.primary && fallbackTimer.Stop() {
510
511
512
513
514 fallbackTimer.Reset(0)
515 }
516 }
517 }
518 }
519
520
521
522 func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) {
523 var firstErr error
524
525 for i, ra := range ras {
526 select {
527 case <-ctx.Done():
528 return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())}
529 default:
530 }
531
532 dialCtx := ctx
533 if deadline, hasDeadline := ctx.Deadline(); hasDeadline {
534 partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i)
535 if err != nil {
536
537 if firstErr == nil {
538 firstErr = &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err}
539 }
540 break
541 }
542 if partialDeadline.Before(deadline) {
543 var cancel context.CancelFunc
544 dialCtx, cancel = context.WithDeadline(ctx, partialDeadline)
545 defer cancel()
546 }
547 }
548
549 c, err := sd.dialSingle(dialCtx, ra)
550 if err == nil {
551 return c, nil
552 }
553 if firstErr == nil {
554 firstErr = err
555 }
556 }
557
558 if firstErr == nil {
559 firstErr = &OpError{Op: "dial", Net: sd.network, Source: nil, Addr: nil, Err: errMissingAddress}
560 }
561 return nil, firstErr
562 }
563
564
565
566 func (sd *sysDialer) dialSingle(ctx context.Context, ra Addr) (c Conn, err error) {
567 trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
568 if trace != nil {
569 raStr := ra.String()
570 if trace.ConnectStart != nil {
571 trace.ConnectStart(sd.network, raStr)
572 }
573 if trace.ConnectDone != nil {
574 defer func() { trace.ConnectDone(sd.network, raStr, err) }()
575 }
576 }
577 la := sd.LocalAddr
578 switch ra := ra.(type) {
579 case *TCPAddr:
580 la, _ := la.(*TCPAddr)
581 c, err = sd.dialTCP(ctx, la, ra)
582 case *UDPAddr:
583 la, _ := la.(*UDPAddr)
584 c, err = sd.dialUDP(ctx, la, ra)
585 case *IPAddr:
586 la, _ := la.(*IPAddr)
587 c, err = sd.dialIP(ctx, la, ra)
588 case *UnixAddr:
589 la, _ := la.(*UnixAddr)
590 c, err = sd.dialUnix(ctx, la, ra)
591 default:
592 return nil, &OpError{Op: "dial", Net: sd.network, Source: la, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: sd.address}}
593 }
594 if err != nil {
595 return nil, &OpError{Op: "dial", Net: sd.network, Source: la, Addr: ra, Err: err}
596 }
597 return c, nil
598 }
599
600
601 type ListenConfig struct {
602
603
604
605
606
607
608 Control func(network, address string, c syscall.RawConn) error
609
610
611
612
613
614
615
616 KeepAlive time.Duration
617 }
618
619
620
621
622
623 func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (Listener, error) {
624 addrs, err := DefaultResolver.resolveAddrList(ctx, "listen", network, address, nil)
625 if err != nil {
626 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: err}
627 }
628 sl := &sysListener{
629 ListenConfig: *lc,
630 network: network,
631 address: address,
632 }
633 var l Listener
634 la := addrs.first(isIPv4)
635 switch la := la.(type) {
636 case *TCPAddr:
637 l, err = sl.listenTCP(ctx, la)
638 case *UnixAddr:
639 l, err = sl.listenUnix(ctx, la)
640 default:
641 return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: address}}
642 }
643 if err != nil {
644 return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: err}
645 }
646 return l, nil
647 }
648
649
650
651
652
653 func (lc *ListenConfig) ListenPacket(ctx context.Context, network, address string) (PacketConn, error) {
654 addrs, err := DefaultResolver.resolveAddrList(ctx, "listen", network, address, nil)
655 if err != nil {
656 return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: nil, Err: err}
657 }
658 sl := &sysListener{
659 ListenConfig: *lc,
660 network: network,
661 address: address,
662 }
663 var c PacketConn
664 la := addrs.first(isIPv4)
665 switch la := la.(type) {
666 case *UDPAddr:
667 c, err = sl.listenUDP(ctx, la)
668 case *IPAddr:
669 c, err = sl.listenIP(ctx, la)
670 case *UnixAddr:
671 c, err = sl.listenUnixgram(ctx, la)
672 default:
673 return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: address}}
674 }
675 if err != nil {
676 return nil, &OpError{Op: "listen", Net: sl.network, Source: nil, Addr: la, Err: err}
677 }
678 return c, nil
679 }
680
681
682 type sysListener struct {
683 ListenConfig
684 network, address string
685 }
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708 func Listen(network, address string) (Listener, error) {
709 var lc ListenConfig
710 return lc.Listen(context.Background(), network, address)
711 }
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738 func ListenPacket(network, address string) (PacketConn, error) {
739 var lc ListenConfig
740 return lc.ListenPacket(context.Background(), network, address)
741 }
742
View as plain text