use std::net::IpAddr;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Protocol {
Dns,
Http,
Stun,
}
impl std::fmt::Display for Protocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Protocol::Dns => write!(f, "DNS"),
Protocol::Http => write!(f, "HTTP"),
Protocol::Stun => write!(f, "STUN"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum IpVersion {
V4,
V6,
#[default]
Any,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProviderResult {
pub ip: IpAddr,
pub provider: String,
pub protocol: Protocol,
pub latency: Duration,
}
impl ProviderResult {
pub fn ipv4(&self) -> Option<std::net::Ipv4Addr> {
match self.ip {
IpAddr::V4(v4) => Some(v4),
_ => None,
}
}
pub fn ipv6(&self) -> Option<std::net::Ipv6Addr> {
match self.ip {
IpAddr::V6(v6) => Some(v6),
_ => None,
}
}
}
impl std::fmt::Display for ProviderResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} (via {} over {}, {:?})",
self.ip, self.provider, self.protocol, self.latency
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BuiltinProvider {
GoogleStun,
GoogleStun1,
GoogleStun2,
CloudflareStun,
GoogleDns,
CloudflareDns,
OpenDns,
CloudflareHttp,
Aws,
}
impl BuiltinProvider {
pub fn protocol(&self) -> Protocol {
match self {
Self::GoogleStun | Self::GoogleStun1 | Self::GoogleStun2 | Self::CloudflareStun => {
Protocol::Stun
}
Self::GoogleDns | Self::CloudflareDns | Self::OpenDns => Protocol::Dns,
Self::CloudflareHttp | Self::Aws => Protocol::Http,
}
}
pub const ALL: &'static [BuiltinProvider] = &[
Self::CloudflareStun,
Self::CloudflareDns,
Self::GoogleStun,
Self::GoogleStun1,
Self::GoogleStun2,
Self::GoogleDns,
Self::OpenDns,
Self::CloudflareHttp,
Self::Aws,
];
pub(crate) fn to_boxed(self) -> crate::provider::BoxedProvider {
match self {
#[cfg(feature = "stun")]
Self::GoogleStun => Box::new(crate::stun::providers::google()),
#[cfg(feature = "stun")]
Self::GoogleStun1 => Box::new(crate::stun::providers::google1()),
#[cfg(feature = "stun")]
Self::GoogleStun2 => Box::new(crate::stun::providers::google2()),
#[cfg(feature = "stun")]
Self::CloudflareStun => Box::new(crate::stun::providers::cloudflare()),
#[cfg(feature = "dns")]
Self::GoogleDns => Box::new(crate::dns::providers::google()),
#[cfg(feature = "dns")]
Self::CloudflareDns => Box::new(crate::dns::providers::cloudflare()),
#[cfg(feature = "dns")]
Self::OpenDns => Box::new(crate::dns::providers::opendns()),
#[cfg(feature = "http")]
Self::CloudflareHttp => Box::new(crate::http::providers::cloudflare()),
#[cfg(feature = "http")]
Self::Aws => Box::new(crate::http::providers::aws()),
#[allow(unreachable_patterns)]
other => Box::new(super::provider::DisabledProvider(format!("{:?}", other))),
}
}
}
impl std::fmt::Display for BuiltinProvider {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::GoogleStun => write!(f, "Google STUN"),
Self::GoogleStun1 => write!(f, "Google STUN 1"),
Self::GoogleStun2 => write!(f, "Google STUN 2"),
Self::CloudflareStun => write!(f, "Cloudflare STUN"),
Self::GoogleDns => write!(f, "Google DNS"),
Self::CloudflareDns => write!(f, "Cloudflare DNS"),
Self::OpenDns => write!(f, "OpenDNS"),
Self::CloudflareHttp => write!(f, "Cloudflare"),
Self::Aws => write!(f, "AWS"),
}
}
}