use std::collections::{
hash_map::{Entry, Values},
HashMap,
};
use fnv::FnvHashMap;
use log::trace;
use pako_tools::{FiveTuple, Flow, FlowID};
use rand::prelude::*;
use rand_chacha::*;
pub struct FlowMap {
trng: ChaChaRng,
flows: FnvHashMap<FlowID, Flow>,
flows_id: HashMap<FiveTuple, FlowID>,
}
impl Default for FlowMap {
fn default() -> Self {
FlowMap {
trng: ChaChaRng::from_rng(rand::thread_rng()).unwrap(),
flows: FnvHashMap::default(),
flows_id: HashMap::new(),
}
}
}
impl FlowMap {
pub fn with_rng_seed(self, seed: u64) -> Self {
let trng = <ChaChaRng as SeedableRng>::seed_from_u64(seed);
FlowMap { trng, ..self }
}
pub fn lookup_flow(&self, five_t: &FiveTuple) -> Option<FlowID> {
self.flows_id.get(five_t).copied()
}
#[inline]
pub fn len(&self) -> usize {
self.flows.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.flows.is_empty()
}
pub fn insert_flow(&mut self, five_t: FiveTuple, flow: Flow) -> FlowID {
let rev_id = self.flows_id.get(&five_t.get_reverse()).copied();
if let Some(id) = rev_id {
trace!("Inserting reverse flow ID 0x{:x}", id);
self.flows_id.insert(five_t, id);
return id;
}
let id = self.trng.gen();
trace!("Inserting new flow (id=0x{:x})", id);
trace!(" flow: {:?}", flow);
self.flows.insert(id, flow);
self.flows_id.insert(five_t, id);
id
}
#[inline]
pub fn get_flow(&self, flow_id: FlowID) -> Option<&Flow> {
self.flows.get(&flow_id)
}
#[inline]
pub fn get_flow_mut(&mut self, flow_id: FlowID) -> Option<&mut Flow> {
self.flows.get_mut(&flow_id)
}
#[inline]
pub fn values(&self) -> Values<FlowID, Flow> {
self.flows.values()
}
#[inline]
pub fn entry(&mut self, flow_id: FlowID) -> Entry<FlowID, Flow> {
self.flows.entry(flow_id)
}
pub fn clear(&mut self) {
self.flows.clear();
self.flows_id.clear();
}
}