| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package daemon
- import (
- "bytes"
- "context"
- "github.com/sagernet/sing-box"
- "github.com/sagernet/sing-box/adapter"
- "github.com/sagernet/sing-box/common/urltest"
- C "github.com/sagernet/sing-box/constant"
- "github.com/sagernet/sing-box/dns"
- "github.com/sagernet/sing-box/experimental/deprecated"
- "github.com/sagernet/sing-box/include"
- "github.com/sagernet/sing-box/option"
- E "github.com/sagernet/sing/common/exceptions"
- "github.com/sagernet/sing/common/json"
- "github.com/sagernet/sing/service"
- "github.com/sagernet/sing/service/filemanager"
- "github.com/sagernet/sing/service/pause"
- )
- type Instance struct {
- ctx context.Context
- cancel context.CancelFunc
- instance *box.Box
- clashServer adapter.ClashServer
- cacheFile adapter.CacheFile
- pauseManager pause.Manager
- urlTestHistoryStorage *urltest.HistoryStorage
- }
- func (s *StartedService) baseContext() context.Context {
- dnsRegistry := include.DNSTransportRegistry()
- if s.platform != nil && s.platform.UsePlatformLocalDNSTransport() {
- dns.RegisterTransport[option.LocalDNSServerOptions](dnsRegistry, C.DNSTypeLocal, s.platform.LocalDNSTransport())
- }
- ctx := box.Context(s.ctx, include.InboundRegistry(), include.OutboundRegistry(), include.EndpointRegistry(), dnsRegistry, include.ServiceRegistry())
- ctx = filemanager.WithDefault(ctx, s.workingDirectory, s.tempDirectory, s.userID, s.groupID)
- return ctx
- }
- func (s *StartedService) CheckConfig(configContent string) error {
- ctx := s.baseContext()
- options, err := parseConfig(ctx, configContent)
- if err != nil {
- return err
- }
- ctx, cancel := context.WithCancel(ctx)
- defer cancel()
- instance, err := box.New(box.Options{
- Context: ctx,
- Options: options,
- })
- if err == nil {
- instance.Close()
- }
- return err
- }
- func (s *StartedService) FormatConfig(configContent string) (string, error) {
- options, err := parseConfig(s.baseContext(), configContent)
- if err != nil {
- return "", err
- }
- var buffer bytes.Buffer
- encoder := json.NewEncoder(&buffer)
- encoder.SetIndent("", " ")
- err = encoder.Encode(options)
- if err != nil {
- return "", err
- }
- return buffer.String(), nil
- }
- type OverrideOptions struct {
- AutoRedirect bool
- IncludePackage []string
- ExcludePackage []string
- }
- func (s *StartedService) newInstance(profileContent string, overrideOptions *OverrideOptions) (*Instance, error) {
- ctx := s.baseContext()
- service.MustRegister[deprecated.Manager](ctx, new(deprecatedManager))
- ctx, cancel := context.WithCancel(include.Context(ctx))
- options, err := parseConfig(ctx, profileContent)
- if err != nil {
- cancel()
- return nil, err
- }
- if overrideOptions != nil {
- for _, inbound := range options.Inbounds {
- if tunInboundOptions, isTUN := inbound.Options.(*option.TunInboundOptions); isTUN {
- tunInboundOptions.AutoRedirect = overrideOptions.AutoRedirect
- tunInboundOptions.IncludePackage = append(tunInboundOptions.IncludePackage, overrideOptions.IncludePackage...)
- tunInboundOptions.ExcludePackage = append(tunInboundOptions.ExcludePackage, overrideOptions.ExcludePackage...)
- break
- }
- }
- }
- urlTestHistoryStorage := urltest.NewHistoryStorage()
- ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage)
- i := &Instance{
- ctx: ctx,
- cancel: cancel,
- urlTestHistoryStorage: urlTestHistoryStorage,
- }
- boxInstance, err := box.New(box.Options{
- Context: ctx,
- Options: options,
- PlatformLogWriter: s,
- })
- if err != nil {
- cancel()
- return nil, err
- }
- i.instance = boxInstance
- i.clashServer = service.FromContext[adapter.ClashServer](ctx)
- i.pauseManager = service.FromContext[pause.Manager](ctx)
- i.cacheFile = service.FromContext[adapter.CacheFile](ctx)
- return i, nil
- }
- func (i *Instance) Start() error {
- return i.instance.Start()
- }
- func (i *Instance) Close() error {
- i.cancel()
- i.urlTestHistoryStorage.Close()
- return i.instance.Close()
- }
- func (i *Instance) Box() *box.Box {
- return i.instance
- }
- func (i *Instance) PauseManager() pause.Manager {
- return i.pauseManager
- }
- func parseConfig(ctx context.Context, configContent string) (option.Options, error) {
- options, err := json.UnmarshalExtendedContext[option.Options](ctx, []byte(configContent))
- if err != nil {
- return option.Options{}, E.Cause(err, "decode config")
- }
- return options, nil
- }
|