diff --git a/src/main.rs b/src/main.rs index cea7a0c..8cfa5e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -185,12 +185,44 @@ fn resolve_reflectors( if protocol != ReflectorProtocol::Irtt && endpoint.is_ipv6() { continue; } - resolved.insert(endpoint, definition.clone()); + insert_reflector(&mut resolved, endpoint, definition.clone())?; } } Ok(resolved) } +fn insert_reflector( + reflectors: &mut HashMap, + endpoint: SocketAddr, + definition: ReflectorDefinition, +) -> anyhow::Result<()> { + if let Some(existing) = reflectors.get(&endpoint) { + let same_country = match (&existing.country, &definition.country) { + (Some(a), Some(b)) => a.eq_ignore_ascii_case(b), + (None, None) => true, + _ => false, + }; + let same_protocols = existing + .protocols + .iter() + .all(|p| definition.protocols.contains(p)) + && definition + .protocols + .iter() + .all(|p| existing.protocols.contains(p)); + if !same_country + || !same_protocols + || existing.irtt_port.unwrap_or(2112) != definition.irtt_port.unwrap_or(2112) + || existing.irtt_hmac != definition.irtt_hmac + { + anyhow::bail!("conflicting reflector definitions for resolved endpoint {endpoint}"); + } + } else { + reflectors.insert(endpoint, definition); + } + Ok(()) +} + fn setup_reflectors(settings: &Settings) -> anyhow::Result { let protocol = settings.advanced_settings.measurement_type; let configured = resolve_reflectors( @@ -201,11 +233,9 @@ fn setup_reflectors(settings: &Settings) -> anyhow::Result { )?; let bootstrap = resolve_reflectors(&settings.reflectors.bootstrap, protocol, &[], false)?; let mut reflectors = bootstrap.clone(); - reflectors.extend( - configured - .iter() - .map(|(endpoint, definition)| (*endpoint, definition.clone())), - ); + for (endpoint, definition) in &configured { + insert_reflector(&mut reflectors, *endpoint, definition.clone())?; + } if reflectors.is_empty() { anyhow::bail!("no usable reflectors for measurement protocol {protocol}"); }