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  }