Skip to content

Commit 3201ce9

Browse files
JimhHanJimhHan
authored andcommitted
add ruleset
1 parent b60cf02 commit 3201ce9

File tree

7 files changed

+322
-79
lines changed

7 files changed

+322
-79
lines changed

app/router/condition.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,32 @@ func (v *ConditionChan) Len() int {
4141
return len(*v)
4242
}
4343

44+
type OrConditionChan []Condition
45+
46+
func NewOrConditionChan() *OrConditionChan {
47+
var condChan OrConditionChan = make([]Condition, 0, 8)
48+
return &condChan
49+
}
50+
51+
func (v *OrConditionChan) Add(cond Condition) *OrConditionChan {
52+
*v = append(*v, cond)
53+
return v
54+
}
55+
56+
// Apply applies all conditions registered in this chan.
57+
func (v *OrConditionChan) Apply(ctx routing.Context) bool {
58+
for _, cond := range *v {
59+
if cond.Apply(ctx) {
60+
return true
61+
}
62+
}
63+
return false
64+
}
65+
66+
func (v *OrConditionChan) Len() int {
67+
return len(*v)
68+
}
69+
4470
var matcherTypeMap = map[Domain_Type]strmatcher.Type{
4571
Domain_Plain: strmatcher.Substr,
4672
Domain_Regex: strmatcher.Regex,

app/router/config.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (r *Rule) Apply(ctx routing.Context) bool {
6363
return r.Condition.Apply(ctx)
6464
}
6565

66-
func (rr *RoutingRule) BuildCondition() (Condition, error) {
66+
func (rr *RoutingRule) BuildCondition() (*ConditionChan, error) {
6767
conds := NewConditionChan()
6868

6969
if len(rr.Domain) > 0 {
@@ -138,7 +138,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
138138
conds.Add(cond)
139139
}
140140

141-
if conds.Len() == 0 {
141+
if conds.Len() == 0 && rr.RuleSet == "" {
142142
return nil, newError("this rule has no effective fields").AtWarning()
143143
}
144144

@@ -152,3 +152,23 @@ func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
152152
ohm: ohm,
153153
}, nil
154154
}
155+
156+
func (rrs *RoutingRules) BuildCondition() (Condition, error) {
157+
conds := NewOrConditionChan()
158+
159+
for _, rr := range rrs.Rules {
160+
if rr.GetTag() != "" || rr.GetBalancingTag() != "" {
161+
newError("ignoring tag in rule set").AtWarning().WriteToLog()
162+
}
163+
cond, err := rr.BuildCondition()
164+
if err != nil {
165+
return nil, err
166+
}
167+
conds.Add(cond)
168+
}
169+
if conds.Len() == 0 {
170+
return nil, newError("this rule set has no effective fields").AtWarning()
171+
}
172+
173+
return conds, nil
174+
}

app/router/config.pb.go

Lines changed: 158 additions & 60 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/router/config.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,19 @@ message RoutingRule {
119119
repeated string protocol = 9;
120120

121121
string attributes = 15;
122+
string rule_set = 17;
122123
}
123124

124125
message BalancingRule {
125126
string tag = 1;
126127
repeated string outbound_selector = 2;
127128
}
128129

130+
message RoutingRules {
131+
string identifier = 1;
132+
repeated RoutingRule rules = 2;
133+
}
134+
129135
message Config {
130136
enum DomainStrategy {
131137
// Use domain as is.
@@ -143,4 +149,5 @@ message Config {
143149
DomainStrategy domain_strategy = 1;
144150
repeated RoutingRule rule = 2;
145151
repeated BalancingRule balancing_rule = 3;
152+
repeated RoutingRules rule_sets = 4;
146153
}

app/router/router.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,30 @@ func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error
4242
r.balancers[rule.Tag] = balancer
4343
}
4444

45+
var rulSets = make(map[string]Condition)
46+
for _, rs := range config.RuleSets {
47+
cond, err := rs.BuildCondition()
48+
if err != nil {
49+
return err
50+
}
51+
rulSets[rs.Identifier] = cond
52+
}
53+
4554
r.rules = make([]*Rule, 0, len(config.Rule))
4655
for _, rule := range config.Rule {
4756
cond, err := rule.BuildCondition()
4857
if err != nil {
4958
return err
5059
}
60+
61+
if rule.RuleSet != "" {
62+
if ruleset, found := rulSets[rule.RuleSet]; found {
63+
cond.Add(ruleset)
64+
} else {
65+
return newError("undefined rule set: " + rule.RuleSet).AtError()
66+
}
67+
}
68+
5169
rr := &Rule{
5270
Condition: cond,
5371
Tag: rule.GetTag(),

infra/conf/router.go

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,39 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
3737
}, nil
3838
}
3939

40+
type RuleSet struct {
41+
Identifier string `json:"tag"`
42+
Rules []json.RawMessage `json:"rules"`
43+
}
44+
45+
func (r *RuleSet) Build() (*router.RoutingRules, error) {
46+
if r.Identifier == "" {
47+
return nil, newError("empty rule set tag")
48+
}
49+
if len(r.Rules) == 0 {
50+
return nil, newError("empty rule set")
51+
}
52+
53+
ruleSet := new(router.RoutingRules)
54+
ruleSet.Identifier = r.Identifier
55+
56+
for _, rr := range r.Rules {
57+
if rule, err := ParseRule(rr, true); err != nil {
58+
return nil, err
59+
} else {
60+
ruleSet.Rules = append(ruleSet.Rules, rule)
61+
}
62+
}
63+
64+
return ruleSet, nil
65+
}
66+
4067
type RouterConfig struct {
4168
Settings *RouterRulesConfig `json:"settings"` // Deprecated
4269
RuleList []json.RawMessage `json:"rules"`
4370
DomainStrategy *string `json:"domainStrategy"`
4471
Balancers []*BalancingRule `json:"balancers"`
72+
RuleSets []*RuleSet `json:"rule_sets"`
4573
}
4674

4775
func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
@@ -78,7 +106,7 @@ func (c *RouterConfig) Build() (*router.Config, error) {
78106
}
79107

80108
for _, rawRule := range rawRuleList {
81-
rule, err := ParseRule(rawRule)
109+
rule, err := ParseRule(rawRule, false)
82110
if err != nil {
83111
return nil, err
84112
}
@@ -91,6 +119,13 @@ func (c *RouterConfig) Build() (*router.Config, error) {
91119
}
92120
config.BalancingRule = append(config.BalancingRule, balancer)
93121
}
122+
for _, rawRuleSet := range c.RuleSets {
123+
rawRuleSet, err := rawRuleSet.Build()
124+
if err != nil {
125+
return nil, err
126+
}
127+
config.RuleSets = append(config.RuleSets, rawRuleSet)
128+
}
94129
return config, nil
95130
}
96131

@@ -456,7 +491,7 @@ func toCidrList(ips StringList) ([]*router.GeoIP, error) {
456491
return geoipList, nil
457492
}
458493

459-
func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
494+
func parseFieldRule(msg json.RawMessage, skipTargetCheck bool) (*router.RoutingRule, error) {
460495
type RawFieldRule struct {
461496
RouterRule
462497
Domain *StringList `json:"domain"`
@@ -469,6 +504,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
469504
InboundTag *StringList `json:"inboundTag"`
470505
Protocols *StringList `json:"protocol"`
471506
Attributes string `json:"attrs"`
507+
RuleSet string `json:"rule_set"`
472508
}
473509
rawFieldRule := new(RawFieldRule)
474510
err := json.Unmarshal(msg, rawFieldRule)
@@ -477,17 +513,20 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
477513
}
478514

479515
rule := new(router.RoutingRule)
480-
switch {
481-
case len(rawFieldRule.OutboundTag) > 0:
482-
rule.TargetTag = &router.RoutingRule_Tag{
483-
Tag: rawFieldRule.OutboundTag,
484-
}
485-
case len(rawFieldRule.BalancerTag) > 0:
486-
rule.TargetTag = &router.RoutingRule_BalancingTag{
487-
BalancingTag: rawFieldRule.BalancerTag,
516+
517+
if !skipTargetCheck {
518+
switch {
519+
case len(rawFieldRule.OutboundTag) > 0:
520+
rule.TargetTag = &router.RoutingRule_Tag{
521+
Tag: rawFieldRule.OutboundTag,
522+
}
523+
case len(rawFieldRule.BalancerTag) > 0:
524+
rule.TargetTag = &router.RoutingRule_BalancingTag{
525+
BalancingTag: rawFieldRule.BalancerTag,
526+
}
527+
default:
528+
return nil, newError("neither outboundTag nor balancerTag is specified in routing rule")
488529
}
489-
default:
490-
return nil, newError("neither outboundTag nor balancerTag is specified in routing rule")
491530
}
492531

493532
if rawFieldRule.Domain != nil {
@@ -550,17 +589,19 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
550589
rule.Attributes = rawFieldRule.Attributes
551590
}
552591

592+
rule.RuleSet = rawFieldRule.RuleSet
593+
553594
return rule, nil
554595
}
555596

556-
func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
597+
func ParseRule(msg json.RawMessage, skipTargetCheck bool) (*router.RoutingRule, error) {
557598
rawRule := new(RouterRule)
558599
err := json.Unmarshal(msg, rawRule)
559600
if err != nil {
560601
return nil, newError("invalid router rule").Base(err)
561602
}
562603
if rawRule.Type == "field" {
563-
fieldrule, err := parseFieldRule(msg)
604+
fieldrule, err := parseFieldRule(msg, skipTargetCheck)
564605
if err != nil {
565606
return nil, newError("invalid field rule").Base(err)
566607
}

infra/conf/xray.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,6 @@ func (c *Config) Override(o *Config, fn string) {
391391
if o.LogConfig != nil {
392392
c.LogConfig = o.LogConfig
393393
}
394-
if o.RouterConfig != nil {
395-
c.RouterConfig = o.RouterConfig
396-
}
397394
if o.DNSConfig != nil {
398395
c.DNSConfig = o.DNSConfig
399396
}
@@ -462,6 +459,42 @@ func (c *Config) Override(o *Config, fn string) {
462459
c.OutboundConfigs = o.OutboundConfigs
463460
}
464461
}
462+
463+
if o.RouterConfig != nil {
464+
if len(o.RouterConfig.Balancers) > 0 {
465+
c.RouterConfig.Balancers = o.RouterConfig.Balancers
466+
}
467+
if o.RouterConfig.DomainStrategy != nil {
468+
c.RouterConfig.DomainStrategy = o.RouterConfig.DomainStrategy
469+
}
470+
if len(o.RouterConfig.RuleList) > 0 {
471+
c.RouterConfig.RuleList = o.RouterConfig.RuleList
472+
}
473+
if o.RouterConfig.Settings != nil {
474+
c.RouterConfig.Settings = o.RouterConfig.Settings
475+
}
476+
477+
if len(o.RouterConfig.RuleSets) > 0 {
478+
if len(c.RouterConfig.RuleSets) > 0 {
479+
for _, set := range o.RouterConfig.RuleSets {
480+
found := false
481+
for _, cset := range c.RouterConfig.RuleSets {
482+
if cset.Identifier == set.Identifier {
483+
found = true
484+
}
485+
}
486+
487+
if found {
488+
ctllog.Println("[", fn, "] found existing rule set: "+set.Identifier+", ignoring")
489+
} else {
490+
c.RouterConfig.RuleSets = append(c.RouterConfig.RuleSets, set)
491+
}
492+
}
493+
} else {
494+
c.RouterConfig.RuleSets = o.RouterConfig.RuleSets
495+
}
496+
}
497+
}
465498
}
466499

467500
func applyTransportConfig(s *StreamConfig, t *TransportConfig) {

0 commit comments

Comments
 (0)