use huginn_net_db::{Label, MatchQualityType, Type};
use std::fmt;
use std::fmt::Formatter;
#[derive(Debug)]
pub struct HttpAnalysisResult {
pub http_request: Option<HttpRequestOutput>,
pub http_response: Option<HttpResponseOutput>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct IpPort {
pub ip: std::net::IpAddr,
pub port: u16,
}
impl IpPort {
pub fn new(ip: std::net::IpAddr, port: u16) -> Self {
Self { ip, port }
}
}
use crate::observable::{ObservableHttpRequest, ObservableHttpResponse};
use huginn_net_db::http::HttpDiagnosis;
#[derive(Debug)]
pub struct BrowserQualityMatched {
pub browser: Option<Browser>,
pub quality: MatchQualityType,
}
#[derive(Debug)]
pub struct Browser {
pub name: String,
pub family: Option<String>,
pub variant: Option<String>,
pub kind: Type,
}
impl From<&Label> for Browser {
fn from(label: &Label) -> Self {
Browser {
name: label.name.clone(),
family: label.class.clone(),
variant: label.flavor.clone(),
kind: label.ty.clone(),
}
}
}
#[derive(Debug)]
pub struct HttpRequestOutput {
pub source: IpPort,
pub destination: IpPort,
pub lang: Option<String>,
pub diagnosis: HttpDiagnosis,
pub browser_matched: BrowserQualityMatched,
pub sig: ObservableHttpRequest,
}
impl fmt::Display for HttpRequestOutput {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"[HTTP Request] {}:{} → {}:{}\n\
Browser: {}\n\
Lang: {}\n\
Params: {}\n\
Sig: {}\n",
self.source.ip,
self.source.port,
self.destination.ip,
self.destination.port,
self.browser_matched
.browser
.as_ref()
.map_or("???".to_string(), |browser| {
format!(
"{}:{}",
browser.family.as_deref().unwrap_or("???"),
browser.variant.as_deref().unwrap_or("???")
)
}),
self.lang.as_deref().unwrap_or("???"),
self.diagnosis,
self.sig,
)
}
}
#[derive(Debug)]
pub struct WebServerQualityMatched {
pub web_server: Option<WebServer>,
pub quality: MatchQualityType,
}
#[derive(Debug)]
pub struct WebServer {
pub name: String,
pub family: Option<String>,
pub variant: Option<String>,
pub kind: Type,
}
impl From<&Label> for WebServer {
fn from(label: &Label) -> Self {
WebServer {
name: label.name.clone(),
family: label.class.clone(),
variant: label.flavor.clone(),
kind: label.ty.clone(),
}
}
}
#[derive(Debug)]
pub struct HttpResponseOutput {
pub source: IpPort,
pub destination: IpPort,
pub diagnosis: HttpDiagnosis,
pub web_server_matched: WebServerQualityMatched,
pub sig: ObservableHttpResponse,
}
impl fmt::Display for HttpResponseOutput {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"[HTTP Response] {}:{} → {}:{}\n\
Server: {}\n\
Params: {}\n\
Sig: {}\n",
self.source.ip,
self.source.port,
self.destination.ip,
self.destination.port,
self.web_server_matched
.web_server
.as_ref()
.map_or("???".to_string(), |web_server| {
if !web_server.name.is_empty() {
web_server.name.clone()
} else {
format!(
"{}:{}",
web_server.family.as_deref().unwrap_or("???"),
web_server.variant.as_deref().unwrap_or("???")
)
}
}),
self.diagnosis,
self.sig,
)
}
}