package dns import ( "context" "github.com/qdm12/dns/v2/pkg/nameserver" "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" ) func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) var err error l.localResolvers, err = nameserver.GetPrivateDNSServers() if err != nil { l.logger.Error("getting private DNS servers: " + err.Error()) return } select { case <-l.start: case <-ctx.Done(): return } for ctx.Err() == nil { // Upper scope variables for the DNS forwarder server only // Their values are to be used if DOT=off var runError <-chan error var settings settings.DNS for { settings = l.GetSettings() var err error if *settings.ServerEnabled { //nolint:nestif runError, err = l.setupServer(ctx, settings) if err == nil { l.logger.Infof("ready and using DNS server with %s upstream resolvers", settings.UpstreamType) err = l.updateFiles(ctx, settings) if err != nil { l.logger.Warn("downloading block lists failed, skipping: " + err.Error()) } break } } else { err = l.usePlainServers(settings.UpstreamPlainAddresses) if err == nil { l.logger.Infof("ready and using plain DNS resolvers: %v", settings.UpstreamPlainAddresses) break } } l.signalOrSetStatus(constants.Crashed) if ctx.Err() != nil { return } l.logAndWait(ctx, err) } l.backoffTime = defaultBackoffTime l.signalOrSetStatus(constants.Running) l.userTrigger = false report, err := leakCheck(ctx, l.client) if err != nil { l.logger.Warnf("running leak check: %s", err) } else { l.logger.Infof("leak check report: %s", report) } exitLoop := l.runWait(ctx, runError) if exitLoop { return } } } func (l *Loop) runWait(ctx context.Context, runError <-chan error) (exitLoop bool) { for { select { case <-ctx.Done(): l.stopServerIfAny() // TODO revert OS and Go nameserver when exiting return true case <-l.stop: l.userTrigger = true l.logger.Info("stopping") l.stopServerIfAny() l.stopped <- struct{}{} case <-l.start: l.userTrigger = true l.logger.Info("starting") return false case err := <-runError: // unexpected error l.statusManager.SetStatus(constants.Crashed) l.logAndWait(ctx, err) return false } } } func (l *Loop) stopServerIfAny() { if l.server == nil { return } stopErr := l.server.Stop() if stopErr != nil { l.logger.Error("stopping server: " + stopErr.Error()) } }