sing-box/route/router.go

207 lines
6 KiB
Go
Raw Permalink Normal View History

2022-06-30 13:27:56 +00:00
package route
import (
"context"
2022-07-02 14:55:10 +00:00
"os"
2024-02-22 13:20:23 +00:00
"runtime"
2022-06-30 13:27:56 +00:00
2022-07-06 07:01:09 +00:00
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-box/common/taskmonitor"
2022-07-06 07:01:09 +00:00
C "github.com/sagernet/sing-box/constant"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing-box/experimental/libbox/platform"
2022-07-06 07:01:09 +00:00
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
2024-10-21 15:38:34 +00:00
R "github.com/sagernet/sing-box/route/rule"
2022-07-08 15:03:57 +00:00
E "github.com/sagernet/sing/common/exceptions"
2023-12-01 05:24:12 +00:00
"github.com/sagernet/sing/common/task"
2023-08-08 08:14:03 +00:00
"github.com/sagernet/sing/service"
2023-08-07 09:46:51 +00:00
"github.com/sagernet/sing/service/pause"
2022-06-30 13:27:56 +00:00
)
var _ adapter.Router = (*Router)(nil)
type Router struct {
2024-12-02 15:17:01 +00:00
ctx context.Context
logger log.ContextLogger
inbound adapter.InboundManager
outbound adapter.OutboundManager
dns adapter.DNSRouter
dnsTransport adapter.DNSTransportManager
connection adapter.ConnectionManager
network adapter.NetworkManager
rules []adapter.Rule
needFindProcess bool
ruleSets []adapter.RuleSet
ruleSetMap map[string]adapter.RuleSet
processSearcher process.Searcher
pauseManager pause.Manager
tracker adapter.ConnectionTracker
platformInterface platform.Interface
needWIFIState bool
started bool
2024-11-10 04:11:21 +00:00
}
2024-12-02 15:17:01 +00:00
func NewRouter(ctx context.Context, logFactory log.Factory, options option.RouteOptions, dnsOptions option.DNSOptions) *Router {
return &Router{
ctx: ctx,
logger: logFactory.NewLogger("router"),
inbound: service.FromContext[adapter.InboundManager](ctx),
outbound: service.FromContext[adapter.OutboundManager](ctx),
dns: service.FromContext[adapter.DNSRouter](ctx),
dnsTransport: service.FromContext[adapter.DNSTransportManager](ctx),
connection: service.FromContext[adapter.ConnectionManager](ctx),
network: service.FromContext[adapter.NetworkManager](ctx),
rules: make([]adapter.Rule, 0, len(options.Rules)),
ruleSetMap: make(map[string]adapter.RuleSet),
needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess,
pauseManager: service.FromContext[pause.Manager](ctx),
platformInterface: service.FromContext[platform.Interface](ctx),
needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
2022-06-30 13:27:56 +00:00
}
2024-12-02 15:17:01 +00:00
}
func (r *Router) Initialize(rules []option.Rule, ruleSets []option.RuleSet) error {
for i, options := range rules {
rule, err := R.NewRule(r.ctx, r.logger, options, false)
2022-07-07 13:47:21 +00:00
if err != nil {
2024-12-02 15:17:01 +00:00
return E.Cause(err, "parse rule[", i, "]")
2022-07-07 13:47:21 +00:00
}
2024-12-02 15:17:01 +00:00
r.rules = append(r.rules, rule)
2022-07-07 13:47:21 +00:00
}
2024-12-02 15:17:01 +00:00
for i, options := range ruleSets {
if _, exists := r.ruleSetMap[options.Tag]; exists {
return E.New("duplicate rule-set tag: ", options.Tag)
2023-12-01 05:24:12 +00:00
}
2024-12-02 15:17:01 +00:00
ruleSet, err := R.NewRuleSet(r.ctx, r.logger, options)
2023-12-01 05:24:12 +00:00
if err != nil {
2024-12-02 15:17:01 +00:00
return E.Cause(err, "parse rule-set[", i, "]")
2023-12-01 05:24:12 +00:00
}
2024-12-02 15:17:01 +00:00
r.ruleSets = append(r.ruleSets, ruleSet)
r.ruleSetMap[options.Tag] = ruleSet
2023-12-01 05:24:12 +00:00
}
2024-12-02 15:17:01 +00:00
return nil
2022-06-30 13:27:56 +00:00
}
func (r *Router) Start(stage adapter.StartStage) error {
2024-04-02 15:07:26 +00:00
monitor := taskmonitor.New(r.logger, C.StartTimeout)
switch stage {
case adapter.StartStateStart:
var cacheContext *adapter.HTTPStartContext
if len(r.ruleSets) > 0 {
monitor.Start("initialize rule-set")
cacheContext = adapter.NewHTTPStartContext()
var ruleSetStartGroup task.Group
for i, ruleSet := range r.ruleSets {
ruleSetInPlace := ruleSet
ruleSetStartGroup.Append0(func(ctx context.Context) error {
err := ruleSetInPlace.StartContext(ctx, cacheContext)
if err != nil {
return E.Cause(err, "initialize rule-set[", i, "]")
}
return nil
})
}
ruleSetStartGroup.Concurrency(5)
ruleSetStartGroup.FastFail()
err := ruleSetStartGroup.Run(r.ctx)
monitor.Finish()
if err != nil {
return err
}
}
if cacheContext != nil {
cacheContext.Close()
}
needFindProcess := r.needFindProcess
for _, ruleSet := range r.ruleSets {
metadata := ruleSet.Metadata()
if metadata.ContainsProcessRule {
needFindProcess = true
}
if metadata.ContainsWIFIRule {
2024-11-10 04:11:21 +00:00
r.needWIFIState = true
}
}
if needFindProcess {
if r.platformInterface != nil {
r.processSearcher = r.platformInterface
} else {
monitor.Start("initialize process searcher")
searcher, err := process.NewSearcher(process.Config{
Logger: r.logger,
2024-11-20 03:32:02 +00:00
PackageManager: r.network.PackageManager(),
})
monitor.Finish()
if err != nil {
if err != os.ErrInvalid {
r.logger.Warn(E.Cause(err, "create process searcher"))
}
} else {
r.processSearcher = searcher
}
}
}
2024-12-23 14:24:10 +00:00
case adapter.StartStatePostStart:
for i, rule := range r.rules {
monitor.Start("initialize rule[", i, "]")
err := rule.Start()
monitor.Finish()
if err != nil {
return E.Cause(err, "initialize rule[", i, "]")
}
}
for _, ruleSet := range r.ruleSets {
monitor.Start("post start rule_set[", ruleSet.Name(), "]")
err := ruleSet.PostStart()
monitor.Finish()
if err != nil {
return E.Cause(err, "post start rule_set[", ruleSet.Name(), "]")
}
}
r.started = true
return nil
case adapter.StartStateStarted:
for _, ruleSet := range r.ruleSetMap {
ruleSet.Cleanup()
}
runtime.GC()
2023-02-21 06:53:00 +00:00
}
2022-07-02 06:07:50 +00:00
return nil
}
2022-07-02 14:55:10 +00:00
func (r *Router) Close() error {
2024-04-02 15:07:26 +00:00
monitor := taskmonitor.New(r.logger, C.StopTimeout)
2023-04-08 00:09:28 +00:00
var err error
for i, rule := range r.rules {
monitor.Start("close rule[", i, "]")
2023-04-08 00:09:28 +00:00
err = E.Append(err, rule.Close(), func(err error) error {
return E.Cause(err, "close rule[", i, "]")
})
monitor.Finish()
2022-07-07 15:36:32 +00:00
}
2023-04-08 00:09:28 +00:00
return err
2022-07-02 14:55:10 +00:00
}
2023-12-01 05:24:12 +00:00
func (r *Router) RuleSet(tag string) (adapter.RuleSet, bool) {
ruleSet, loaded := r.ruleSetMap[tag]
return ruleSet, loaded
}
func (r *Router) NeedWIFIState() bool {
return r.needWIFIState
}
2022-07-19 14:16:49 +00:00
func (r *Router) Rules() []adapter.Rule {
return r.rules
}
2024-11-10 08:46:59 +00:00
func (r *Router) SetTracker(tracker adapter.ConnectionTracker) {
r.tracker = tracker
2022-07-14 15:06:03 +00:00
}
2022-11-06 02:36:19 +00:00
2024-11-10 04:11:21 +00:00
func (r *Router) ResetNetwork() {
2024-11-20 03:32:02 +00:00
r.network.ResetNetwork()
2024-12-02 15:17:01 +00:00
r.dns.ResetNetwork()
2024-02-22 13:20:23 +00:00
}