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}
43
44pub use handlers::{
46 bgp::BgpProtocolHandler, bmp::BmpProtocolHandler, flow::FlowProtocolHandler,
47 udp_notif::UdpNotifProtocolHandler,
48};
49
50pub fn load_pcap_and_process<M, C, E, H>(
65 config: &Config,
66 handler: &H,
67) -> Result<(), Box<dyn std::error::Error>>
68where
69 C: Default,
70 H: ProtocolHandler<M, C, E>,
71{
72 let pcap_file = File::open(config.pcap_path.as_path()).expect("Failed to open pcap file");
73 let pcap_reader =
74 Box::new(pcap_parser::LegacyPcapReader::new(PCAP_BUFFER_SIZE, pcap_file).unwrap());
75
76 let mut exporter_peers: HashMap<(IpAddr, u16, IpAddr, u16), (C, bytes::BytesMut)> =
77 HashMap::new();
78 let mut packet_counter = 0;
79
80 let mut writer: Box<dyn Write> = if let Some(output_path_ref) = &config.output_path {
81 let output_file = File::create(output_path_ref).map_err(|e| {
83 format!(
84 "Failed to create output file '{}': {}",
85 output_path_ref.display(),
86 e
87 )
88 })?;
89 Box::new(BufWriter::new(output_file))
90 } else {
91 Box::new(BufWriter::new(io::stdout()))
93 };
94
95 for (src_ip, src_port, dst_ip, dst_port, protocol, packet_data) in PcapIter::new(pcap_reader) {
96 packet_counter += 1;
97 if let Some(max_packets) = config.input_size
98 && packet_counter > max_packets
99 {
100 break;
101 }
102
103 let flow_key = (src_ip, src_port, dst_ip, dst_port);
104 if let Some(message) = handler.decode(flow_key, protocol, &packet_data, &mut exporter_peers)
105 {
106 for result in message {
107 let serialized_data = handler.serialize(result)?;
108 writer.write_all(serde_json::to_string(&serialized_data)?.as_bytes())?;
109 writer.write_all(b"\n")?;
110 }
111 }
112 }
113
114 writer.flush()?;
115 Ok(())
116}