use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::OnceLock;
use tokio::sync::watch;
fn channel() -> &'static watch::Sender<Option<Ipv4Addr>> {
static TX: OnceLock<watch::Sender<Option<Ipv4Addr>>> = OnceLock::new();
TX.get_or_init(|| watch::channel(None).0)
}
pub fn publish(address: Option<Ipv4Addr>) {
channel().send_replace(address);
}
pub fn current() -> Option<Ipv4Addr> {
*channel().borrow()
}
pub fn subscribe() -> watch::Receiver<Option<Ipv4Addr>> {
channel().subscribe()
}
static WG_ONLY: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub fn set_wg_only(on: bool) {
WG_ONLY.store(on, std::sync::atomic::Ordering::SeqCst);
}
pub fn wg_only() -> bool {
WG_ONLY.load(std::sync::atomic::Ordering::SeqCst)
}
pub fn estate_is_wg_only(seed_is_wireguard: Option<bool>) -> bool {
seed_is_wireguard == Some(true)
}
pub fn primary_control(
utility: Option<Ipv4Addr>,
overlay: Option<Ipv4Addr>,
wg_only: bool,
) -> Option<Ipv4Addr> {
if wg_only {
overlay
} else {
utility.or(overlay)
}
}
pub fn over_the_tunnel(at: &str, pairs: &[(Ipv4Addr, Ipv4Addr)]) -> String {
let Ok(sa) = at.parse::<SocketAddr>() else {
return at.to_string();
};
let IpAddr::V4(ip) = sa.ip() else {
return at.to_string();
};
match pairs.iter().find(|(u, _)| *u == ip) {
Some((_, o)) => SocketAddr::new(IpAddr::V4(*o), sa.port()).to_string(),
None => at.to_string(),
}
}
pub fn replication_extra(
derived: SocketAddr,
explicit: bool,
tunnel: Option<Ipv4Addr>,
) -> Option<SocketAddr> {
let t = tunnel?;
if explicit || derived.ip().is_unspecified() || derived.ip() == IpAddr::V4(t) {
return None;
}
Some(SocketAddr::new(IpAddr::V4(t), derived.port()))
}
#[cfg(test)]
mod tests {
use super::*;
fn eth1() -> SocketAddr {
"10.0.3.15:50052".parse().unwrap()
}
#[test]
fn with_a_tunnel_address_a_second_door_opens_on_wg0() {
let t: Ipv4Addr = "10.77.0.2".parse().unwrap();
assert_eq!(
replication_extra(eth1(), false, Some(t)),
Some("10.77.0.2:50052".parse().unwrap())
);
}
#[test]
fn without_a_tunnel_there_is_only_the_utility_door() {
assert_eq!(replication_extra(eth1(), false, None), None);
}
#[test]
fn an_explicit_or_unspecified_bind_gets_no_second_door() {
let t = Some("10.77.0.2".parse().unwrap());
assert_eq!(replication_extra(eth1(), true, t), None);
assert_eq!(
replication_extra("0.0.0.0:50052".parse().unwrap(), false, t),
None
);
assert_eq!(
replication_extra("10.77.0.2:50052".parse().unwrap(), false, t),
None
);
}
#[test]
fn a_fed_utility_address_is_dialled_over_the_tunnel() {
let pairs = [
(Ipv4Addr::new(10, 13, 8, 3), Ipv4Addr::new(10, 44, 0, 3)),
(Ipv4Addr::new(10, 13, 8, 2), Ipv4Addr::new(10, 44, 0, 2)),
];
assert_eq!(
over_the_tunnel("10.13.8.3:50051", &pairs),
"10.44.0.3:50051"
);
assert_eq!(
over_the_tunnel("10.9.9.9:50051", &pairs),
"10.9.9.9:50051",
"nobody's: as fed"
);
assert_eq!(
over_the_tunnel("twin.example:50051", &pairs),
"twin.example:50051"
);
}
#[test]
fn an_estate_box_is_wg_only_and_a_standalone_appliance_is_not() {
assert!(estate_is_wg_only(Some(true)));
assert!(!estate_is_wg_only(Some(false)));
assert!(!estate_is_wg_only(None));
}
#[test]
fn under_wg_only_a_twin_joins_the_primarys_overlay_address() {
let (u, o) = (
Some(Ipv4Addr::new(10, 13, 8, 2)),
Some(Ipv4Addr::new(10, 44, 0, 2)),
);
assert_eq!(primary_control(u, o, true), o);
assert_eq!(
primary_control(u, None, true),
None,
"no overlay: nothing to join, never the plain IP"
);
assert_eq!(primary_control(u, o, false), u);
assert_eq!(primary_control(None, o, false), o);
}
#[tokio::test]
async fn a_runtime_publish_wakes_the_watcher() {
let mut rx = subscribe();
let before = current();
let t: Ipv4Addr = "10.77.0.9".parse().unwrap();
publish(Some(t));
rx.changed().await.expect("the watcher is woken");
assert_eq!(*rx.borrow(), Some(t));
assert_eq!(current(), Some(t));
publish(before);
}
}