diff --git a/client/internal/connect.go b/client/internal/connect.go index 515321f7f..36b340cfb 100644 --- a/client/internal/connect.go +++ b/client/internal/connect.go @@ -158,6 +158,7 @@ func (c *ConnectClient) run( } defer c.statusRecorder.ClientStop() + runningChanOpen := true operation := func() error { // if context cancelled we not start new backoff cycle if c.isContextCancelled() { @@ -267,6 +268,12 @@ func (c *ConnectClient) run( checks := loginResp.GetChecks() c.engineMutex.Lock() + if c.engine != nil && c.engine.ctx.Err() != nil { + log.Info("Stopping Netbird Engine") + if err := c.engine.Stop(); err != nil { + log.Errorf("Failed to stop engine: %v", err) + } + } c.engine = NewEngineWithProbes(engineCtx, cancel, signalClient, mgmClient, relayManager, engineConfig, mobileDependency, c.statusRecorder, probes, checks) c.engineMutex.Unlock() @@ -279,9 +286,10 @@ func (c *ConnectClient) run( log.Infof("Netbird engine started, the IP is: %s", peerConfig.GetAddress()) state.Set(StatusConnected) - if runningChan != nil { + if runningChan != nil && runningChanOpen { runningChan <- nil close(runningChan) + runningChanOpen = false } <-engineCtx.Done() diff --git a/client/internal/engine.go b/client/internal/engine.go index 47a36c4bf..b0deb5a29 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -1115,10 +1115,7 @@ func (e *Engine) close() { } // stop/restore DNS first so dbus and friends don't complain because of a missing interface - if e.dnsServer != nil { - e.dnsServer.Stop() - e.dnsServer = nil - } + e.stopDNSServer() if e.routeManager != nil { e.routeManager.Stop() @@ -1360,12 +1357,16 @@ func (e *Engine) probeTURNs() []relay.ProbeResult { } func (e *Engine) restartEngine() { + log.Info("restarting engine") + CtxGetState(e.ctx).Set(StatusConnecting) + if err := e.Stop(); err != nil { log.Errorf("Failed to stop engine: %v", err) } - if err := e.Start(); err != nil { - log.Errorf("Failed to start engine: %v", err) - } + + _ = CtxGetState(e.ctx).Wrap(ErrResetConnection) + log.Infof("cancelling client, engine will be recreated") + e.clientCancel() } func (e *Engine) startNetworkMonitor() { @@ -1387,6 +1388,7 @@ func (e *Engine) startNetworkMonitor() { defer mu.Unlock() if debounceTimer != nil { + log.Infof("Network monitor: detected network change, reset debounceTimer") debounceTimer.Stop() } @@ -1396,7 +1398,7 @@ func (e *Engine) startNetworkMonitor() { mu.Lock() defer mu.Unlock() - log.Infof("Network monitor detected network change, restarting engine") + log.Infof("Network monitor: detected network change, restarting engine") e.restartEngine() }) }) @@ -1421,6 +1423,20 @@ func (e *Engine) addrViaRoutes(addr netip.Addr) (bool, netip.Prefix, error) { return false, netip.Prefix{}, nil } +func (e *Engine) stopDNSServer() { + err := fmt.Errorf("DNS server stopped") + nsGroupStates := e.statusRecorder.GetDNSStates() + for i := range nsGroupStates { + nsGroupStates[i].Enabled = false + nsGroupStates[i].Error = err + } + e.statusRecorder.UpdateDNSStates(nsGroupStates) + if e.dnsServer != nil { + e.dnsServer.Stop() + e.dnsServer = nil + } +} + // isChecksEqual checks if two slices of checks are equal. func isChecksEqual(checks []*mgmProto.Checks, oChecks []*mgmProto.Checks) bool { return slices.EqualFunc(checks, oChecks, func(checks, oChecks *mgmProto.Checks) bool {