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  }