github.com/sagernet/sing-box@v1.9.0-rc.20/route/rule_set_local.go (about) 1 package route 2 3 import ( 4 "context" 5 "os" 6 "strings" 7 8 "github.com/sagernet/sing-box/adapter" 9 "github.com/sagernet/sing-box/common/srs" 10 C "github.com/sagernet/sing-box/constant" 11 "github.com/sagernet/sing-box/option" 12 E "github.com/sagernet/sing/common/exceptions" 13 F "github.com/sagernet/sing/common/format" 14 "github.com/sagernet/sing/common/json" 15 ) 16 17 var _ adapter.RuleSet = (*LocalRuleSet)(nil) 18 19 type LocalRuleSet struct { 20 rules []adapter.HeadlessRule 21 metadata adapter.RuleSetMetadata 22 } 23 24 func NewLocalRuleSet(router adapter.Router, options option.RuleSet) (*LocalRuleSet, error) { 25 var plainRuleSet option.PlainRuleSet 26 switch options.Format { 27 case C.RuleSetFormatSource, "": 28 content, err := os.ReadFile(options.LocalOptions.Path) 29 if err != nil { 30 return nil, err 31 } 32 compat, err := json.UnmarshalExtended[option.PlainRuleSetCompat](content) 33 if err != nil { 34 return nil, err 35 } 36 plainRuleSet = compat.Upgrade() 37 case C.RuleSetFormatBinary: 38 setFile, err := os.Open(options.LocalOptions.Path) 39 if err != nil { 40 return nil, err 41 } 42 plainRuleSet, err = srs.Read(setFile, false) 43 if err != nil { 44 return nil, err 45 } 46 default: 47 return nil, E.New("unknown rule set format: ", options.Format) 48 } 49 rules := make([]adapter.HeadlessRule, len(plainRuleSet.Rules)) 50 var err error 51 for i, ruleOptions := range plainRuleSet.Rules { 52 rules[i], err = NewHeadlessRule(router, ruleOptions) 53 if err != nil { 54 return nil, E.Cause(err, "parse rule_set.rules.[", i, "]") 55 } 56 } 57 var metadata adapter.RuleSetMetadata 58 metadata.ContainsProcessRule = hasHeadlessRule(plainRuleSet.Rules, isProcessHeadlessRule) 59 metadata.ContainsWIFIRule = hasHeadlessRule(plainRuleSet.Rules, isWIFIHeadlessRule) 60 metadata.ContainsIPCIDRRule = hasHeadlessRule(plainRuleSet.Rules, isIPCIDRHeadlessRule) 61 return &LocalRuleSet{rules, metadata}, nil 62 } 63 64 func (s *LocalRuleSet) Match(metadata *adapter.InboundContext) bool { 65 for _, rule := range s.rules { 66 if rule.Match(metadata) { 67 return true 68 } 69 } 70 return false 71 } 72 73 func (s *LocalRuleSet) String() string { 74 return strings.Join(F.MapToString(s.rules), " ") 75 } 76 77 func (s *LocalRuleSet) StartContext(ctx context.Context, startContext adapter.RuleSetStartContext) error { 78 return nil 79 } 80 81 func (s *LocalRuleSet) PostStart() error { 82 return nil 83 } 84 85 func (s *LocalRuleSet) Metadata() adapter.RuleSetMetadata { 86 return s.metadata 87 } 88 89 func (s *LocalRuleSet) Close() error { 90 return nil 91 }