diff --git a/control/controlclient/auto.go b/control/controlclient/auto.go index 0cc236e7e..be80fd791 100644 --- a/control/controlclient/auto.go +++ b/control/controlclient/auto.go @@ -12,7 +12,6 @@ "sync/atomic" "time" - "tailscale.com/health" "tailscale.com/logtail/backoff" "tailscale.com/net/sockstats" "tailscale.com/tailcfg" @@ -195,7 +194,7 @@ func NewNoStart(opts Options) (_ *Auto, err error) { c.mapCtx, c.mapCancel = context.WithCancel(context.Background()) c.mapCtx = sockstats.WithSockStats(c.mapCtx, sockstats.LabelControlClientAuto, opts.Logf) - c.unregisterHealthWatch = health.Global.RegisterWatcher(direct.ReportHealthChange) + c.unregisterHealthWatch = opts.HealthTracker.RegisterWatcher(direct.ReportHealthChange) return c, nil } @@ -316,7 +315,7 @@ func (c *Auto) authRoutine() { } if goal == nil { - health.Global.SetAuthRoutineInError(nil) + c.direct.health.SetAuthRoutineInError(nil) // Wait for user to Login or Logout. <-ctx.Done() c.logf("[v1] authRoutine: context done.") @@ -343,7 +342,7 @@ func (c *Auto) authRoutine() { f = "TryLogin" } if err != nil { - health.Global.SetAuthRoutineInError(err) + c.direct.health.SetAuthRoutineInError(err) report(err, f) bo.BackOff(ctx, err) continue @@ -373,7 +372,7 @@ func (c *Auto) authRoutine() { } // success - health.Global.SetAuthRoutineInError(nil) + c.direct.health.SetAuthRoutineInError(nil) c.mu.Lock() c.urlToVisit = "" c.loggedIn = true @@ -503,11 +502,11 @@ func (c *Auto) mapRoutine() { c.logf("[v1] mapRoutine: context done.") continue } - health.Global.SetOutOfPollNetMap() + c.direct.health.SetOutOfPollNetMap() err := c.direct.PollNetMap(ctx, mrs) - health.Global.SetOutOfPollNetMap() + c.direct.health.SetOutOfPollNetMap() c.mu.Lock() c.inMapPoll = false if c.state == StateSynchronized { diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index f59f16401..89d670f6c 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -69,6 +69,7 @@ type Direct struct { clock tstime.Clock logf logger.Logf netMon *netmon.Monitor // or nil + health *health.Tracker discoPubKey key.DiscoPublic getMachinePrivKey func() (key.MachinePrivate, error) debugFlags []string @@ -119,10 +120,11 @@ type Options struct { Hostinfo *tailcfg.Hostinfo // non-nil passes ownership, nil means to use default using os.Hostname, etc DiscoPublicKey key.DiscoPublic Logf logger.Logf - HTTPTestClient *http.Client // optional HTTP client to use (for tests only) - NoiseTestClient *http.Client // optional HTTP client to use for noise RPCs (tests only) - DebugFlags []string // debug settings to send to control - NetMon *netmon.Monitor // optional network monitor + HTTPTestClient *http.Client // optional HTTP client to use (for tests only) + NoiseTestClient *http.Client // optional HTTP client to use for noise RPCs (tests only) + DebugFlags []string // debug settings to send to control + NetMon *netmon.Monitor // optional network monitor + HealthTracker *health.Tracker PopBrowserURL func(url string) // optional func to open browser OnClientVersion func(*tailcfg.ClientVersion) // optional func to inform GUI of client version status OnControlTime func(time.Time) // optional func to notify callers of new time from control @@ -248,7 +250,7 @@ func NewDirect(opts Options) (*Direct, error) { tr := http.DefaultTransport.(*http.Transport).Clone() tr.Proxy = tshttpproxy.ProxyFromEnvironment tshttpproxy.SetTransportGetProxyConnectHeader(tr) - tr.TLSClientConfig = tlsdial.Config(serverURL.Hostname(), health.Global, tr.TLSClientConfig) + tr.TLSClientConfig = tlsdial.Config(serverURL.Hostname(), opts.HealthTracker, tr.TLSClientConfig) tr.DialContext = dnscache.Dialer(opts.Dialer.SystemDial, dnsCache) tr.DialTLSContext = dnscache.TLSDialer(opts.Dialer.SystemDial, dnsCache, tr.TLSClientConfig) tr.ForceAttemptHTTP2 = true @@ -271,6 +273,7 @@ func NewDirect(opts Options) (*Direct, error) { discoPubKey: opts.DiscoPublicKey, debugFlags: opts.DebugFlags, netMon: opts.NetMon, + health: opts.HealthTracker, skipIPForwardingCheck: opts.SkipIPForwardingCheck, pinger: opts.Pinger, popBrowser: opts.PopBrowserURL, @@ -894,10 +897,10 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap ipForwardingBroken(hi.RoutableIPs, c.netMon.InterfaceState()) { extraDebugFlags = append(extraDebugFlags, "warn-ip-forwarding-off") } - if health.Global.RouterHealth() != nil { + if c.health.RouterHealth() != nil { extraDebugFlags = append(extraDebugFlags, "warn-router-unhealthy") } - extraDebugFlags = health.Global.AppendWarnableDebugFlags(extraDebugFlags) + extraDebugFlags = c.health.AppendWarnableDebugFlags(extraDebugFlags) if hostinfo.DisabledEtcAptSource() { extraDebugFlags = append(extraDebugFlags, "warn-etc-apt-source-disabled") } @@ -970,7 +973,7 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap } defer res.Body.Close() - health.Global.NoteMapRequestHeard(request) + c.health.NoteMapRequestHeard(request) watchdogTimer.Reset(watchdogTimeout) if nu == nil { @@ -1041,7 +1044,7 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap metricMapResponseMessages.Add(1) if isStreaming { - health.Global.GotStreamedMapResponse() + c.health.GotStreamedMapResponse() } if pr := resp.PingRequest; pr != nil && c.isUniquePingRequest(pr) { diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index c4c86c210..5ab0c05ac 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -1763,6 +1763,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { DiscoPublicKey: discoPublic, DebugFlags: debugFlags, NetMon: b.sys.NetMon.Get(), + HealthTracker: b.health, Pinger: b, PopBrowserURL: b.tellClientToBrowseToURL, OnClientVersion: b.onClientVersion,