sing-box/ntp/service.go

107 lines
2.4 KiB
Go
Raw Permalink Normal View History

2023-02-21 06:53:00 +00:00
package ntp
import (
"context"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/settings"
C "github.com/sagernet/sing-box/constant"
2023-02-21 06:53:00 +00:00
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/ntp"
)
var _ adapter.TimeService = (*Service)(nil)
type Service struct {
ctx context.Context
cancel context.CancelFunc
server M.Socksaddr
writeToSystem bool
dialer N.Dialer
logger logger.Logger
ticker *time.Ticker
clockOffset time.Duration
2023-02-21 06:53:00 +00:00
}
func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) *Service {
ctx, cancel := context.WithCancel(ctx)
server := options.ServerOptions.Build()
if server.Port == 0 {
server.Port = 123
}
var interval time.Duration
if options.Interval > 0 {
2023-02-21 12:20:17 +00:00
interval = time.Duration(options.Interval)
2023-02-21 06:53:00 +00:00
} else {
interval = 30 * time.Minute
}
return &Service{
ctx: ctx,
cancel: cancel,
server: server,
writeToSystem: options.WriteToSystem,
dialer: dialer.New(router, options.DialerOptions),
logger: logger,
ticker: time.NewTicker(interval),
2023-02-21 06:53:00 +00:00
}
}
func (s *Service) Start() error {
err := s.update()
if err != nil {
return E.Cause(err, "initialize time")
}
s.logger.Info("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
2023-02-21 06:53:00 +00:00
go s.loopUpdate()
return nil
}
func (s *Service) Close() error {
s.ticker.Stop()
s.cancel()
return nil
}
func (s *Service) TimeFunc() func() time.Time {
return func() time.Time {
return time.Now().Add(s.clockOffset)
}
}
func (s *Service) loopUpdate() {
for {
select {
case <-s.ctx.Done():
return
case <-s.ticker.C:
}
err := s.update()
if err == nil {
s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
2023-02-21 06:53:00 +00:00
} else {
s.logger.Warn("update time: ", err)
}
}
}
func (s *Service) update() error {
response, err := ntp.Exchange(s.ctx, s.dialer, s.server)
if err != nil {
return err
}
s.clockOffset = response.ClockOffset
if s.writeToSystem {
writeErr := settings.SetSystemTime(s.TimeFunc()())
if writeErr != nil {
s.logger.Warn("write time to system: ", writeErr)
}
}
2023-02-21 06:53:00 +00:00
return nil
}