netgauze_pcap_decoder/
lib.rs1pub mod handlers;
22pub mod protocol_handler;
23
24use crate::protocol_handler::ProtocolHandler;
25use netgauze_pcap_reader::PcapIter;
26use std::collections::HashMap;
27use std::fs::File;
28use std::io::{self, BufWriter, Write};
29use std::net::IpAddr;
30use std::path::PathBuf;
31
32pub const PCAP_BUFFER_SIZE: usize = 165536;
34
35#[derive(Debug, Clone)]
37pub struct Config {
38 pub dest_ports: Vec<u16>,
39 pub input_size: Option<usize>,
40 pub pcap_path: PathBuf,
41 pub output_path: Option<PathBuf>,
42 pub show_frame_number: bool,
43}
44
45pub use handlers::{
47 bgp::BgpProtocolHandler, bmp::BmpProtocolHandler, flow::FlowProtocolHandler,
48 udp_notif::UdpNotifProtocolHandler,
49};
50
51pub fn load_pcap_and_process<M, C, E, H>(
66 config: &Config,
67 handler: &H,
68) -> Result<(), Box<dyn std::error::Error>>
69where
70 C: Default,
71 H: ProtocolHandler<M, C, E>,
72{
73 let pcap_file = File::open(config.pcap_path.as_path()).expect("Failed to open pcap file");
74 let pcap_reader = Box::new(pcap_parser::LegacyPcapReader::new(
75 PCAP_BUFFER_SIZE,
76 pcap_file,
77 )?);
78
79 let mut exporter_peers: HashMap<(IpAddr, u16, IpAddr, u16), (C, bytes::BytesMut)> =
80 HashMap::new();
81
82 let mut writer: Box<dyn Write> = if let Some(output_path_ref) = &config.output_path {
83 let output_file = File::create(output_path_ref).map_err(|e| {
85 format!(
86 "Failed to create output file '{}': {}",
87 output_path_ref.display(),
88 e
89 )
90 })?;
91 Box::new(BufWriter::new(output_file))
92 } else {
93 Box::new(BufWriter::new(io::stdout()))
95 };
96
97 let mut iter = PcapIter::new(pcap_reader);
98 while let Some((src_ip, src_port, dst_ip, dst_port, protocol, packet_data)) = iter.next() {
99 let frame_counter = iter.frame_counter();
100 if let Some(max_packets) = config.input_size
101 && frame_counter > max_packets
102 {
103 break;
104 }
105
106 let flow_key = (src_ip, src_port, dst_ip, dst_port);
107 if let Some(message) = handler.decode(flow_key, protocol, &packet_data, &mut exporter_peers)
108 {
109 for result in message {
110 let serialized_data = handler.serialize(result)?;
111 let output = if config.show_frame_number {
112 serde_json::json!({
113 "frame_number": frame_counter,
114 "data": serialized_data,
115 })
116 } else {
117 serialized_data
118 };
119 writer.write_all(serde_json::to_string(&output)?.as_bytes())?;
120 writer.write_all(b"\n")?;
121 }
122 }
123 }
124
125 writer.flush()?;
126 Ok(())
127}