github.com/xraypb/xray-core@v1.6.6/app/router/config.go (about) 1 package router 2 3 import ( 4 "github.com/xraypb/xray-core/common/net" 5 "github.com/xraypb/xray-core/features/outbound" 6 "github.com/xraypb/xray-core/features/routing" 7 ) 8 9 // CIDRList is an alias of []*CIDR to provide sort.Interface. 10 type CIDRList []*CIDR 11 12 // Len implements sort.Interface. 13 func (l *CIDRList) Len() int { 14 return len(*l) 15 } 16 17 // Less implements sort.Interface. 18 func (l *CIDRList) Less(i int, j int) bool { 19 ci := (*l)[i] 20 cj := (*l)[j] 21 22 if len(ci.Ip) < len(cj.Ip) { 23 return true 24 } 25 26 if len(ci.Ip) > len(cj.Ip) { 27 return false 28 } 29 30 for k := 0; k < len(ci.Ip); k++ { 31 if ci.Ip[k] < cj.Ip[k] { 32 return true 33 } 34 35 if ci.Ip[k] > cj.Ip[k] { 36 return false 37 } 38 } 39 40 return ci.Prefix < cj.Prefix 41 } 42 43 // Swap implements sort.Interface. 44 func (l *CIDRList) Swap(i int, j int) { 45 (*l)[i], (*l)[j] = (*l)[j], (*l)[i] 46 } 47 48 type Rule struct { 49 Tag string 50 Balancer *Balancer 51 Condition Condition 52 } 53 54 func (r *Rule) GetTag() (string, error) { 55 if r.Balancer != nil { 56 return r.Balancer.PickOutbound() 57 } 58 return r.Tag, nil 59 } 60 61 // Apply checks rule matching of current routing context. 62 func (r *Rule) Apply(ctx routing.Context) bool { 63 return r.Condition.Apply(ctx) 64 } 65 66 func (rr *RoutingRule) BuildCondition() (Condition, error) { 67 conds := NewConditionChan() 68 69 if len(rr.Domain) > 0 { 70 switch rr.DomainMatcher { 71 case "linear": 72 matcher, err := NewDomainMatcher(rr.Domain) 73 if err != nil { 74 return nil, newError("failed to build domain condition").Base(err) 75 } 76 conds.Add(matcher) 77 case "mph", "hybrid": 78 fallthrough 79 default: 80 matcher, err := NewMphMatcherGroup(rr.Domain) 81 if err != nil { 82 return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err) 83 } 84 newError("MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)").AtDebug().WriteToLog() 85 conds.Add(matcher) 86 } 87 } 88 89 if len(rr.UserEmail) > 0 { 90 conds.Add(NewUserMatcher(rr.UserEmail)) 91 } 92 93 if len(rr.InboundTag) > 0 { 94 conds.Add(NewInboundTagMatcher(rr.InboundTag)) 95 } 96 97 if rr.PortList != nil { 98 conds.Add(NewPortMatcher(rr.PortList, false)) 99 } else if rr.PortRange != nil { 100 conds.Add(NewPortMatcher(&net.PortList{Range: []*net.PortRange{rr.PortRange}}, false)) 101 } 102 103 if rr.SourcePortList != nil { 104 conds.Add(NewPortMatcher(rr.SourcePortList, true)) 105 } 106 107 if len(rr.Networks) > 0 { 108 conds.Add(NewNetworkMatcher(rr.Networks)) 109 } else if rr.NetworkList != nil { 110 conds.Add(NewNetworkMatcher(rr.NetworkList.Network)) 111 } 112 113 if len(rr.Geoip) > 0 { 114 cond, err := NewMultiGeoIPMatcher(rr.Geoip, false) 115 if err != nil { 116 return nil, err 117 } 118 conds.Add(cond) 119 } else if len(rr.Cidr) > 0 { 120 cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.Cidr}}, false) 121 if err != nil { 122 return nil, err 123 } 124 conds.Add(cond) 125 } 126 127 if len(rr.SourceGeoip) > 0 { 128 cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true) 129 if err != nil { 130 return nil, err 131 } 132 conds.Add(cond) 133 } else if len(rr.SourceCidr) > 0 { 134 cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.SourceCidr}}, true) 135 if err != nil { 136 return nil, err 137 } 138 conds.Add(cond) 139 } 140 141 if len(rr.Protocol) > 0 { 142 conds.Add(NewProtocolMatcher(rr.Protocol)) 143 } 144 145 if len(rr.Attributes) > 0 { 146 cond, err := NewAttributeMatcher(rr.Attributes) 147 if err != nil { 148 return nil, err 149 } 150 conds.Add(cond) 151 } 152 153 if conds.Len() == 0 { 154 return nil, newError("this rule has no effective fields").AtWarning() 155 } 156 157 return conds, nil 158 } 159 160 func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) { 161 switch br.Strategy { 162 case "leastPing": 163 return &Balancer{ 164 selectors: br.OutboundSelector, 165 strategy: &LeastPingStrategy{}, 166 ohm: ohm, 167 }, nil 168 case "random": 169 fallthrough 170 default: 171 return &Balancer{ 172 selectors: br.OutboundSelector, 173 strategy: &RandomStrategy{}, 174 ohm: ohm, 175 }, nil 176 177 } 178 }