mirror of
https://github.com/2dust/v2rayNG.git
synced 2026-10-29 06:31:54 +00:00
Fix policy group fallback isolation (#6283)
Give least-ping and least-load groups their own first member as fallback so missing or failed probes cannot send a matched routing rule through the main profile. Keep least-load on its burst observatory and preserve random and round-robin fallback behavior. Cover group isolation and observatory selection with regression tests.
This commit is contained in:
1 parent
61c4e40ec1
commit
6fe3893bfd
1 file changed
+23
-8
@@ -413,13 +413,7 @@ object CoreConfigManager {
|
||||
"${AppConfig.TAG_BALANCER_PRE}-${resolvedOutbound.tag}"
|
||||
}
|
||||
val strategyType = BalancerStrategyType.from(resolvedOutbound.profile.policyGroupType)
|
||||
val fallbackTag = if (strategyType.supportsObservatory && resolvedOutbound.profile.policyGroupTestOutbounds != false) {
|
||||
resolvedOutbound.profile.policyGroupFallbackTag
|
||||
?.takeIf { it.isNotEmpty() && it != AppConfig.TAG_PROXY }
|
||||
// Xray excludes dead random/roundRobin candidates only when fallbackTag is set;
|
||||
// without this default, an enabled empty field creates no observatory.
|
||||
?: membersToAdd.first().tag
|
||||
} else null
|
||||
val fallbackTag = resolvePolicyGroupFallbackTag(strategyType, resolvedOutbound.profile, membersToAdd.first().tag)
|
||||
val strategy = buildBalancerStrategy(
|
||||
strategyType = strategyType,
|
||||
selector = listOf(memberTagPrefix),
|
||||
@@ -435,6 +429,27 @@ object CoreConfigManager {
|
||||
policyGroupBalancerTags[resolvedOutbound.tag] = balancerTag
|
||||
}
|
||||
|
||||
internal fun resolvePolicyGroupFallbackTag(
|
||||
strategyType: BalancerStrategyType,
|
||||
profile: ProfileItem,
|
||||
firstMemberTag: String,
|
||||
): String? {
|
||||
if (strategyType.requiresObservatory || strategyType.requiresBurstObservatory) {
|
||||
// Missing or failed probes must not let a matched rule use Xray's default outbound.
|
||||
return firstMemberTag
|
||||
}
|
||||
return if (strategyType.supportsObservatory && profile.policyGroupTestOutbounds != false) {
|
||||
profile.policyGroupFallbackTag
|
||||
?.takeIf { it.isNotEmpty() && it != AppConfig.TAG_PROXY }
|
||||
// Xray excludes dead random/roundRobin candidates only when fallbackTag is set;
|
||||
// without this default, an enabled empty field creates no observatory.
|
||||
?: firstMemberTag
|
||||
} else null
|
||||
}
|
||||
|
||||
internal fun shouldUseStandardObservatory(strategyType: BalancerStrategyType, fallbackTag: String?): Boolean =
|
||||
strategyType.requiresObservatory || (strategyType.supportsObservatory && fallbackTag != null)
|
||||
|
||||
/**
|
||||
* Trim runtime sections that are not needed for latency testing.
|
||||
*/
|
||||
@@ -1249,7 +1264,7 @@ object CoreConfigManager {
|
||||
fallbackTag = fallbackTag,
|
||||
strategy = V2rayConfig.RoutingBean.StrategyObject(type = strategyType.policyGroupType)
|
||||
)
|
||||
val observatory = if (strategyType.requiresObservatory || fallbackTag != null) {
|
||||
val observatory = if (shouldUseStandardObservatory(strategyType, fallbackTag)) {
|
||||
V2rayConfig.ObservatoryObject(
|
||||
subjectSelector = selector,
|
||||
probeUrl = probeUrl,
|
||||
|
||||
Reference in new issue
Block a user