use crate::core::types::Transport;
use memchr::memmem;
#[cfg(feature = "proto-dns")]
pub mod dns;
#[cfg(feature = "proto-ftp")]
pub mod ftp;
#[cfg(feature = "proto-http")]
pub mod http;
#[cfg(feature = "proto-https")]
pub mod https;
#[cfg(feature = "proto-ssh")]
pub mod ssh;
pub struct ProtocolMatch {
pub name: String,
pub metadata: Option<String>,
}
pub trait RefractiumProtocol: Send + Sync {
fn name(&self) -> &str;
fn identify(&self, data: &[u8]) -> Option<ProtocolMatch>;
fn transport(&self) -> Transport;
}
pub struct DynamicProtocol {
pub name: String,
pub patterns: Vec<String>,
}
impl RefractiumProtocol for DynamicProtocol {
fn identify(&self, data: &[u8]) -> Option<ProtocolMatch> {
let matched = self
.patterns
.iter()
.any(|p| memmem::find(data, p.as_bytes()).is_some());
if matched {
return Some(ProtocolMatch {
name: self.name.to_lowercase(),
metadata: None,
});
}
None
}
fn name(&self) -> &str {
&self.name
}
fn transport(&self) -> Transport {
Transport::Both
}
}
pub struct ProtocolRegistry {
protocols: Vec<Box<dyn RefractiumProtocol>>,
}
impl Default for ProtocolRegistry {
fn default() -> Self {
Self::new()
}
}
impl ProtocolRegistry {
#[must_use]
pub fn new() -> Self {
Self {
protocols: Vec::new(),
}
}
pub fn register(&mut self, proto: Box<dyn RefractiumProtocol>) {
self.protocols.push(proto);
}
#[must_use]
pub fn probe(&self, data: &[u8]) -> Option<ProtocolMatch> {
for proto in &self.protocols {
if let Some(m) = proto.identify(data) {
return Some(m);
}
}
None
}
}