MCPcopy Create free account
hub / github.com/coder/coder / AwaitReachable

Method AwaitReachable

tailnet/conn.go:607–658  ·  view source on GitHub ↗

AwaitReachable pings the provided IP continually until the address is reachable. It's the callers responsibility to provide a timeout, otherwise this function will block forever.

(ctx context.Context, ip netip.Addr)

Source from the content-addressed store, hash-verified

605// address is reachable. It's the callers responsibility to provide
606// a timeout, otherwise this function will block forever.
607func (c *Conn) AwaitReachable(ctx context.Context, ip netip.Addr) bool {
608 ctx, cancel := context.WithCancel(ctx)
609 defer cancel() // Cancel all pending pings on exit.
610
611 completedCtx, completed := context.WithCancel(context.Background())
612 defer completed()
613
614 run := func() {
615 // Safety timeout, initially we'll have around 10-20 goroutines
616 // running in parallel. The exponential backoff will converge
617 // around ~1 ping / 30s, this means we'll have around 10-20
618 // goroutines pending towards the end as well.
619 ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
620 defer cancel()
621
622 // For reachability, we use TSMP ping, which pings at the IP layer, and
623 // therefore requires that wireguard and the netstack are up. If we
624 // don't wait for wireguard to be up, we could miss a handshake, and it
625 // might take 5 seconds for the handshake to be retried. A 5s initial
626 // round trip can set us up for poor TCP performance, since the initial
627 // round-trip-time sets the initial retransmit timeout.
628 _, _, _, err := c.pingWithType(ctx, ip, tailcfg.PingTSMP)
629 if err == nil {
630 completed()
631 }
632 }
633
634 eb := backoff.NewExponentialBackOff()
635 eb.MaxElapsedTime = 0
636 eb.InitialInterval = 50 * time.Millisecond
637 eb.MaxInterval = 30 * time.Second
638 // Consume the first interval since
639 // we'll fire off a ping immediately.
640 _ = eb.NextBackOff()
641
642 t := backoff.NewTicker(eb)
643 defer t.Stop()
644
645 go run()
646 for {
647 select {
648 case <-completedCtx.Done():
649 return true
650 case <-t.C:
651 // Pings can take a while, so we can run multiple
652 // in parallel to return ASAP.
653 go run()
654 case <-ctx.Done():
655 return false
656 }
657 }
658}
659
660// Closed is a channel that ends when the connection has
661// been closed.

Callers 4

TestDERPFunction · 0.95
TestTailnetFunction · 0.95
TestConn_UpdateDERPFunction · 0.95
TestConn_BlockEndpointsFunction · 0.95

Implementers 1

fakeConnvpn/tunnel_internal_test.go

Calls 4

pingWithTypeMethod · 0.95
StopMethod · 0.65
runFunction · 0.50
DoneMethod · 0.45

Tested by 4

TestDERPFunction · 0.76
TestTailnetFunction · 0.76
TestConn_UpdateDERPFunction · 0.76
TestConn_BlockEndpointsFunction · 0.76