mirror of
https://github.com/telemt/telemt.git
synced 2026-04-17 02:24:10 +03:00
@@ -329,6 +329,17 @@ pub struct UpstreamManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UpstreamManager {
|
impl UpstreamManager {
|
||||||
|
fn is_unscoped_upstream(upstream: &UpstreamConfig) -> bool {
|
||||||
|
upstream.scopes.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_check_in_default_dc_connectivity(
|
||||||
|
has_unscoped: bool,
|
||||||
|
upstream: &UpstreamConfig,
|
||||||
|
) -> bool {
|
||||||
|
!has_unscoped || Self::is_unscoped_upstream(upstream)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
configs: Vec<UpstreamConfig>,
|
configs: Vec<UpstreamConfig>,
|
||||||
connect_retry_attempts: u32,
|
connect_retry_attempts: u32,
|
||||||
@@ -1309,10 +1320,19 @@ impl UpstreamManager {
|
|||||||
.map(|(i, u)| (i, u.config.clone(), u.bind_rr.clone()))
|
.map(|(i, u)| (i, u.config.clone(), u.bind_rr.clone()))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
let has_unscoped = upstreams
|
||||||
|
.iter()
|
||||||
|
.any(|(_, cfg, _)| Self::is_unscoped_upstream(cfg));
|
||||||
|
|
||||||
let mut all_results = Vec::new();
|
let mut all_results = Vec::new();
|
||||||
|
|
||||||
for (upstream_idx, upstream_config, bind_rr) in &upstreams {
|
for (upstream_idx, upstream_config, bind_rr) in &upstreams {
|
||||||
|
// DC connectivity checks should follow the default routing path.
|
||||||
|
// Scoped upstreams are included only when no unscoped upstream exists.
|
||||||
|
if !Self::should_check_in_default_dc_connectivity(has_unscoped, upstream_config) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let (upstream_ipv4_enabled, upstream_ipv6_enabled) =
|
let (upstream_ipv4_enabled, upstream_ipv6_enabled) =
|
||||||
Self::resolve_probe_dc_families(upstream_config, ipv4_enabled, ipv6_enabled);
|
Self::resolve_probe_dc_families(upstream_config, ipv4_enabled, ipv6_enabled);
|
||||||
let upstream_name = match &upstream_config.upstream_type {
|
let upstream_name = match &upstream_config.upstream_type {
|
||||||
@@ -1720,8 +1740,25 @@ impl UpstreamManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = self.upstreams.read().await.len();
|
let target_upstreams: Vec<usize> = {
|
||||||
for i in 0..count {
|
let guard = self.upstreams.read().await;
|
||||||
|
let has_unscoped = guard
|
||||||
|
.iter()
|
||||||
|
.any(|upstream| Self::is_unscoped_upstream(&upstream.config));
|
||||||
|
guard
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, upstream)| {
|
||||||
|
Self::should_check_in_default_dc_connectivity(
|
||||||
|
has_unscoped,
|
||||||
|
&upstream.config,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(idx, _)| idx)
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in target_upstreams {
|
||||||
let (config, bind_rr) = {
|
let (config, bind_rr) = {
|
||||||
let guard = self.upstreams.read().await;
|
let guard = self.upstreams.read().await;
|
||||||
let u = &guard[i];
|
let u = &guard[i];
|
||||||
@@ -2001,6 +2038,33 @@ mod tests {
|
|||||||
assert!(!UpstreamManager::is_hard_connect_error(&error));
|
assert!(!UpstreamManager::is_hard_connect_error(&error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unscoped_selection_detects_default_route_upstream() {
|
||||||
|
let mut upstream = UpstreamConfig {
|
||||||
|
upstream_type: UpstreamType::Direct {
|
||||||
|
interface: None,
|
||||||
|
bind_addresses: None,
|
||||||
|
bindtodevice: None,
|
||||||
|
},
|
||||||
|
weight: 1,
|
||||||
|
enabled: true,
|
||||||
|
scopes: String::new(),
|
||||||
|
selected_scope: String::new(),
|
||||||
|
ipv4: None,
|
||||||
|
ipv6: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(UpstreamManager::is_unscoped_upstream(&upstream));
|
||||||
|
upstream.scopes = "local".to_string();
|
||||||
|
assert!(!UpstreamManager::is_unscoped_upstream(&upstream));
|
||||||
|
assert!(!UpstreamManager::should_check_in_default_dc_connectivity(
|
||||||
|
true, &upstream
|
||||||
|
));
|
||||||
|
assert!(UpstreamManager::should_check_in_default_dc_connectivity(
|
||||||
|
false, &upstream
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resolve_bind_address_prefers_explicit_bind_ip() {
|
fn resolve_bind_address_prefers_explicit_bind_ip() {
|
||||||
let target = "203.0.113.10:443".parse::<SocketAddr>().unwrap();
|
let target = "203.0.113.10:443".parse::<SocketAddr>().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user