use std::sync::Arc;
use crate::{FlowSide, Reassembler, ReassemblerFactory};
use super::parser::{self, DirState, ParseOutput};
use super::types::{HttpConfig, HttpHandler};
pub struct HttpFactory<H: HttpHandler> {
handler: Arc<H>,
config: HttpConfig,
}
impl<H: HttpHandler> HttpFactory<H> {
pub fn with_handler(handler: H) -> Self {
Self {
handler: Arc::new(handler),
config: HttpConfig::default(),
}
}
pub fn with_config(handler: H, config: HttpConfig) -> Self {
Self {
handler: Arc::new(handler),
config,
}
}
}
impl<K, H> ReassemblerFactory<K> for HttpFactory<H>
where
K: Send + 'static,
H: HttpHandler,
{
type Reassembler = HttpReassembler<H>;
fn new_reassembler(&mut self, _key: &K, side: FlowSide) -> HttpReassembler<H> {
HttpReassembler {
handler: self.handler.clone(),
config: self.config.clone(),
buffer: Vec::with_capacity(8192),
state: DirState::Headers,
side,
}
}
}
pub struct HttpReassembler<H: HttpHandler> {
handler: Arc<H>,
config: HttpConfig,
buffer: Vec<u8>,
state: DirState,
side: FlowSide,
}
impl<H: HttpHandler> HttpReassembler<H> {
fn drain(&mut self) {
let is_request = matches!(self.side, FlowSide::Initiator);
loop {
match parser::step(&mut self.state, &mut self.buffer, is_request, &self.config) {
Ok(Some(ParseOutput::Request(req))) => self.handler.on_request(&req),
Ok(Some(ParseOutput::Response(resp))) => self.handler.on_response(&resp),
Ok(None) => break,
Err(_) => {
self.buffer.clear();
break;
}
}
}
}
}
impl<H: HttpHandler> Reassembler for HttpReassembler<H> {
fn segment(&mut self, _seq: u32, payload: &[u8]) {
if payload.is_empty() {
return;
}
self.buffer.extend_from_slice(payload);
self.drain();
}
fn fin(&mut self) {
if let Some(out) = parser::eof(&mut self.state, &mut self.buffer) {
match out {
ParseOutput::Request(req) => self.handler.on_request(&req),
ParseOutput::Response(resp) => self.handler.on_response(&resp),
}
}
}
fn rst(&mut self) {
self.buffer.clear();
}
}