use std::net::SocketAddr;
use std::time::{Duration, Instant};
use super::{DiscoveryError, NetworkDiscovery, NetworkInterface};
pub struct LinuxDiscovery {
cache: Option<InterfaceCache>,
cache_refresh_interval: Duration,
}
struct InterfaceCache {
interfaces: Vec<NetworkInterface>,
last_refresh: Instant,
}
impl LinuxDiscovery {
pub fn new(cache_refresh_interval: Duration) -> Self {
Self {
cache: None,
cache_refresh_interval,
}
}
fn refresh_cache_if_needed(&mut self) -> Result<(), DiscoveryError> {
let should_refresh = match &self.cache {
Some(cache) => cache.last_refresh.elapsed() >= self.cache_refresh_interval,
None => true,
};
if should_refresh {
self.refresh_cache()?;
}
Ok(())
}
fn refresh_cache(&mut self) -> Result<(), DiscoveryError> {
let interfaces = self.get_interfaces_from_system()?;
self.cache = Some(InterfaceCache {
interfaces,
last_refresh: Instant::now(),
});
Ok(())
}
fn get_interfaces_from_system(&self) -> Result<Vec<NetworkInterface>, DiscoveryError> {
Ok(Vec::new())
}
}
impl NetworkDiscovery for LinuxDiscovery {
fn discover_interfaces(&self) -> Result<Vec<NetworkInterface>, DiscoveryError> {
if let Some(cache) = &self.cache {
if cache.last_refresh.elapsed() < self.cache_refresh_interval {
return Ok(cache.interfaces.clone());
}
}
let mut this = self.clone();
this.refresh_cache_if_needed()?;
match &this.cache {
Some(cache) => Ok(cache.interfaces.clone()),
None => Err(DiscoveryError::InternalError("Cache refresh failed".into())),
}
}
fn get_default_route(&self) -> Result<Option<SocketAddr>, DiscoveryError> {
Ok(None)
}
}
impl Clone for LinuxDiscovery {
fn clone(&self) -> Self {
Self {
cache: self.cache.clone(),
cache_refresh_interval: self.cache_refresh_interval,
}
}
}
impl Clone for InterfaceCache {
fn clone(&self) -> Self {
Self {
interfaces: self.interfaces.clone(),
last_refresh: self.last_refresh,
}
}
}