| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- package router
- import (
- "context"
- "regexp"
- "strconv"
- "strings"
- "sync"
- "github.com/xtls/xray-core/common/errors"
- )
- type weightScaler func(value, weight float64) float64
- var numberFinder = regexp.MustCompile(`\d+(\.\d+)?`)
- // NewWeightManager creates a new WeightManager with settings
- func NewWeightManager(s []*StrategyWeight, defaultWeight float64, scaler weightScaler) *WeightManager {
- return &WeightManager{
- settings: s,
- cache: make(map[string]float64),
- scaler: scaler,
- defaultWeight: defaultWeight,
- }
- }
- // WeightManager manages weights for specific settings
- type WeightManager struct {
- settings []*StrategyWeight
- cache map[string]float64
- scaler weightScaler
- defaultWeight float64
- mu sync.Mutex
- }
- // Get get the weight of specified tag
- func (s *WeightManager) Get(tag string) float64 {
- s.mu.Lock()
- defer s.mu.Unlock()
- weight, ok := s.cache[tag]
- if ok {
- return weight
- }
- weight = s.findValue(tag)
- s.cache[tag] = weight
- return weight
- }
- // Apply applies weight to the value
- func (s *WeightManager) Apply(tag string, value float64) float64 {
- return s.scaler(value, s.Get(tag))
- }
- func (s *WeightManager) findValue(tag string) float64 {
- for _, w := range s.settings {
- matched := s.getMatch(tag, w.Match, w.Regexp)
- if matched == "" {
- continue
- }
- if w.Value > 0 {
- return float64(w.Value)
- }
- // auto weight from matched
- numStr := numberFinder.FindString(matched)
- if numStr == "" {
- return s.defaultWeight
- }
- weight, err := strconv.ParseFloat(numStr, 64)
- if err != nil {
- errors.LogError(context.Background(), "unexpected error from ParseFloat: ", err)
- return s.defaultWeight
- }
- return weight
- }
- return s.defaultWeight
- }
- func (s *WeightManager) getMatch(tag, find string, isRegexp bool) string {
- if !isRegexp {
- idx := strings.Index(tag, find)
- if idx < 0 {
- return ""
- }
- return find
- }
- r, err := regexp.Compile(find)
- if err != nil {
- errors.LogError(context.Background(), "invalid regexp: ", find, "err: ", err)
- return ""
- }
- return r.FindString(tag)
- }
|