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