Select alive only node when fallbackTag is given

- Apply to random and roundrobin strategy
- Require observatory config

Co-authored-by: Mark Ma <38940419+mkmark@users.noreply.github.com>
This commit is contained in:
yuhan6665 2024-05-05 10:07:40 -04:00
parent eba2906d3a
commit 84eeb56ae4
4 changed files with 100 additions and 5 deletions

View file

@ -1,17 +1,63 @@
package router
import (
"context"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
)
// RandomStrategy represents a random balancing strategy
type RandomStrategy struct{}
type RandomStrategy struct{
FallbackTag string
ctx context.Context
observatory extension.Observatory
}
func (s *RandomStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx
}
func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
return strings
}
func (s *RandomStrategy) PickOutbound(candidates []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil {
aliveTags := make([]string, 0)
if result, ok := observeReport.(*observatory.ObservationResult); ok {
status := result.Status
statusMap := make(map[string]*observatory.OutboundStatus)
for _, outboundStatus := range status {
statusMap[outboundStatus.OutboundTag] = outboundStatus
}
for _, candidate := range candidates {
if outboundStatus, found := statusMap[candidate]; found {
if outboundStatus.Alive {
aliveTags = append(aliveTags, candidate)
}
} else {
// unfound candidate is considered alive
aliveTags = append(aliveTags, candidate)
}
}
candidates = aliveTags
}
}
}
count := len(candidates)
if count == 0 {
// goes to fallbackTag