use std::collections::HashMap;
use std::net::IpAddr;
use std::time::Duration;
use parking_lot::Mutex;
use super::peer_state::PeerState;
use super::{ReplayFilter, Seq, Stamp};
impl ReplayFilter {
pub fn new(freshness_window: Duration, enabled: bool) -> Self {
ReplayFilter {
peers: Mutex::new(HashMap::new()),
freshness_window,
enabled,
}
}
pub fn check_and_record(&self, sender: IpAddr, seq: Seq, stamp: Stamp) -> bool {
if !self.enabled {
return true;
}
self.check_and_record_at(sender, seq, stamp, Stamp::now())
}
pub(super) fn check_and_record_at(
&self,
sender: IpAddr,
seq: Seq,
stamp: Stamp,
now: Stamp,
) -> bool {
if !stamp.is_fresh(now, self.freshness_window) {
return false;
}
let mut map = self.peers.lock();
let window = self.freshness_window;
map.retain(|_, s| s.stamp_at_max().age_relative_to(now) <= window.as_millis() as u64);
match map.get_mut(&sender) {
None => {
map.insert(sender, PeerState::new(seq, stamp));
true
}
Some(state) => state.accept(seq, stamp),
}
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.peers.lock().len()
}
#[cfg(test)]
pub fn evict(&self, peer: IpAddr) {
self.peers.lock().remove(&peer);
}
}