chore: reduce internal dependencies of the ntp package

This commit is contained in:
wwqgtxx
2025-10-27 17:29:57 +08:00
parent 85c56e7446
commit ff62386f6b
6 changed files with 37 additions and 25 deletions

107
ntp/ntp/service.go Normal file
View File

@@ -0,0 +1,107 @@
package ntp
import (
"context"
"sync"
"time"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/proxydialer"
"github.com/metacubex/mihomo/log"
mihomoNtp "github.com/metacubex/mihomo/ntp"
M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/sing/common/ntp"
)
var globalSrv *Service
var globalMu sync.Mutex
type Service struct {
server M.Socksaddr
dialer proxydialer.SingDialer
ticker *time.Ticker
ctx context.Context
cancel context.CancelFunc
syncSystemTime bool
}
func ReCreateNTPService(server string, interval time.Duration, dialerProxy string, syncSystemTime bool) {
globalMu.Lock()
defer globalMu.Unlock()
if globalSrv != nil {
globalSrv.Stop()
}
if server == "" || interval <= 0 {
return
}
ctx, cancel := context.WithCancel(context.Background())
globalSrv = &Service{
server: M.ParseSocksaddr(server),
dialer: proxydialer.NewByNameSingDialer(dialerProxy, dialer.NewDialer()),
ticker: time.NewTicker(interval * time.Minute),
ctx: ctx,
cancel: cancel,
syncSystemTime: syncSystemTime,
}
globalSrv.Start()
}
func (srv *Service) Start() {
log.Infoln("NTP service start, sync system time is %t", srv.syncSystemTime)
go srv.loopUpdate()
}
func (srv *Service) Stop() {
log.Infoln("NTP service stop")
srv.cancel()
}
func (srv *Service) update() error {
var response *ntp.Response
var err error
for i := 0; i < 3; i++ {
response, err = ntp.Exchange(srv.ctx, srv.dialer, srv.server)
if err != nil {
if srv.ctx.Err() != nil {
return nil
}
continue
}
offset := response.ClockOffset
if offset > time.Duration(0) {
log.Infoln("System clock is ahead of NTP time by %s", offset)
} else if offset < time.Duration(0) {
log.Infoln("System clock is behind NTP time by %s", -offset)
}
mihomoNtp.SetOffset(offset)
if srv.syncSystemTime {
timeNow := response.Time
syncErr := setSystemTime(timeNow)
if syncErr == nil {
log.Infoln("Sync system time success: %s", timeNow.Local().Format(ntp.TimeLayout))
} else {
log.Errorln("Write time to system: %s", syncErr)
srv.syncSystemTime = false
}
}
return nil
}
return err
}
func (srv *Service) loopUpdate() {
defer mihomoNtp.SetOffset(0)
defer srv.ticker.Stop()
for {
err := srv.update()
if err != nil {
log.Warnln("Sync time failed: %s", err)
}
select {
case <-srv.ctx.Done():
return
case <-srv.ticker.C:
}
}
}

12
ntp/ntp/time_stub.go Normal file
View File

@@ -0,0 +1,12 @@
//go:build !(windows || linux || darwin)
package ntp
import (
"os"
"time"
)
func setSystemTime(nowTime time.Time) error {
return os.ErrInvalid
}

14
ntp/ntp/time_unix.go Normal file
View File

@@ -0,0 +1,14 @@
//go:build linux || darwin
package ntp
import (
"time"
"golang.org/x/sys/unix"
)
func setSystemTime(nowTime time.Time) error {
timeVal := unix.NsecToTimeval(nowTime.UnixNano())
return unix.Settimeofday(&timeVal)
}

32
ntp/ntp/time_windows.go Normal file
View File

@@ -0,0 +1,32 @@
package ntp
import (
"time"
"unsafe"
"golang.org/x/sys/windows"
)
func setSystemTime(nowTime time.Time) error {
var systemTime windows.Systemtime
systemTime.Year = uint16(nowTime.Year())
systemTime.Month = uint16(nowTime.Month())
systemTime.Day = uint16(nowTime.Day())
systemTime.Hour = uint16(nowTime.Hour())
systemTime.Minute = uint16(nowTime.Minute())
systemTime.Second = uint16(nowTime.Second())
systemTime.Milliseconds = uint16(nowTime.UnixMilli() - nowTime.Unix()*1000)
dllKernel32 := windows.NewLazySystemDLL("kernel32.dll")
proc := dllKernel32.NewProc("SetSystemTime")
_, _, err := proc.Call(
uintptr(unsafe.Pointer(&systemTime)),
)
if err != nil && err.Error() != "The operation completed successfully." {
return err
}
return nil
}