| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package router
- import (
- "context"
- sync "sync"
- "github.com/xtls/xray-core/common/dice"
- "github.com/xtls/xray-core/features/extension"
- "github.com/xtls/xray-core/features/outbound"
- )
- type BalancingStrategy interface {
- PickOutbound([]string) string
- }
- type RandomStrategy struct{}
- func (s *RandomStrategy) PickOutbound(tags []string) string {
- n := len(tags)
- if n == 0 {
- panic("0 tags")
- }
- return tags[dice.Roll(n)]
- }
- type RoundRobinStrategy struct {
- mu sync.Mutex
- index int
- }
- func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
- n := len(tags)
- if n == 0 {
- panic("0 tags")
- }
- s.mu.Lock()
- defer s.mu.Unlock()
- tag := tags[s.index%n]
- s.index = (s.index + 1) % n
- return tag
- }
- type Balancer struct {
- selectors []string
- strategy BalancingStrategy
- ohm outbound.Manager
- }
- func (b *Balancer) PickOutbound() (string, error) {
- hs, ok := b.ohm.(outbound.HandlerSelector)
- if !ok {
- return "", newError("outbound.Manager is not a HandlerSelector")
- }
- tags := hs.Select(b.selectors)
- if len(tags) == 0 {
- return "", newError("no available outbounds selected")
- }
- tag := b.strategy.PickOutbound(tags)
- if tag == "" {
- return "", newError("balancing strategy returns empty tag")
- }
- return tag, nil
- }
- func (b *Balancer) InjectContext(ctx context.Context) {
- if contextReceiver, ok := b.strategy.(extension.ContextReceiver); ok {
- contextReceiver.InjectContext(ctx)
- }
- }
|