Projects STRLCPY sing-box Commits 0558b3fc
🤬
  • ntp: Add write_to_system service option

  • Loading...
  • 世界 committed 1 year ago
    0558b3fc
    1 parent 99b2ab55
  • ■ ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools.go
    skipped 3 lines
    4 4   "context"
    5 5   
    6 6   box "github.com/sagernet/sing-box"
    7  - "github.com/sagernet/sing-box/option"
    8 7   E "github.com/sagernet/sing/common/exceptions"
    9 8   N "github.com/sagernet/sing/common/network"
    10 9   
    11 10   "github.com/spf13/cobra"
    12 11  )
     12 + 
     13 +var commandToolsFlagOutbound string
    13 14   
    14 15  var commandTools = &cobra.Command{
    15 16   Use: "tools",
    skipped 1 lines
    17 18  }
    18 19   
    19 20  func init() {
     21 + commandTools.PersistentFlags().StringVarP(&commandToolsFlagOutbound, "outbound", "o", "", "Use specified tag instead of default outbound")
    20 22   mainCommand.AddCommand(commandTools)
    21 23  }
    22 24   
    skipped 2 lines
    25 27   if err != nil {
    26 28   return nil, err
    27 29   }
    28  - if options.Log == nil {
    29  - options.Log = &option.LogOptions{}
    30  - }
    31  - options.Log.Disabled = true
    32 30   instance, err := box.New(context.Background(), options, nil)
    33 31   if err != nil {
    34 32   return nil, E.Cause(err, "create service")
    skipped 7 lines
    42 40   
    43 41  func createDialer(instance *box.Box, network string, outboundTag string) (N.Dialer, error) {
    44 42   if outboundTag == "" {
    45  - outbound := instance.Router().DefaultOutbound(network)
     43 + outbound := instance.Router().DefaultOutbound(N.NetworkName(network))
    46 44   if outbound == nil {
    47 45   return nil, E.New("missing default outbound")
    48 46   }
    skipped 10 lines
  • ■ ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools_connect.go
    skipped 14 lines
    15 15   "github.com/spf13/cobra"
    16 16  )
    17 17   
    18  -var (
    19  - commandConnectFlagNetwork string
    20  - commandConnectFlagOutbound string
    21  -)
     18 +var commandConnectFlagNetwork string
    22 19   
    23 20  var commandConnect = &cobra.Command{
    24 21   Use: "connect [address]",
    skipped 8 lines
    33 30  }
    34 31   
    35 32  func init() {
    36  - commandConnect.Flags().StringVar(&commandConnectFlagNetwork, "network", "tcp", "network type")
    37  - commandConnect.Flags().StringVar(&commandConnectFlagOutbound, "outbound", "", "outbound tag")
     33 + commandConnect.Flags().StringVarP(&commandConnectFlagNetwork, "network", "n", "tcp", "network type")
    38 34   commandTools.AddCommand(commandConnect)
    39 35  }
    40 36   
    skipped 8 lines
    49 45   return err
    50 46   }
    51 47   defer instance.Close()
    52  - dialer, err := createDialer(instance, commandConnectFlagNetwork, commandConnectFlagOutbound)
     48 + dialer, err := createDialer(instance, commandConnectFlagNetwork, commandToolsFlagOutbound)
    53 49   if err != nil {
    54 50   return err
    55 51   }
    skipped 23 lines
  • ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools_fetch.go
    skipped 11 lines
    12 12   "github.com/sagernet/sing-box/log"
    13 13   "github.com/sagernet/sing/common/bufio"
    14 14   M "github.com/sagernet/sing/common/metadata"
    15  - N "github.com/sagernet/sing/common/network"
    16 15   
    17 16   "github.com/spf13/cobra"
    18 17  )
    19  - 
    20  -var commandFetchFlagOutbound string
    21 18   
    22 19  var commandFetch = &cobra.Command{
    23 20   Use: "fetch",
    skipped 8 lines
    32 29  }
    33 30   
    34 31  func init() {
    35  - commandFetch.Flags().StringVar(&commandFetchFlagOutbound, "outbound", "", "outbound tag")
    36 32   commandTools.AddCommand(commandFetch)
    37 33  }
    38 34   
    skipped 8 lines
    47 43   httpClient = &http.Client{
    48 44   Transport: &http.Transport{
    49 45   DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
    50  - dialer, err := createDialer(instance, N.NetworkTCP, commandFetchFlagOutbound)
     46 + dialer, err := createDialer(instance, network, commandToolsFlagOutbound)
    51 47   if err != nil {
    52 48   return nil, err
    53 49   }
    skipped 43 lines
  • ■ ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools_synctime.go
     1 +package main
     2 + 
     3 +import (
     4 + "context"
     5 + "os"
     6 + 
     7 + "github.com/sagernet/sing-box/common/settings"
     8 + C "github.com/sagernet/sing-box/constant"
     9 + "github.com/sagernet/sing-box/log"
     10 + E "github.com/sagernet/sing/common/exceptions"
     11 + M "github.com/sagernet/sing/common/metadata"
     12 + N "github.com/sagernet/sing/common/network"
     13 + "github.com/sagernet/sing/common/ntp"
     14 + 
     15 + "github.com/spf13/cobra"
     16 +)
     17 + 
     18 +var (
     19 + commandSyncTimeFlagServer string
     20 + commandSyncTimeOutputFormat string
     21 + commandSyncTimeWrite bool
     22 +)
     23 + 
     24 +var commandSyncTime = &cobra.Command{
     25 + Use: "synctime",
     26 + Short: "Sync time using the NTP protocol",
     27 + Args: cobra.NoArgs,
     28 + Run: func(cmd *cobra.Command, args []string) {
     29 + err := syncTime()
     30 + if err != nil {
     31 + log.Fatal(err)
     32 + }
     33 + },
     34 +}
     35 + 
     36 +func init() {
     37 + commandSyncTime.Flags().StringVarP(&commandSyncTimeFlagServer, "server", "s", "time.apple.com", "Set NTP server")
     38 + commandSyncTime.Flags().StringVarP(&commandSyncTimeOutputFormat, "format", "f", C.TimeLayout, "Set output format")
     39 + commandSyncTime.Flags().BoolVarP(&commandSyncTimeWrite, "write", "w", false, "Write time to system")
     40 + commandTools.AddCommand(commandSyncTime)
     41 +}
     42 + 
     43 +func syncTime() error {
     44 + instance, err := createPreStartedClient()
     45 + if err != nil {
     46 + return err
     47 + }
     48 + dialer, err := createDialer(instance, N.NetworkUDP, commandToolsFlagOutbound)
     49 + if err != nil {
     50 + return err
     51 + }
     52 + defer instance.Close()
     53 + serverAddress := M.ParseSocksaddr(commandSyncTimeFlagServer)
     54 + if serverAddress.Port == 0 {
     55 + serverAddress.Port = 123
     56 + }
     57 + response, err := ntp.Exchange(context.Background(), dialer, serverAddress)
     58 + if err != nil {
     59 + return err
     60 + }
     61 + if commandSyncTimeWrite {
     62 + err = settings.SetSystemTime(response.Time)
     63 + if err != nil {
     64 + return E.Cause(err, "write time to system")
     65 + }
     66 + }
     67 + os.Stdout.WriteString(response.Time.Local().Format(commandSyncTimeOutputFormat))
     68 + return nil
     69 +}
     70 + 
  • ■ ■ ■ ■ ■ ■
    common/settings/time_stub.go
     1 +//go:build !(windows || linux || darwin)
     2 + 
     3 +package settings
     4 + 
     5 +import (
     6 + "os"
     7 + "time"
     8 +)
     9 + 
     10 +func SetSystemTime(nowTime time.Time) error {
     11 + return os.ErrInvalid
     12 +}
     13 + 
  • ■ ■ ■ ■ ■ ■
    common/settings/time_unix.go
     1 +//go:build linux || darwin
     2 + 
     3 +package settings
     4 + 
     5 +import (
     6 + "time"
     7 + 
     8 + "golang.org/x/sys/unix"
     9 +)
     10 + 
     11 +func SetSystemTime(nowTime time.Time) error {
     12 + timeVal := unix.NsecToTimeval(nowTime.UnixNano())
     13 + return unix.Settimeofday(&timeVal)
     14 +}
     15 + 
  • ■ ■ ■ ■ ■ ■
    common/settings/time_windows.go
     1 +package settings
     2 + 
     3 +import (
     4 + "time"
     5 + "unsafe"
     6 + 
     7 + "golang.org/x/sys/windows"
     8 +)
     9 + 
     10 +func SetSystemTime(nowTime time.Time) error {
     11 + var systemTime windows.Systemtime
     12 + systemTime.Year = uint16(nowTime.Year())
     13 + systemTime.Month = uint16(nowTime.Month())
     14 + systemTime.Day = uint16(nowTime.Day())
     15 + systemTime.Hour = uint16(nowTime.Hour())
     16 + systemTime.Minute = uint16(nowTime.Minute())
     17 + systemTime.Second = uint16(nowTime.Second())
     18 + systemTime.Milliseconds = uint16(nowTime.UnixMilli() - nowTime.Unix()*1000)
     19 + 
     20 + dllKernel32 := windows.NewLazySystemDLL("kernel32.dll")
     21 + proc := dllKernel32.NewProc("SetSystemTime")
     22 + 
     23 + _, _, err := proc.Call(
     24 + uintptr(unsafe.Pointer(&systemTime)),
     25 + )
     26 + 
     27 + if err != nil && err.Error() != "The operation completed successfully." {
     28 + return err
     29 + }
     30 + 
     31 + return nil
     32 +}
     33 + 
  • ■ ■ ■ ■ ■ ■
    constant/time.go
     1 +package constant
     2 + 
     3 +const TimeLayout = "2006-01-02 15:04:05 -0700"
     4 + 
  • ■ ■ ■ ■ ■ ■
    ntp/service.go
    skipped 5 lines
    6 6   
    7 7   "github.com/sagernet/sing-box/adapter"
    8 8   "github.com/sagernet/sing-box/common/dialer"
     9 + "github.com/sagernet/sing-box/common/settings"
     10 + C "github.com/sagernet/sing-box/constant"
    9 11   "github.com/sagernet/sing-box/option"
    10 12   E "github.com/sagernet/sing/common/exceptions"
    11 13   "github.com/sagernet/sing/common/logger"
    skipped 2 lines
    14 16   "github.com/sagernet/sing/common/ntp"
    15 17  )
    16 18   
    17  -const timeLayout = "2006-01-02 15:04:05 -0700"
    18  - 
    19 19  var _ adapter.TimeService = (*Service)(nil)
    20 20   
    21 21  type Service struct {
    22  - ctx context.Context
    23  - cancel context.CancelFunc
    24  - server M.Socksaddr
    25  - dialer N.Dialer
    26  - logger logger.Logger
    27  - 
    28  - ticker *time.Ticker
    29  - clockOffset time.Duration
     22 + ctx context.Context
     23 + cancel context.CancelFunc
     24 + server M.Socksaddr
     25 + writeToSystem bool
     26 + dialer N.Dialer
     27 + logger logger.Logger
     28 + ticker *time.Ticker
     29 + clockOffset time.Duration
    30 30  }
    31 31   
    32 32  func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) *Service {
    skipped 9 lines
    42 42   interval = 30 * time.Minute
    43 43   }
    44 44   return &Service{
    45  - ctx: ctx,
    46  - cancel: cancel,
    47  - server: server,
    48  - dialer: dialer.New(router, options.DialerOptions),
    49  - logger: logger,
    50  - ticker: time.NewTicker(interval),
     45 + ctx: ctx,
     46 + cancel: cancel,
     47 + server: server,
     48 + writeToSystem: options.WriteToSystem,
     49 + dialer: dialer.New(router, options.DialerOptions),
     50 + logger: logger,
     51 + ticker: time.NewTicker(interval),
    51 52   }
    52 53  }
    53 54   
    skipped 2 lines
    56 57   if err != nil {
    57 58   return E.Cause(err, "initialize time")
    58 59   }
    59  - s.logger.Info("updated time: ", s.TimeFunc()().Local().Format(timeLayout))
     60 + s.logger.Info("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
    60 61   go s.loopUpdate()
    61 62   return nil
    62 63  }
    skipped 19 lines
    82 83   }
    83 84   err := s.update()
    84 85   if err == nil {
    85  - s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(timeLayout))
     86 + s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
    86 87   } else {
    87 88   s.logger.Warn("update time: ", err)
    88 89   }
    skipped 6 lines
    95 96   return err
    96 97   }
    97 98   s.clockOffset = response.ClockOffset
     99 + if s.writeToSystem {
     100 + writeErr := settings.SetSystemTime(s.TimeFunc()())
     101 + if writeErr != nil {
     102 + s.logger.Warn("write time to system: ", writeErr)
     103 + }
     104 + }
    98 105   return nil
    99 106  }
    100 107   
  • ■ ■ ■ ■ ■
    option/ntp.go
    1 1  package option
    2 2   
    3 3  type NTPOptions struct {
    4  - Enabled bool `json:"enabled"`
    5  - Interval Duration `json:"interval,omitempty"`
     4 + Enabled bool `json:"enabled"`
     5 + Interval Duration `json:"interval,omitempty"`
     6 + WriteToSystem bool `json:"write_to_system,omitempty"`
    6 7   ServerOptions
    7 8   DialerOptions
    8 9  }
    skipped 1 lines
Please wait...
Page is in error, reload to recover