use crate::{
location::DstLocation,
messages::{Message, MessageHash},
};
use lru_time_cache::LruCache;
use std::time::Duration;
use xor_name::XorName;
const INCOMING_EXPIRY_DURATION: Duration = Duration::from_secs(20 * 60);
const OUTGOING_EXPIRY_DURATION: Duration = Duration::from_secs(10 * 60);
const MAX_ENTRIES: usize = 5_000;
#[derive(Eq, PartialEq)]
pub enum FilteringResult {
NewMessage,
KnownMessage,
}
impl FilteringResult {
pub fn is_new(&self) -> bool {
match self {
Self::NewMessage => true,
Self::KnownMessage => false,
}
}
}
pub(crate) struct MessageFilter {
incoming: LruCache<MessageHash, ()>,
outgoing: LruCache<(MessageHash, XorName), ()>,
}
impl MessageFilter {
pub fn new() -> Self {
Self {
incoming: LruCache::with_expiry_duration_and_capacity(
INCOMING_EXPIRY_DURATION,
MAX_ENTRIES,
),
outgoing: LruCache::with_expiry_duration_and_capacity(
OUTGOING_EXPIRY_DURATION,
MAX_ENTRIES,
),
}
}
pub fn contains_incoming(&self, msg: &Message) -> bool {
let hash = msg.hash();
self.incoming.contains_key(hash)
}
pub fn insert_incoming(&mut self, msg: &Message) {
if let DstLocation::Direct = msg.dst() {
return;
}
let _ = self.incoming.insert(*msg.hash(), ());
}
pub fn filter_outgoing(&mut self, msg: &Message, pub_id: &XorName) -> FilteringResult {
if let DstLocation::Direct = msg.dst() {
return FilteringResult::NewMessage;
}
if self.outgoing.insert((*msg.hash(), *pub_id), ()).is_some() {
FilteringResult::KnownMessage
} else {
FilteringResult::NewMessage
}
}
pub fn reset(&mut self) {
self.incoming.clear();
self.outgoing.clear();
}
}
impl Default for MessageFilter {
fn default() -> Self {
Self::new()
}
}