chore: cleanup ntp code

This commit is contained in:
wwqgtxx 2025-09-13 10:30:14 +08:00
parent dd7b3c28ad
commit ad69ee84a9
2 changed files with 46 additions and 49 deletions

View File

@ -231,6 +231,8 @@ func updateNTP(c *config.NTP) {
c.DialerProxy, c.DialerProxy,
c.WriteToSystem, c.WriteToSystem,
) )
} else {
ntp.ReCreateNTPService("", 0, "", false)
} }
} }

View File

@ -3,6 +3,7 @@ package ntp
import ( import (
"context" "context"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
@ -13,8 +14,8 @@ import (
"github.com/metacubex/sing/common/ntp" "github.com/metacubex/sing/common/ntp"
) )
var offset time.Duration var globalSrv atomic.Pointer[Service]
var service *Service var globalMu sync.Mutex
type Service struct { type Service struct {
server M.Socksaddr server M.Socksaddr
@ -22,15 +23,20 @@ type Service struct {
ticker *time.Ticker ticker *time.Ticker
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
mu sync.Mutex offset atomic.Int64 // [time.Duration]
syncSystemTime bool syncSystemTime bool
running bool
} }
func ReCreateNTPService(server string, interval time.Duration, dialerProxy string, syncSystemTime bool) { func ReCreateNTPService(server string, interval time.Duration, dialerProxy string, syncSystemTime bool) {
globalMu.Lock()
defer globalMu.Unlock()
service := globalSrv.Swap(nil)
if service != nil { if service != nil {
service.Stop() service.Stop()
} }
if server == "" {
return
}
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
service = &Service{ service = &Service{
server: M.ParseSocksaddr(server), server: M.ParseSocksaddr(server),
@ -41,57 +47,43 @@ func ReCreateNTPService(server string, interval time.Duration, dialerProxy strin
syncSystemTime: syncSystemTime, syncSystemTime: syncSystemTime,
} }
service.Start() service.Start()
globalSrv.Store(service)
} }
func (srv *Service) Start() { func (srv *Service) Start() {
srv.mu.Lock()
defer srv.mu.Unlock()
log.Infoln("NTP service start, sync system time is %t", srv.syncSystemTime) log.Infoln("NTP service start, sync system time is %t", srv.syncSystemTime)
err := srv.update()
if err != nil {
log.Errorln("Initialize NTP time failed: %s", err)
return
}
service.running = true
go srv.loopUpdate() go srv.loopUpdate()
} }
func (srv *Service) Stop() { func (srv *Service) Stop() {
srv.mu.Lock()
defer srv.mu.Unlock()
if service.running {
srv.ticker.Stop()
srv.cancel() srv.cancel()
service.running = false
}
} }
func (srv *Service) Running() bool { func (srv *Service) Offset() time.Duration {
if srv == nil { if srv == nil {
return false return 0
} }
srv.mu.Lock() if srv.ctx.Err() != nil {
defer srv.mu.Unlock() return time.Duration(srv.offset.Load())
return srv.running }
return 0
} }
func (srv *Service) update() error { func (srv *Service) update() error {
var response *ntp.Response var response *ntp.Response
var err error var err error
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
if response, err = ntp.Exchange(context.Background(), srv.dialer, srv.server); err == nil { response, err = ntp.Exchange(srv.ctx, srv.dialer, srv.server)
break if err != nil {
continue
} }
if i == 2 { offset := response.ClockOffset
return err
}
}
offset = response.ClockOffset
if offset > time.Duration(0) { if offset > time.Duration(0) {
log.Infoln("System clock is ahead of NTP time by %s", offset) log.Infoln("System clock is ahead of NTP time by %s", offset)
} else if offset < time.Duration(0) { } else if offset < time.Duration(0) {
log.Infoln("System clock is behind NTP time by %s", -offset) log.Infoln("System clock is behind NTP time by %s", -offset)
} }
srv.offset.Store(int64(offset))
if srv.syncSystemTime { if srv.syncSystemTime {
timeNow := response.Time timeNow := response.Time
syncErr := setSystemTime(timeNow) syncErr := setSystemTime(timeNow)
@ -104,24 +96,27 @@ func (srv *Service) update() error {
} }
return nil return nil
} }
return err
}
func (srv *Service) loopUpdate() { func (srv *Service) loopUpdate() {
defer srv.ticker.Stop()
for { for {
err := srv.update()
if err != nil {
log.Warnln("Sync time failed: %s", err)
}
select { select {
case <-srv.ctx.Done(): case <-srv.ctx.Done():
return return
case <-srv.ticker.C: case <-srv.ticker.C:
} }
err := srv.update()
if err != nil {
log.Warnln("Sync time failed: %s", err)
}
} }
} }
func Now() time.Time { func Now() time.Time {
now := time.Now() now := time.Now()
if service.Running() && offset.Abs() > 0 { if offset := globalSrv.Load().Offset(); offset.Abs() > 0 {
now = now.Add(offset) now = now.Add(offset)
} }
return now return now