use std::{
fmt,
net::{Ipv4Addr, SocketAddrV4},
sync::Arc,
time::Duration,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MappingProtocol {
Pcp,
NatPmp,
Upnp,
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Event {
Discovering,
Gateway {
local_ip: Ipv4Addr,
gateway: Ipv4Addr,
},
Discovered(super::ProbeOutput),
DiscoveryFailed(String),
Requesting {
protocol: MappingProtocol,
gateway: Ipv4Addr,
renewal: bool,
},
Active {
protocol: MappingProtocol,
external: SocketAddrV4,
lifetime: Duration,
},
MappingFailed(String),
Expired(SocketAddrV4),
Cancelled,
Releasing(SocketAddrV4),
Released {
external: SocketAddrV4,
confirmed: bool,
},
ReleaseFailed {
external: SocketAddrV4,
error: String,
},
}
#[derive(Clone, Default)]
pub struct Observer(Option<Arc<dyn Fn(Event) + Send + Sync>>);
impl Observer {
pub fn new(callback: impl Fn(Event) + Send + Sync + 'static) -> Self {
Self(Some(Arc::new(callback)))
}
pub(crate) fn emit(&self, event: Event) {
if let Some(callback) = &self.0 {
callback(event);
}
}
}
impl fmt::Debug for Observer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Observer")
.field("enabled", &self.0.is_some())
.finish()
}
}
pub(crate) fn detail(error: impl fmt::Display) -> String {
error.to_string().chars().take(256).collect()
}