github.com/v2fly/v2ray-core/v4@v4.45.2/app/router/balancing.go (about)

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package router
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/v2fly/v2ray-core/v4/common/dice"
    10  	"github.com/v2fly/v2ray-core/v4/features/extension"
    11  	"github.com/v2fly/v2ray-core/v4/features/outbound"
    12  )
    13  
    14  type BalancingStrategy interface {
    15  	PickOutbound([]string) string
    16  }
    17  
    18  type RandomStrategy struct{}
    19  
    20  func (s *RandomStrategy) PickOutbound(tags []string) string {
    21  	n := len(tags)
    22  	if n == 0 {
    23  		panic("0 tags")
    24  	}
    25  
    26  	return tags[dice.Roll(n)]
    27  }
    28  
    29  type Balancer struct {
    30  	selectors []string
    31  	strategy  BalancingStrategy
    32  	ohm       outbound.Manager
    33  }
    34  
    35  func (b *Balancer) PickOutbound() (string, error) {
    36  	hs, ok := b.ohm.(outbound.HandlerSelector)
    37  	if !ok {
    38  		return "", newError("outbound.Manager is not a HandlerSelector")
    39  	}
    40  	tags := hs.Select(b.selectors)
    41  	if len(tags) == 0 {
    42  		return "", newError("no available outbounds selected")
    43  	}
    44  	tag := b.strategy.PickOutbound(tags)
    45  	if tag == "" {
    46  		return "", newError("balancing strategy returns empty tag")
    47  	}
    48  	return tag, nil
    49  }
    50  
    51  func (b *Balancer) InjectContext(ctx context.Context) {
    52  	if contextReceiver, ok := b.strategy.(extension.ContextReceiver); ok {
    53  		contextReceiver.InjectContext(ctx)
    54  	}
    55  }