manager.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package script
  2. import (
  3. "context"
  4. "github.com/sagernet/sing-box/adapter"
  5. "github.com/sagernet/sing-box/common/taskmonitor"
  6. C "github.com/sagernet/sing-box/constant"
  7. "github.com/sagernet/sing-box/log"
  8. "github.com/sagernet/sing-box/option"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. F "github.com/sagernet/sing/common/format"
  11. "github.com/sagernet/sing/common/logger"
  12. "github.com/sagernet/sing/common/task"
  13. )
  14. var _ adapter.ScriptManager = (*Manager)(nil)
  15. type Manager struct {
  16. ctx context.Context
  17. logger logger.ContextLogger
  18. scripts []adapter.Script
  19. // scriptByName map[string]adapter.Script
  20. }
  21. func NewManager(ctx context.Context, logFactory log.Factory, scripts []option.Script) (*Manager, error) {
  22. manager := &Manager{
  23. ctx: ctx,
  24. logger: logFactory.NewLogger("script"),
  25. // scriptByName: make(map[string]adapter.Script),
  26. }
  27. for _, scriptOptions := range scripts {
  28. script, err := NewScript(ctx, logFactory.NewLogger(F.ToString("script/", scriptOptions.Type, "[", scriptOptions.Tag, "]")), scriptOptions)
  29. if err != nil {
  30. return nil, E.Cause(err, "initialize script: ", scriptOptions.Tag)
  31. }
  32. manager.scripts = append(manager.scripts, script)
  33. // manager.scriptByName[scriptOptions.Tag] = script
  34. }
  35. return manager, nil
  36. }
  37. func (m *Manager) Start(stage adapter.StartStage) error {
  38. monitor := taskmonitor.New(m.logger, C.StartTimeout)
  39. switch stage {
  40. case adapter.StartStateStart:
  41. var cacheContext *adapter.HTTPStartContext
  42. if len(m.scripts) > 0 {
  43. monitor.Start("initialize rule-set")
  44. cacheContext = adapter.NewHTTPStartContext(m.ctx)
  45. var scriptStartGroup task.Group
  46. for _, script := range m.scripts {
  47. scriptInPlace := script
  48. scriptStartGroup.Append0(func(ctx context.Context) error {
  49. err := scriptInPlace.StartContext(ctx, cacheContext)
  50. if err != nil {
  51. return E.Cause(err, "initialize script/", scriptInPlace.Type(), "[", scriptInPlace.Tag(), "]")
  52. }
  53. return nil
  54. })
  55. }
  56. scriptStartGroup.Concurrency(5)
  57. scriptStartGroup.FastFail()
  58. err := scriptStartGroup.Run(m.ctx)
  59. monitor.Finish()
  60. if err != nil {
  61. return err
  62. }
  63. }
  64. if cacheContext != nil {
  65. cacheContext.Close()
  66. }
  67. case adapter.StartStatePostStart:
  68. for _, script := range m.scripts {
  69. monitor.Start(F.ToString("post start script/", script.Type(), "[", script.Tag(), "]"))
  70. err := script.PostStart()
  71. monitor.Finish()
  72. if err != nil {
  73. return E.Cause(err, "post start script/", script.Type(), "[", script.Tag(), "]")
  74. }
  75. }
  76. }
  77. return nil
  78. }
  79. func (m *Manager) Close() error {
  80. monitor := taskmonitor.New(m.logger, C.StopTimeout)
  81. var err error
  82. for _, script := range m.scripts {
  83. monitor.Start(F.ToString("close start script/", script.Type(), "[", script.Tag(), "]"))
  84. err = E.Append(err, script.Close(), func(err error) error {
  85. return E.Cause(err, "close script/", script.Type(), "[", script.Tag(), "]")
  86. })
  87. monitor.Finish()
  88. }
  89. return err
  90. }
  91. func (m *Manager) Scripts() []adapter.Script {
  92. return m.scripts
  93. }
  94. /*
  95. func (m *Manager) Script(name string) (adapter.Script, bool) {
  96. script, loaded := m.scriptByName[name]
  97. return script, loaded
  98. }*/