pub mod passive;
pub mod heuristic;
pub use passive::PassiveProbe;
pub use heuristic::HeuristicProbe;
use crate::core::{ProtocolType, DetectionResult};
use crate::error::{Result, DetectorError};
pub trait ProbeEngine {
fn probe(&self, data: &[u8]) -> Result<DetectionResult>;
fn probe_type(&self) -> ProbeType;
fn needs_more_data(&self, data: &[u8]) -> bool;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProbeType {
Passive,
Active,
Heuristic,
}
pub struct ProbeAggregator {
engines: Vec<Box<dyn ProbeEngine>>,
}
impl ProbeAggregator {
pub fn new() -> Self {
Self {
engines: Vec::new(),
}
}
pub fn add_engine(&mut self, engine: Box<dyn ProbeEngine>) {
self.engines.push(engine);
}
pub fn probe_all(&self, data: &[u8]) -> Result<Vec<DetectionResult>> {
let mut results = Vec::new();
for engine in &self.engines {
match engine.probe(data) {
Ok(result) => results.push(result),
Err(DetectorError::NeedMoreData(_)) => continue,
Err(e) => return Err(e),
}
}
Ok(results)
}
pub fn best_result(&self, data: &[u8]) -> Result<DetectionResult> {
let results = self.probe_all(data)?;
if results.is_empty() {
return Err(DetectorError::detection_failed("No probe results available"));
}
let best = results.into_iter()
.max_by(|a, b| a.confidence().partial_cmp(&b.confidence()).unwrap())
.unwrap();
Ok(best)
}
}
impl Default for ProbeAggregator {
fn default() -> Self {
Self::new()
}
}