use std::collections::VecDeque;
use crate::Protocol;
const HISTORY_SIZE: usize = 60;
#[derive(Debug, Clone)]
pub struct ProtocolSnapshot {
pub tcp: u64,
pub udp: u64,
pub http: u64,
pub https: u64,
pub dns: u64,
pub ssh: u64,
pub unknown: u64,
pub total: u64,
}
impl ProtocolSnapshot {
fn new() -> Self {
Self {
tcp: 0,
udp: 0,
http: 0,
https: 0,
dns: 0,
ssh: 0,
unknown: 0,
total: 0,
}
}
}
pub struct ProtocolActivityTracker {
history: VecDeque<ProtocolSnapshot>,
current: ProtocolSnapshot,
}
impl ProtocolActivityTracker {
pub fn new() -> Self {
Self {
history: VecDeque::with_capacity(HISTORY_SIZE),
current: ProtocolSnapshot::new(),
}
}
pub fn record_packet(&mut self, protocol: Protocol) {
match protocol {
Protocol::TCP => self.current.tcp += 1,
Protocol::UDP => self.current.udp += 1,
Protocol::HTTP => self.current.http += 1,
Protocol::HTTPS => self.current.https += 1,
Protocol::DNS => self.current.dns += 1,
Protocol::SSH => self.current.ssh += 1,
Protocol::Unknown => self.current.unknown += 1,
}
self.current.total += 1;
}
pub fn tick(&mut self) {
self.history.push_back(self.current.clone());
if self.history.len() > HISTORY_SIZE {
self.history.pop_front();
}
self.current = ProtocolSnapshot::new();
}
pub fn get_history(&self) -> &VecDeque<ProtocolSnapshot> {
&self.history
}
pub fn get_sparkline_data(&self, protocol: Protocol) -> Vec<u64> {
let mut data: Vec<u64> = self.history.iter().map(|snapshot| {
match protocol {
Protocol::TCP => snapshot.tcp,
Protocol::UDP => snapshot.udp,
Protocol::HTTP => snapshot.http,
Protocol::HTTPS => snapshot.https,
Protocol::DNS => snapshot.dns,
Protocol::SSH => snapshot.ssh,
Protocol::Unknown => snapshot.unknown,
}
}).collect();
data.push(match protocol {
Protocol::TCP => self.current.tcp,
Protocol::UDP => self.current.udp,
Protocol::HTTP => self.current.http,
Protocol::HTTPS => self.current.https,
Protocol::DNS => self.current.dns,
Protocol::SSH => self.current.ssh,
Protocol::Unknown => self.current.unknown,
});
while data.len() < 20 {
data.insert(0, 0);
}
if data.len() > 20 {
data.split_off(data.len() - 20)
} else {
data
}
}
pub fn get_max_value(&self) -> u64 {
let history_max = self.history.iter()
.map(|s| s.total)
.max()
.unwrap_or(0);
history_max.max(self.current.total).max(1)
}
}