1use std::net::IpAddr;
4use std::time::Duration;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum Protocol {
10 Dns,
12 Http,
14 Stun,
16}
17
18impl std::fmt::Display for Protocol {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 match self {
21 Protocol::Dns => write!(f, "DNS"),
22 Protocol::Http => write!(f, "HTTP"),
23 Protocol::Stun => write!(f, "STUN"),
24 }
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
30#[non_exhaustive]
31pub enum IpVersion {
32 V4,
34 V6,
36 #[default]
38 Any,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct ProviderResult {
44 pub ip: IpAddr,
46 pub provider: String,
48 pub protocol: Protocol,
50 pub latency: Duration,
52}
53
54impl ProviderResult {
55 pub fn ipv4(&self) -> Option<std::net::Ipv4Addr> {
57 match self.ip {
58 IpAddr::V4(v4) => Some(v4),
59 _ => None,
60 }
61 }
62
63 pub fn ipv6(&self) -> Option<std::net::Ipv6Addr> {
65 match self.ip {
66 IpAddr::V6(v6) => Some(v6),
67 _ => None,
68 }
69 }
70}
71
72impl std::fmt::Display for ProviderResult {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 write!(
75 f,
76 "{} (via {} over {}, {:?})",
77 self.ip, self.provider, self.protocol, self.latency
78 )
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87#[non_exhaustive]
88pub enum BuiltinProvider {
89 GoogleStun,
92 GoogleStun1,
94 GoogleStun2,
96 CloudflareStun,
98
99 GoogleDns,
102 CloudflareDns,
104 OpenDns,
106
107 CloudflareHttp,
110 Aws,
112}
113
114impl BuiltinProvider {
115 pub fn protocol(&self) -> Protocol {
117 match self {
118 Self::GoogleStun | Self::GoogleStun1 | Self::GoogleStun2 | Self::CloudflareStun => {
119 Protocol::Stun
120 }
121 Self::GoogleDns | Self::CloudflareDns | Self::OpenDns => Protocol::Dns,
122 Self::CloudflareHttp | Self::Aws => Protocol::Http,
123 }
124 }
125
126 pub const ALL: &'static [BuiltinProvider] = &[
136 Self::CloudflareStun,
138 Self::CloudflareDns,
139 Self::GoogleStun,
140 Self::GoogleStun1,
141 Self::GoogleStun2,
142 Self::GoogleDns,
143 Self::OpenDns,
145 Self::CloudflareHttp,
146 Self::Aws,
147 ];
148
149 pub(crate) fn to_boxed(self) -> crate::provider::BoxedProvider {
151 match self {
152 #[cfg(feature = "stun")]
153 Self::GoogleStun => Box::new(crate::stun::providers::google()),
154 #[cfg(feature = "stun")]
155 Self::GoogleStun1 => Box::new(crate::stun::providers::google1()),
156 #[cfg(feature = "stun")]
157 Self::GoogleStun2 => Box::new(crate::stun::providers::google2()),
158 #[cfg(feature = "stun")]
159 Self::CloudflareStun => Box::new(crate::stun::providers::cloudflare()),
160
161 #[cfg(feature = "dns")]
162 Self::GoogleDns => Box::new(crate::dns::providers::google()),
163 #[cfg(feature = "dns")]
164 Self::CloudflareDns => Box::new(crate::dns::providers::cloudflare()),
165 #[cfg(feature = "dns")]
166 Self::OpenDns => Box::new(crate::dns::providers::opendns()),
167
168 #[cfg(feature = "http")]
169 Self::CloudflareHttp => Box::new(crate::http::providers::cloudflare()),
170 #[cfg(feature = "http")]
171 Self::Aws => Box::new(crate::http::providers::aws()),
172
173 #[allow(unreachable_patterns)]
175 other => Box::new(super::provider::DisabledProvider(format!("{:?}", other))),
176 }
177 }
178}
179
180impl std::fmt::Display for BuiltinProvider {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 Self::GoogleStun => write!(f, "Google STUN"),
184 Self::GoogleStun1 => write!(f, "Google STUN 1"),
185 Self::GoogleStun2 => write!(f, "Google STUN 2"),
186 Self::CloudflareStun => write!(f, "Cloudflare STUN"),
187 Self::GoogleDns => write!(f, "Google DNS"),
188 Self::CloudflareDns => write!(f, "Cloudflare DNS"),
189 Self::OpenDns => write!(f, "OpenDNS"),
190 Self::CloudflareHttp => write!(f, "Cloudflare"),
191 Self::Aws => write!(f, "AWS"),
192 }
193 }
194}