frameassembly 0.9.0

A Domain-Specific Language (DSL) for writing deterministic network traffic to .pcap files.
Documentation
use pcap_file::pcapng::PcapNgBlock;
use pcap_file::pcapng::PcapNgWriter;
use pcap_file::pcapng::blocks::enhanced_packet::EnhancedPacketBlock;
use pcap_file::pcapng::blocks::interface_description::{
    InterfaceDescriptionBlock, InterfaceDescriptionOption,
};
use std::borrow::Cow;
use std::fs::File;
use std::io::{self, Error};

pub struct PcapWriter {
    writer: PcapNgWriter<File>,
}

impl PcapWriter {
    pub fn create(path: &str) -> io::Result<Self> {
        let file = File::create(path)?;
        let mut writer = PcapNgWriter::new(file).map_err(|e| {
            Error::other(alloc::format!("Failed to create PCAP writer: {}", e))
        })?;

        let interface = InterfaceDescriptionBlock {
            linktype: pcap_file::DataLink::ETHERNET,
            snaplen: 65535,
            options: vec![InterfaceDescriptionOption::IfTsResol(9)],
        };
        writer.write_block(&interface.into_block()).map_err(|e| {
            Error::other(alloc::format!("Failed to write PCAP interface block: {}", e))
        })?;

        Ok(Self { writer })
    }

    pub fn write_packet(&mut self, packet_data: &[u8], ts_nanos_total: u64) -> io::Result<()> {
        let length = packet_data.len() as u32;

        let epb = EnhancedPacketBlock {
            interface_id: 0,
            timestamp: std::time::Duration::from_nanos(ts_nanos_total),
            original_len: length,
            data: Cow::Borrowed(packet_data),
            options: vec![],
        };
        self.writer.write_block(&epb.into_block()).map_err(|e| {
            Error::other(alloc::format!("Failed to write PCAP packet block: {}", e))
        })?;
        Ok(())
    }
}