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);
}
}