Skip to main content

ip_discovery/
provider.rs

1//! Provider trait and boxed type alias.
2//!
3//! All IP detection backends (DNS, HTTP, STUN) implement [`Provider`].
4//! Custom providers can also be created by implementing this trait.
5
6use crate::error::ProviderError;
7use crate::types::{IpVersion, Protocol};
8use std::future::Future;
9use std::net::IpAddr;
10use std::pin::Pin;
11
12/// Trait for IP detection providers
13pub trait Provider: Send + Sync {
14    /// Provider name for identification
15    fn name(&self) -> &str;
16
17    /// Protocol used by this provider
18    fn protocol(&self) -> Protocol;
19
20    /// Whether this provider supports IPv4
21    fn supports_v4(&self) -> bool {
22        true
23    }
24
25    /// Whether this provider supports IPv6
26    fn supports_v6(&self) -> bool {
27        false
28    }
29
30    /// Check if provider supports the given IP version
31    fn supports_version(&self, version: IpVersion) -> bool {
32        match version {
33            IpVersion::V4 => self.supports_v4(),
34            IpVersion::V6 => self.supports_v6(),
35            IpVersion::Any => self.supports_v4() || self.supports_v6(),
36        }
37    }
38
39    /// Get the public IP address
40    fn get_ip(
41        &self,
42        version: IpVersion,
43    ) -> Pin<Box<dyn Future<Output = Result<IpAddr, ProviderError>> + Send + '_>>;
44}
45
46/// Type-erased provider, used internally to store heterogeneous providers.
47pub type BoxedProvider = Box<dyn Provider>;
48
49/// Stub provider returned when a protocol feature (dns/http/stun) is not enabled.
50/// Always returns an error explaining which feature is missing.
51pub(crate) struct DisabledProvider(pub(crate) String);
52
53impl Provider for DisabledProvider {
54    fn name(&self) -> &str {
55        &self.0
56    }
57
58    fn protocol(&self) -> Protocol {
59        Protocol::Http // doesn't matter, will always error
60    }
61
62    fn get_ip(
63        &self,
64        _version: IpVersion,
65    ) -> Pin<Box<dyn Future<Output = Result<IpAddr, ProviderError>> + Send + '_>> {
66        let name = self.0.clone();
67        Box::pin(async move {
68            Err(ProviderError::message(
69                &name,
70                "provider feature not enabled",
71            ))
72        })
73    }
74}