fix os.Resolve method to prefer LAN answers

fix os.Resolve method to prefer LAN answers

early return for stop cmd when not installed or stopped

increase service restart delay to 5s
This commit is contained in:
Alex
2025-02-02 11:21:39 +07:00
committed by Cuong Manh Le
parent f7a6dbe39b
commit 028475a193
4 changed files with 44 additions and 21 deletions
+11
View File
@@ -561,6 +561,17 @@ func initStopCmd() *cobra.Command {
} }
initLogging() initLogging()
status, err := s.Status()
if errors.Is(err, service.ErrNotInstalled) {
mainLog.Load().Warn().Msg("service not installed")
return
}
if status == service.StatusStopped {
mainLog.Load().Warn().Msg("service is already stopped")
return
}
if err := checkDeactivationPin(s, nil); isCheckDeactivationPinErr(err) { if err := checkDeactivationPin(s, nil); isCheckDeactivationPinErr(err) {
os.Exit(deactivationPinInvalidExitCode) os.Exit(deactivationPinInvalidExitCode)
} }
+3 -1
View File
@@ -578,7 +578,9 @@ func (p *prog) metricsEnabled() bool {
func (p *prog) Stop(s service.Service) error { func (p *prog) Stop(s service.Service) error {
p.stopDnsWatchers() p.stopDnsWatchers()
mainLog.Load().Debug().Msg("dns watchers stopped") mainLog.Load().Debug().Msg("dns watchers stopped")
mainLog.Load().Info().Msg("Service stopped") defer func() {
mainLog.Load().Info().Msg("Service stopped")
}()
close(p.stopCh) close(p.stopCh)
if err := p.deAllocateIP(); err != nil { if err := p.deAllocateIP(); err != nil {
mainLog.Load().Error().Err(err).Msg("de-allocate ip failed") mainLog.Load().Error().Err(err).Msg("de-allocate ip failed")
+3 -3
View File
@@ -68,9 +68,9 @@ func ConfigureWindowsServiceFailureActions(serviceName string) error {
// Then proceed with existing actions, e.g. setting failure actions // Then proceed with existing actions, e.g. setting failure actions
actions := []mgr.RecoveryAction{ actions := []mgr.RecoveryAction{
{Type: mgr.ServiceRestart, Delay: time.Second * 2}, // 2 seconds {Type: mgr.ServiceRestart, Delay: time.Second * 5}, // 5 seconds
{Type: mgr.ServiceRestart, Delay: time.Second * 2}, // 2 seconds {Type: mgr.ServiceRestart, Delay: time.Second * 5}, // 5 seconds
{Type: mgr.ServiceRestart, Delay: time.Second * 2}, // 2 seconds {Type: mgr.ServiceRestart, Delay: time.Second * 5}, // 5 seconds
} }
// Set the recovery actions (3 restarts, reset period = 120). // Set the recovery actions (3 restarts, reset period = 120).
+27 -17
View File
@@ -8,7 +8,6 @@ import (
"net" "net"
"net/netip" "net/netip"
"slices" "slices"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -212,6 +211,11 @@ type osResolverResult struct {
lan bool lan bool
} }
type publicResponse struct {
answer *dns.Msg
server string
}
// Resolve resolves DNS queries using pre-configured nameservers. // Resolve resolves DNS queries using pre-configured nameservers.
// Query is sent to all nameservers concurrently, and the first // Query is sent to all nameservers concurrently, and the first
// success response will be returned. // success response will be returned.
@@ -257,33 +261,37 @@ func (o *osResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
} }
logAnswer := func(server string) { logAnswer := func(server string) {
if before, _, found := strings.Cut(server, ":"); found { host, _, err := net.SplitHostPort(server)
server = before if err != nil {
// If splitting fails, fallback to the original server string
host = server
} }
Log(ctx, ProxyLogger.Load().Debug(), "got answer from nameserver: %s", server) Log(ctx, ProxyLogger.Load().Debug(), "got answer from nameserver: %s", host)
} }
var ( var (
nonSuccessAnswer *dns.Msg nonSuccessAnswer *dns.Msg
nonSuccessServer string nonSuccessServer string
controldSuccessAnswer *dns.Msg controldSuccessAnswer *dns.Msg
publicServerAnswer *dns.Msg publicResponses []publicResponse
publicServer string
) )
errs := make([]error, 0, numServers) errs := make([]error, 0, numServers)
for res := range ch { for res := range ch {
switch { switch {
case res.answer != nil && res.answer.Rcode == dns.RcodeSuccess: case res.answer != nil && res.answer.Rcode == dns.RcodeSuccess:
switch { switch {
case res.server == controldPublicDnsWithPort: case res.lan:
controldSuccessAnswer = res.answer // Always prefer LAN responses immediately
case !res.lan && publicServerAnswer == nil: Log(ctx, ProxyLogger.Load().Debug(), "using LAN answer from: %s", res.server)
publicServerAnswer = res.answer
publicServer = res.server
default:
Log(ctx, ProxyLogger.Load().Debug(), "got LAN answer from: %s", res.server)
cancel() cancel()
logAnswer(res.server) logAnswer(res.server)
return res.answer, nil return res.answer, nil
case res.server == controldPublicDnsWithPort:
controldSuccessAnswer = res.answer
case !res.lan:
publicResponses = append(publicResponses, publicResponse{
answer: res.answer,
server: res.server,
})
} }
case res.answer != nil: case res.answer != nil:
nonSuccessAnswer = res.answer nonSuccessAnswer = res.answer
@@ -293,10 +301,12 @@ func (o *osResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
} }
errs = append(errs, res.err) errs = append(errs, res.err)
} }
if publicServerAnswer != nil {
Log(ctx, ProxyLogger.Load().Debug(), "got public answer from: %s", publicServer) if len(publicResponses) > 0 {
logAnswer(publicServer) resp := publicResponses[0]
return publicServerAnswer, nil Log(ctx, ProxyLogger.Load().Debug(), "got public answer from: %s", resp.server)
logAnswer(resp.server)
return resp.answer, nil
} }
if controldSuccessAnswer != nil { if controldSuccessAnswer != nil {
Log(ctx, ProxyLogger.Load().Debug(), "got ControlD answer from: %s", controldPublicDnsWithPort) Log(ctx, ProxyLogger.Load().Debug(), "got ControlD answer from: %s", controldPublicDnsWithPort)