mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-04-04 20:37:37 +03:00
107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
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
|
|
}
|
|
|
|
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
|
|
}*/
|