Skip to content

Commit

Permalink
Merge time service to library
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Apr 10, 2024
1 parent d431e83 commit 0ea2687
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 19 deletions.
62 changes: 43 additions & 19 deletions common/ntp/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/pause"
)

const TimeLayout = "2006-01-02 15:04:05 -0700"
Expand All @@ -19,23 +21,26 @@ type TimeService interface {
}

type Options struct {
Context context.Context
Server M.Socksaddr
Interval time.Duration
Dialer N.Dialer
Logger logger.Logger
Context context.Context
Dialer N.Dialer
Logger logger.Logger
Server M.Socksaddr
Interval time.Duration
WriteToSystem bool
}

var _ TimeService = (*Service)(nil)

type Service struct {
ctx context.Context
cancel common.ContextCancelCauseFunc
server M.Socksaddr
dialer N.Dialer
logger logger.Logger
ticker *time.Ticker
clockOffset time.Duration
ctx context.Context
cancel common.ContextCancelCauseFunc
dialer N.Dialer
logger logger.Logger
server M.Socksaddr
writeToSystem bool
ticker *time.Ticker
clockOffset time.Duration
pause pause.Manager
}

func NewService(options Options) *Service {
Expand All @@ -47,9 +52,12 @@ func NewService(options Options) *Service {
destination := options.Server
if !destination.IsValid() {
destination = M.Socksaddr{
Fqdn: "time.google.com",
Fqdn: "time.apple.com",
}
}
if options.Logger == nil {
options.Logger = logger.NOP()
}
if destination.Port == 0 {
destination.Port = 123
}
Expand All @@ -66,12 +74,14 @@ func NewService(options Options) *Service {
dialer = N.SystemDialer
}
return &Service{
ctx: ctx,
cancel: cancel,
server: destination,
dialer: dialer,
logger: options.Logger,
ticker: time.NewTicker(interval),
ctx: ctx,
cancel: cancel,
dialer: dialer,
logger: options.Logger,
writeToSystem: options.WriteToSystem,
server: destination,
ticker: time.NewTicker(interval),
pause: service.FromContext[pause.Manager](ctx),
}
}

Expand Down Expand Up @@ -104,6 +114,14 @@ func (s *Service) loopUpdate() {
return
case <-s.ticker.C:
}
if s.pause != nil {
s.pause.WaitActive()
select {
case <-s.ctx.Done():
return
default:
}
}
err := s.update()
if err == nil {
s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(TimeLayout))
Expand All @@ -119,5 +137,11 @@ func (s *Service) update() error {
return err
}
s.clockOffset = response.ClockOffset
if s.writeToSystem {
writeErr := SetSystemTime(s.TimeFunc()())
if writeErr != nil {
s.logger.Warn("write time to system: ", writeErr)
}
}
return nil
}
12 changes: 12 additions & 0 deletions common/ntp/time_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build !(windows || linux || darwin)

package ntp

import (
"os"
"time"
)

func SetSystemTime(nowTime time.Time) error {
return os.ErrInvalid
}
14 changes: 14 additions & 0 deletions common/ntp/time_unix.go
Original file line number Diff line number Diff line change
@@ -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 changes: 32 additions & 0 deletions common/ntp/time_windows.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 0ea2687

Please sign in to comment.