external_ip/sources/
interfaces.rs1use std::fmt::Display;
2use std::future::Future;
3use std::net::IpAddr;
4use std::pin::Pin;
5
6#[derive(Copy, Clone, Debug, PartialEq, Default)]
8pub enum Family {
9 #[default]
11 Any,
12 IPv4,
14 IPv6,
16}
17
18#[derive(Debug, thiserror::Error)]
19pub enum Error {
20 #[error("HTTP request: {0}")]
21 Http(#[from] reqwest::Error),
22 #[error("Decode as UTF-8 failed: {0}")]
23 DecodeError(#[from] std::str::Utf8Error),
24 #[error("Address parsing: {0}")]
25 InvalidAddress(#[from] std::net::AddrParseError),
26 #[error("DNS resolution failed: {0}")]
27 Dns(#[from] hickory_resolver::error::ResolveError),
28 #[error("DNS resolution empty")]
29 DnsResolutionEmpty,
30 #[error("Unsupported family")]
31 UnsupportedFamily,
32 #[cfg(feature = "igd")]
33 #[error("IGD external IP: {0}")]
34 IgdExternalIp(#[from] igd::GetExternalIpError),
35 #[cfg(feature = "igd")]
36 #[error("IGD search {0}")]
37 IgdSearch(#[from] igd::SearchError),
38}
39
40pub type IpResult = Result<IpAddr, Error>;
41pub type IpFuture<'a> = Pin<Box<dyn Future<Output = IpResult> + Send + 'a>>;
42
43#[cfg_attr(test, mockall::automock)]
45pub trait Source: Display {
46 fn get_ip(&self, family: Family) -> IpFuture<'_>;
48
49 fn box_clone(&self) -> Box<dyn Source>;
51}
52
53#[cfg(test)]
54impl Display for MockSource {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "MockedSource")
57 }
58}
59
60impl Clone for Box<dyn Source> {
61 fn clone(&self) -> Box<dyn Source> {
62 self.box_clone()
63 }
64}