huginn_net_http/
output.rs1use huginn_net_db::{Label, MatchQualityType, Type};
2use std::fmt;
3use std::fmt::Formatter;
4
5#[derive(Debug)]
10pub struct HttpAnalysisResult {
11 pub http_request: Option<HttpRequestOutput>,
13
14 pub http_response: Option<HttpResponseOutput>,
16}
17
18#[derive(Debug, Clone, PartialEq)]
19pub struct IpPort {
20 pub ip: std::net::IpAddr,
21 pub port: u16,
22}
23
24impl IpPort {
25 pub fn new(ip: std::net::IpAddr, port: u16) -> Self {
26 Self { ip, port }
27 }
28}
29use crate::observable::{ObservableHttpRequest, ObservableHttpResponse};
30use huginn_net_db::http::HttpDiagnosis;
31
32#[derive(Debug)]
33pub struct BrowserQualityMatched {
34 pub browser: Option<Browser>,
35 pub quality: MatchQualityType,
36}
37
38#[derive(Debug)]
45pub struct Browser {
46 pub name: String,
47 pub family: Option<String>,
48 pub variant: Option<String>,
49 pub kind: Type,
50}
51
52impl From<&Label> for Browser {
53 fn from(label: &Label) -> Self {
54 Browser {
55 name: label.name.clone(),
56 family: label.class.clone(),
57 variant: label.flavor.clone(),
58 kind: label.ty.clone(),
59 }
60 }
61}
62
63#[derive(Debug)]
69pub struct HttpRequestOutput {
70 pub source: IpPort,
72 pub destination: IpPort,
74 pub lang: Option<String>,
76 pub diagnosis: HttpDiagnosis,
78 pub browser_matched: BrowserQualityMatched,
80 pub sig: ObservableHttpRequest,
82}
83
84impl fmt::Display for HttpRequestOutput {
85 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86 write!(
87 f,
88 "[HTTP Request] {}:{} → {}:{}\n\
89 Browser: {}\n\
90 Lang: {}\n\
91 Params: {}\n\
92 Sig: {}\n",
93 self.source.ip,
94 self.source.port,
95 self.destination.ip,
96 self.destination.port,
97 self.browser_matched
98 .browser
99 .as_ref()
100 .map_or("???".to_string(), |browser| {
101 format!(
102 "{}:{}",
103 browser.family.as_deref().unwrap_or("???"),
104 browser.variant.as_deref().unwrap_or("???")
105 )
106 }),
107 self.lang.as_deref().unwrap_or("???"),
108 self.diagnosis,
109 self.sig,
110 )
111 }
112}
113
114#[derive(Debug)]
115pub struct WebServerQualityMatched {
116 pub web_server: Option<WebServer>,
117 pub quality: MatchQualityType,
118}
119
120#[derive(Debug)]
127pub struct WebServer {
128 pub name: String,
129 pub family: Option<String>,
130 pub variant: Option<String>,
131 pub kind: Type,
132}
133
134impl From<&Label> for WebServer {
135 fn from(label: &Label) -> Self {
136 WebServer {
137 name: label.name.clone(),
138 family: label.class.clone(),
139 variant: label.flavor.clone(),
140 kind: label.ty.clone(),
141 }
142 }
143}
144
145#[derive(Debug)]
150pub struct HttpResponseOutput {
151 pub source: IpPort,
153 pub destination: IpPort,
155 pub diagnosis: HttpDiagnosis,
157 pub web_server_matched: WebServerQualityMatched,
159 pub sig: ObservableHttpResponse,
161}
162
163impl fmt::Display for HttpResponseOutput {
164 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
165 write!(
166 f,
167 "[HTTP Response] {}:{} → {}:{}\n\
168 Server: {}\n\
169 Params: {}\n\
170 Sig: {}\n",
171 self.source.ip,
172 self.source.port,
173 self.destination.ip,
174 self.destination.port,
175 self.web_server_matched
176 .web_server
177 .as_ref()
178 .map_or("???".to_string(), |web_server| {
179 if !web_server.name.is_empty() {
180 web_server.name.clone()
181 } else {
182 format!(
183 "{}:{}",
184 web_server.family.as_deref().unwrap_or("???"),
185 web_server.variant.as_deref().unwrap_or("???")
186 )
187 }
188 }),
189 self.diagnosis,
190 self.sig,
191 )
192 }
193}