use std::net::Ipv4Addr;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum RoutingMode {
#[default]
PreferOverlay,
OverlayOnly,
DirectOnly,
}
#[derive(Debug, Clone)]
pub enum OverlayReachability {
Reachable(Ipv4Addr),
Unreachable,
Unavailable,
}
pub trait OverlayResolver: Send + Sync {
fn resolve_overlay_ip(&self, node_name: &str) -> OverlayReachability;
fn resolve_direct_endpoint(&self, node_name: &str) -> Option<String>;
fn local_overlay_ip(&self) -> Option<Ipv4Addr>;
fn overlay_active(&self) -> bool;
}
pub type DynOverlayResolver = Arc<dyn OverlayResolver>;
pub trait TunnelDnsRegistrar: Send + Sync {
fn register_service(
&self,
service_name: &str,
overlay_ip: Ipv4Addr,
port: u16,
) -> std::pin::Pin<
Box<dyn std::future::Future<Output = std::result::Result<(), String>> + Send + '_>,
>;
fn unregister_service(
&self,
service_name: &str,
) -> std::pin::Pin<
Box<dyn std::future::Future<Output = std::result::Result<(), String>> + Send + '_>,
>;
}
pub type DynTunnelDnsRegistrar = Arc<dyn TunnelDnsRegistrar>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_routing_mode_default() {
let mode = RoutingMode::default();
assert_eq!(mode, RoutingMode::PreferOverlay);
}
#[test]
fn test_routing_mode_serde_roundtrip() {
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct Wrapper {
mode: RoutingMode,
}
let cases = [
("mode = \"preferoverlay\"", RoutingMode::PreferOverlay),
("mode = \"overlayonly\"", RoutingMode::OverlayOnly),
("mode = \"directonly\"", RoutingMode::DirectOnly),
];
for (toml_str, expected) in &cases {
let wrapper: Wrapper = toml::from_str(toml_str).expect("deserialize");
assert_eq!(*expected, wrapper.mode);
}
}
#[test]
fn test_routing_mode_equality() {
assert_eq!(RoutingMode::PreferOverlay, RoutingMode::PreferOverlay);
assert_eq!(RoutingMode::OverlayOnly, RoutingMode::OverlayOnly);
assert_eq!(RoutingMode::DirectOnly, RoutingMode::DirectOnly);
assert_ne!(RoutingMode::PreferOverlay, RoutingMode::DirectOnly);
assert_ne!(RoutingMode::OverlayOnly, RoutingMode::DirectOnly);
}
#[test]
fn test_overlay_reachability_variants() {
let reachable = OverlayReachability::Reachable(Ipv4Addr::new(10, 0, 0, 1));
assert!(
matches!(reachable, OverlayReachability::Reachable(ip) if ip == Ipv4Addr::new(10, 0, 0, 1))
);
let unreachable = OverlayReachability::Unreachable;
assert!(matches!(unreachable, OverlayReachability::Unreachable));
let unavailable = OverlayReachability::Unavailable;
assert!(matches!(unavailable, OverlayReachability::Unavailable));
}
}