github.com/moqsien/xraycore@v1.8.5/app/router/config.go (about)

     1  package router
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  
     7  	"github.com/moqsien/xraycore/common/net"
     8  	"github.com/moqsien/xraycore/features/outbound"
     9  	"github.com/moqsien/xraycore/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 "linear":
    36  			matcher, err := NewDomainMatcher(rr.Domain)
    37  			if err != nil {
    38  				return nil, newError("failed to build domain condition").Base(err)
    39  			}
    40  			conds.Add(matcher)
    41  		case "mph", "hybrid":
    42  			fallthrough
    43  		default:
    44  			matcher, err := NewMphMatcherGroup(rr.Domain)
    45  			if err != nil {
    46  				return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err)
    47  			}
    48  			newError("MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)").AtDebug().WriteToLog()
    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  		configuredKeys := make(map[string]*regexp.Regexp)
   111  		for key, value := range rr.Attributes {
   112  			configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value)
   113  		}
   114  		conds.Add(&AttributeMatcher{configuredKeys})
   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  	}
   142  }