github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/router/strategy_random.go (about) 1 package router 2 3 import ( 4 "context" 5 6 "github.com/xtls/xray-core/app/observatory" 7 "github.com/xtls/xray-core/common" 8 "github.com/xtls/xray-core/common/dice" 9 "github.com/xtls/xray-core/core" 10 "github.com/xtls/xray-core/features/extension" 11 ) 12 13 // RandomStrategy represents a random balancing strategy 14 type RandomStrategy struct{ 15 FallbackTag string 16 17 ctx context.Context 18 observatory extension.Observatory 19 } 20 21 func (s *RandomStrategy) InjectContext(ctx context.Context) { 22 s.ctx = ctx 23 } 24 25 func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string { 26 return strings 27 } 28 29 func (s *RandomStrategy) PickOutbound(candidates []string) string { 30 if len(s.FallbackTag) > 0 && s.observatory == nil { 31 common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error { 32 s.observatory = observatory 33 return nil 34 })) 35 } 36 if s.observatory != nil { 37 observeReport, err := s.observatory.GetObservation(s.ctx) 38 if err == nil { 39 aliveTags := make([]string, 0) 40 if result, ok := observeReport.(*observatory.ObservationResult); ok { 41 status := result.Status 42 statusMap := make(map[string]*observatory.OutboundStatus) 43 for _, outboundStatus := range status { 44 statusMap[outboundStatus.OutboundTag] = outboundStatus 45 } 46 for _, candidate := range candidates { 47 if outboundStatus, found := statusMap[candidate]; found { 48 if outboundStatus.Alive { 49 aliveTags = append(aliveTags, candidate) 50 } 51 } else { 52 // unfound candidate is considered alive 53 aliveTags = append(aliveTags, candidate) 54 } 55 } 56 candidates = aliveTags 57 } 58 } 59 } 60 61 count := len(candidates) 62 if count == 0 { 63 // goes to fallbackTag 64 return "" 65 } 66 return candidates[dice.Roll(count)] 67 }