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