123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- package script
- import (
- "context"
- "github.com/sagernet/sing-box/adapter"
- "github.com/sagernet/sing-box/common/taskmonitor"
- C "github.com/sagernet/sing-box/constant"
- "github.com/sagernet/sing-box/log"
- "github.com/sagernet/sing-box/option"
- E "github.com/sagernet/sing/common/exceptions"
- F "github.com/sagernet/sing/common/format"
- "github.com/sagernet/sing/common/logger"
- "github.com/sagernet/sing/common/task"
- )
- var _ adapter.ScriptManager = (*Manager)(nil)
- type Manager struct {
- ctx context.Context
- logger logger.ContextLogger
- scripts []adapter.Script
- scriptByName map[string]adapter.Script
- surgeCache *adapter.SurgeInMemoryCache
- }
- func NewManager(ctx context.Context, logFactory log.Factory, scripts []option.Script) (*Manager, error) {
- manager := &Manager{
- ctx: ctx,
- logger: logFactory.NewLogger("script"),
- scriptByName: make(map[string]adapter.Script),
- }
- for _, scriptOptions := range scripts {
- script, err := NewScript(ctx, logFactory.NewLogger(F.ToString("script/", scriptOptions.Type, "[", scriptOptions.Tag, "]")), scriptOptions)
- if err != nil {
- return nil, E.Cause(err, "initialize script: ", scriptOptions.Tag)
- }
- manager.scripts = append(manager.scripts, script)
- manager.scriptByName[scriptOptions.Tag] = script
- }
- return manager, nil
- }
- func (m *Manager) Start(stage adapter.StartStage) error {
- monitor := taskmonitor.New(m.logger, C.StartTimeout)
- switch stage {
- case adapter.StartStateStart:
- var cacheContext *adapter.HTTPStartContext
- if len(m.scripts) > 0 {
- monitor.Start("initialize rule-set")
- cacheContext = adapter.NewHTTPStartContext(m.ctx)
- var scriptStartGroup task.Group
- for _, script := range m.scripts {
- scriptInPlace := script
- scriptStartGroup.Append0(func(ctx context.Context) error {
- err := scriptInPlace.StartContext(ctx, cacheContext)
- if err != nil {
- return E.Cause(err, "initialize script/", scriptInPlace.Type(), "[", scriptInPlace.Tag(), "]")
- }
- return nil
- })
- }
- scriptStartGroup.Concurrency(5)
- scriptStartGroup.FastFail()
- err := scriptStartGroup.Run(m.ctx)
- monitor.Finish()
- if err != nil {
- return err
- }
- }
- if cacheContext != nil {
- cacheContext.Close()
- }
- case adapter.StartStatePostStart:
- for _, script := range m.scripts {
- monitor.Start(F.ToString("post start script/", script.Type(), "[", script.Tag(), "]"))
- err := script.PostStart()
- monitor.Finish()
- if err != nil {
- return E.Cause(err, "post start script/", script.Type(), "[", script.Tag(), "]")
- }
- }
- }
- return nil
- }
- func (m *Manager) Close() error {
- monitor := taskmonitor.New(m.logger, C.StopTimeout)
- var err error
- for _, script := range m.scripts {
- monitor.Start(F.ToString("close start script/", script.Type(), "[", script.Tag(), "]"))
- err = E.Append(err, script.Close(), func(err error) error {
- return E.Cause(err, "close script/", script.Type(), "[", script.Tag(), "]")
- })
- monitor.Finish()
- }
- return err
- }
- func (m *Manager) Scripts() []adapter.Script {
- return m.scripts
- }
- func (m *Manager) Script(name string) (adapter.Script, bool) {
- script, loaded := m.scriptByName[name]
- return script, loaded
- }
- func (m *Manager) SurgeCache() *adapter.SurgeInMemoryCache {
- if m.surgeCache == nil {
- m.surgeCache = &adapter.SurgeInMemoryCache{
- Data: make(map[string]string),
- }
- }
- return m.surgeCache
- }
|