instance.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package daemon
  2. import (
  3. "bytes"
  4. "context"
  5. "github.com/sagernet/sing-box"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/common/urltest"
  8. "github.com/sagernet/sing-box/experimental/deprecated"
  9. "github.com/sagernet/sing-box/include"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing-box/option"
  12. E "github.com/sagernet/sing/common/exceptions"
  13. "github.com/sagernet/sing/common/json"
  14. "github.com/sagernet/sing/service"
  15. "github.com/sagernet/sing/service/pause"
  16. )
  17. type Instance struct {
  18. ctx context.Context
  19. cancel context.CancelFunc
  20. instance *box.Box
  21. clashServer adapter.ClashServer
  22. cacheFile adapter.CacheFile
  23. pauseManager pause.Manager
  24. urlTestHistoryStorage *urltest.HistoryStorage
  25. }
  26. func (s *StartedService) CheckConfig(configContent string) error {
  27. options, err := parseConfig(s.ctx, configContent)
  28. if err != nil {
  29. return err
  30. }
  31. ctx, cancel := context.WithCancel(s.ctx)
  32. defer cancel()
  33. instance, err := box.New(box.Options{
  34. Context: ctx,
  35. Options: options,
  36. })
  37. if err == nil {
  38. instance.Close()
  39. }
  40. return err
  41. }
  42. func (s *StartedService) FormatConfig(configContent string) (string, error) {
  43. options, err := parseConfig(s.ctx, configContent)
  44. if err != nil {
  45. return "", err
  46. }
  47. var buffer bytes.Buffer
  48. encoder := json.NewEncoder(&buffer)
  49. encoder.SetIndent("", " ")
  50. err = encoder.Encode(options)
  51. if err != nil {
  52. return "", err
  53. }
  54. return buffer.String(), nil
  55. }
  56. type OverrideOptions struct {
  57. AutoRedirect bool
  58. IncludePackage []string
  59. ExcludePackage []string
  60. }
  61. func (s *StartedService) newInstance(profileContent string, overrideOptions *OverrideOptions) (*Instance, error) {
  62. ctx := s.ctx
  63. service.MustRegister[deprecated.Manager](ctx, new(deprecatedManager))
  64. ctx, cancel := context.WithCancel(include.Context(ctx))
  65. options, err := parseConfig(ctx, profileContent)
  66. if err != nil {
  67. cancel()
  68. return nil, err
  69. }
  70. if overrideOptions != nil {
  71. for _, inbound := range options.Inbounds {
  72. if tunInboundOptions, isTUN := inbound.Options.(*option.TunInboundOptions); isTUN {
  73. tunInboundOptions.AutoRedirect = overrideOptions.AutoRedirect
  74. tunInboundOptions.IncludePackage = append(tunInboundOptions.IncludePackage, overrideOptions.IncludePackage...)
  75. tunInboundOptions.ExcludePackage = append(tunInboundOptions.ExcludePackage, overrideOptions.ExcludePackage...)
  76. break
  77. }
  78. }
  79. }
  80. urlTestHistoryStorage := urltest.NewHistoryStorage()
  81. ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage)
  82. i := &Instance{
  83. ctx: ctx,
  84. cancel: cancel,
  85. urlTestHistoryStorage: urlTestHistoryStorage,
  86. }
  87. boxInstance, err := box.New(box.Options{
  88. Context: ctx,
  89. Options: options,
  90. PlatformLogWriter: s,
  91. })
  92. if err != nil {
  93. cancel()
  94. return nil, err
  95. }
  96. i.instance = boxInstance
  97. i.clashServer = service.FromContext[adapter.ClashServer](ctx)
  98. i.pauseManager = service.FromContext[pause.Manager](ctx)
  99. i.cacheFile = service.FromContext[adapter.CacheFile](ctx)
  100. log.SetStdLogger(boxInstance.LogFactory().Logger())
  101. return i, nil
  102. }
  103. func (i *Instance) Start() error {
  104. return i.instance.Start()
  105. }
  106. func (i *Instance) Close() error {
  107. i.cancel()
  108. i.urlTestHistoryStorage.Close()
  109. return i.instance.Close()
  110. }
  111. func (i *Instance) Box() *box.Box {
  112. return i.instance
  113. }
  114. func (i *Instance) PauseManager() pause.Manager {
  115. return i.pauseManager
  116. }
  117. func parseConfig(ctx context.Context, configContent string) (option.Options, error) {
  118. options, err := json.UnmarshalExtendedContext[option.Options](ctx, []byte(configContent))
  119. if err != nil {
  120. return option.Options{}, E.Cause(err, "decode config")
  121. }
  122. return options, nil
  123. }