github.com/v2fly/v2ray-core/v4@v4.45.2/infra/conf/router.go (about) 1 package conf 2 3 import ( 4 "context" 5 "encoding/json" 6 "strings" 7 8 "github.com/v2fly/v2ray-core/v4/app/router" 9 "github.com/v2fly/v2ray-core/v4/common/platform" 10 "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon" 11 "github.com/v2fly/v2ray-core/v4/infra/conf/geodata" 12 rule2 "github.com/v2fly/v2ray-core/v4/infra/conf/rule" 13 ) 14 15 type RouterRulesConfig struct { 16 RuleList []json.RawMessage `json:"rules"` 17 DomainStrategy string `json:"domainStrategy"` 18 } 19 20 // StrategyConfig represents a strategy config 21 type StrategyConfig struct { 22 Type string `json:"type"` 23 Settings *json.RawMessage `json:"settings"` 24 } 25 26 type BalancingRule struct { 27 Tag string `json:"tag"` 28 Selectors cfgcommon.StringList `json:"selector"` 29 Strategy StrategyConfig `json:"strategy"` 30 } 31 32 func (r *BalancingRule) Build() (*router.BalancingRule, error) { 33 if r.Tag == "" { 34 return nil, newError("empty balancer tag") 35 } 36 if len(r.Selectors) == 0 { 37 return nil, newError("empty selector list") 38 } 39 40 var strategy string 41 switch strings.ToLower(r.Strategy.Type) { 42 case strategyRandom, "": 43 strategy = strategyRandom 44 case strategyLeastPing: 45 strategy = "leastPing" 46 default: 47 return nil, newError("unknown balancing strategy: " + r.Strategy.Type) 48 } 49 50 return &router.BalancingRule{ 51 Tag: r.Tag, 52 OutboundSelector: []string(r.Selectors), 53 Strategy: strategy, 54 }, nil 55 } 56 57 type RouterConfig struct { 58 Settings *RouterRulesConfig `json:"settings"` // Deprecated 59 RuleList []json.RawMessage `json:"rules"` 60 DomainStrategy *string `json:"domainStrategy"` 61 Balancers []*BalancingRule `json:"balancers"` 62 63 DomainMatcher string `json:"domainMatcher"` 64 } 65 66 func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy { 67 ds := "" 68 if c.DomainStrategy != nil { 69 ds = *c.DomainStrategy 70 } else if c.Settings != nil { 71 ds = c.Settings.DomainStrategy 72 } 73 74 switch strings.ToLower(ds) { 75 case "alwaysip", "always_ip", "always-ip": 76 return router.Config_UseIp 77 case "ipifnonmatch", "ip_if_non_match", "ip-if-non-match": 78 return router.Config_IpIfNonMatch 79 case "ipondemand", "ip_on_demand", "ip-on-demand": 80 return router.Config_IpOnDemand 81 default: 82 return router.Config_AsIs 83 } 84 } 85 86 func (c *RouterConfig) Build() (*router.Config, error) { 87 config := new(router.Config) 88 config.DomainStrategy = c.getDomainStrategy() 89 90 cfgctx := cfgcommon.NewConfigureLoadingContext(context.Background()) 91 92 geoloadername := platform.NewEnvFlag("v2ray.conf.geoloader").GetValue(func() string { 93 return "standard" 94 }) 95 96 if loader, err := geodata.GetGeoDataLoader(geoloadername); err == nil { 97 cfgcommon.SetGeoDataLoader(cfgctx, loader) 98 } else { 99 return nil, newError("unable to create geo data loader ").Base(err) 100 } 101 102 var rawRuleList []json.RawMessage 103 if c != nil { 104 rawRuleList = c.RuleList 105 if c.Settings != nil { 106 c.RuleList = append(c.RuleList, c.Settings.RuleList...) 107 rawRuleList = c.RuleList 108 } 109 } 110 111 for _, rawRule := range rawRuleList { 112 rule, err := rule2.ParseRule(cfgctx, rawRule) 113 if err != nil { 114 return nil, err 115 } 116 117 if rule.DomainMatcher == "" { 118 rule.DomainMatcher = c.DomainMatcher 119 } 120 121 config.Rule = append(config.Rule, rule) 122 } 123 for _, rawBalancer := range c.Balancers { 124 balancer, err := rawBalancer.Build() 125 if err != nil { 126 return nil, err 127 } 128 config.BalancingRule = append(config.BalancingRule, balancer) 129 } 130 return config, nil 131 }