use crate::Parser;
use crate::ParserFactory;
use crate::ParserFuture;
use crate::PktStrm;
use crate::Prolens;
use crate::packet::*;
use std::cell::RefCell;
use std::ffi::c_void;
use std::marker::PhantomData;
use std::rc::Rc;
pub trait ByteCbFn: FnMut(u8, u32, *mut c_void) {}
impl<F: FnMut(u8, u32, *mut c_void)> ByteCbFn for F {}
pub(crate) type CbByte = Rc<RefCell<dyn ByteCbFn + 'static>>;
pub struct ByteParser<T>
where
T: Packet,
{
pub(crate) cb_next_byte: Option<CbByte>,
_phantom_t: PhantomData<T>,
}
impl<T> ByteParser<T>
where
T: Packet,
{
pub fn new() -> Self {
Self {
cb_next_byte: None,
_phantom_t: PhantomData,
}
}
async fn c2s_parser_inner(
strm: *mut PktStrm<T>,
cb_next_byte: Option<CbByte>,
cb_ctx: *mut c_void,
) -> Result<(), ()> {
let stm = unsafe { &mut *strm };
while let Ok((byte, seq)) = stm.next_byte().await {
if let Some(ref cb) = cb_next_byte {
cb.borrow_mut()(byte, seq, cb_ctx);
}
}
Ok(())
}
}
impl<T> Default for ByteParser<T>
where
T: Packet,
{
fn default() -> Self {
Self::new()
}
}
impl<T> Parser for ByteParser<T>
where
T: Packet + 'static,
{
type T = T;
fn c2s_parser(&self, strm: *mut PktStrm<T>, cb_ctx: *mut c_void) -> Option<ParserFuture> {
Some(Box::pin(Self::c2s_parser_inner(
strm,
self.cb_next_byte.clone(),
cb_ctx,
)))
}
}
pub(crate) struct ByteFactory<T> {
_phantom_t: PhantomData<T>,
}
impl<T> ParserFactory<T> for ByteFactory<T>
where
T: Packet + 'static,
{
fn new() -> Self {
Self {
_phantom_t: PhantomData,
}
}
fn create(&self, prolens: &Prolens<T>) -> Box<dyn Parser<T = T>> {
let mut parser = Box::new(ByteParser::new());
parser.cb_next_byte = prolens.cb_byte.clone();
parser
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::*;
#[test]
fn test_next_byte_single_packet() {
let seq1 = 1;
let pkt1 = build_pkt(seq1, true);
let _ = pkt1.decode();
let data = Rc::new(RefCell::new(Vec::new()));
let data_clone = Rc::clone(&data);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
dbg!("in callback. push one byte");
data_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt1);
assert_eq!(*data.borrow(), (1..=10).collect::<Vec<u8>>());
}
#[test]
fn test_next_byte_multiple_packets() {
let seq1 = 1;
let pkt1 = build_pkt(seq1, false);
let seq2 = 11;
let pkt2 = build_pkt(seq2, true);
let _ = pkt1.decode();
let _ = pkt2.decode();
let data = Rc::new(RefCell::new(Vec::new()));
let data_clone = Rc::clone(&data);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
data_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt1);
protolens.run_task(&mut task, pkt2);
let expected: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(*data.borrow(), expected);
}
#[test]
fn test_next_byte_empty_packet() {
let pkt = build_pkt_nodata(1, true);
let _ = pkt.decode();
let data = Rc::new(RefCell::new(Vec::new()));
let data_clone = Rc::clone(&data);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
data_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt);
assert_eq!(data.borrow().len(), 0);
}
#[test]
fn test_next_byte_sequential_with_fin() {
let seq1 = 1;
let pkt1 = build_pkt(seq1, false);
let seq2 = 11;
let pkt2 = build_pkt(seq2, false);
let seq3 = 21;
let pkt3 = build_pkt(seq3, false);
let seq4 = 31;
let pkt4 = build_pkt_nodata(seq4, true);
let _ = pkt1.decode();
let _ = pkt2.decode();
let _ = pkt3.decode();
let _ = pkt4.decode();
let data = Rc::new(RefCell::new(Vec::new()));
let data_clone = Rc::clone(&data);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
data_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt1);
protolens.run_task(&mut task, pkt2);
protolens.run_task(&mut task, pkt3);
protolens.run_task(&mut task, pkt4);
#[rustfmt::skip]
let expected: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
];
assert_eq!(*data.borrow(), expected);
}
#[test]
fn test_next_byte_with_pure_ack() {
let seq1 = 1;
let pkt1 = build_pkt(seq1, false);
let seq2 = 11;
let pkt2 = build_pkt(seq2, false);
let seq_ack = 21;
let pkt_ack = build_pkt_ack(seq_ack, 15);
let seq3 = 21;
let pkt3 = build_pkt(seq3, false);
let seq4 = 41;
let pkt4 = build_pkt_nodata(seq4, true);
let _ = pkt1.decode();
let _ = pkt2.decode();
let _ = pkt_ack.decode();
let _ = pkt3.decode();
let _ = pkt4.decode();
let vec = Rc::new(RefCell::new(Vec::new()));
let vec_clone = Rc::clone(&vec);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
vec_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt1);
protolens.run_task(&mut task, pkt2);
protolens.run_task(&mut task, pkt_ack);
protolens.run_task(&mut task, pkt3);
protolens.run_task(&mut task, pkt4);
#[rustfmt::skip]
let expected: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
];
assert_eq!(*vec.borrow(), expected);
}
#[test]
fn test_next_byte_out_of_order() {
let seq1 = 1;
let pkt1 = build_pkt(seq1, false);
let seq2 = 11;
let pkt2 = build_pkt(seq2, false);
let seq_ack = 21;
let pkt_ack = build_pkt_ack(seq_ack, 15);
let seq3 = 21;
let pkt3 = build_pkt(seq3, false);
let seq4 = 41;
let pkt4 = build_pkt_nodata(seq4, true);
let _ = pkt1.decode();
let _ = pkt2.decode();
let _ = pkt_ack.decode();
let _ = pkt3.decode();
let _ = pkt4.decode();
let vec = Rc::new(RefCell::new(Vec::new()));
let vec_clone = Rc::clone(&vec);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
vec_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt1);
protolens.run_task(&mut task, pkt3);
protolens.run_task(&mut task, pkt2);
protolens.run_task(&mut task, pkt_ack);
protolens.run_task(&mut task, pkt4);
#[rustfmt::skip]
let expected: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ];
assert_eq!(*vec.borrow(), expected);
}
#[test]
fn test_next_byte_syn_with_out_of_order() {
let seq1 = 1;
let pkt_syn = build_pkt_syn(seq1);
let seq2 = 2; let pkt1 = build_pkt(seq2, false);
let seq3 = 12;
let pkt2 = build_pkt(seq3, false);
let seq_ack = 22;
let pkt_ack = build_pkt_ack(seq_ack, 15);
let seq4 = 22;
let pkt3 = build_pkt(seq4, false);
let seq5 = 32;
let pkt4 = build_pkt_nodata(seq5, true);
let _ = pkt_syn.decode();
let _ = pkt1.decode();
let _ = pkt2.decode();
let _ = pkt_ack.decode();
let _ = pkt3.decode();
let _ = pkt4.decode();
let vec = Rc::new(RefCell::new(Vec::new()));
let vec_clone = Rc::clone(&vec);
let callback = move |byte: u8, _seq: u32, _cb_ctx: *mut c_void| {
vec_clone.borrow_mut().push(byte);
};
let mut protolens = Prolens::<CapPacket>::default();
protolens.set_cb_byte(callback);
let mut task = protolens.new_task(TransProto::Tcp);
protolens.set_task_parser(&mut task, L7Proto::Byte);
protolens.run_task(&mut task, pkt_syn);
protolens.run_task(&mut task, pkt2);
protolens.run_task(&mut task, pkt_ack);
protolens.run_task(&mut task, pkt1);
protolens.run_task(&mut task, pkt3);
protolens.run_task(&mut task, pkt4);
#[rustfmt::skip]
let expected: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ];
assert_eq!(*vec.borrow(), expected);
}
}