pcap_file/pcap/
writer.rs

1use std::io::Write;
2
3use byteorder_slice::{BigEndian, LittleEndian};
4
5use super::RawPcapPacket;
6use crate::errors::*;
7use crate::pcap::{PcapHeader, PcapPacket};
8use crate::{Endianness, TsResolution};
9
10
11/// Writes a pcap to a writer.
12///
13/// # Example
14/// ```rust,no_run
15/// use std::fs::File;
16///
17/// use pcap_file::pcap::{PcapReader, PcapWriter};
18///
19/// let file_in = File::open("test.pcap").expect("Error opening file");
20/// let mut pcap_reader = PcapReader::new(file_in).unwrap();
21///
22/// let file_out = File::create("out.pcap").expect("Error creating file out");
23/// let mut pcap_writer = PcapWriter::new(file_out).expect("Error writing file");
24///
25/// // Read test.pcap
26/// while let Some(pkt) = pcap_reader.next_packet() {
27///     //Check if there is no error
28///     let pkt = pkt.unwrap();
29///
30///     //Write each packet of test.pcap in out.pcap
31///     pcap_writer.write_packet(&pkt).unwrap();
32/// }
33/// ```
34#[derive(Debug)]
35pub struct PcapWriter<W: Write> {
36    endianness: Endianness,
37    snaplen: u32,
38    ts_resolution: TsResolution,
39    writer: W,
40}
41
42impl<W: Write> PcapWriter<W> {
43    /// Creates a new [`PcapWriter`] from an existing writer.
44    ///
45    /// Defaults to the native endianness of the CPU.
46    ///
47    /// Writes this default global pcap header to the file:
48    /// ```rust, ignore
49    /// PcapHeader {
50    ///     version_major: 2,
51    ///     version_minor: 4,
52    ///     ts_correction: 0,
53    ///     ts_accuracy: 0,
54    ///     snaplen: 65535,
55    ///     datalink: DataLink::ETHERNET,
56    ///     ts_resolution: TsResolution::MicroSecond,
57    ///     endianness: Endianness::Native
58    /// };
59    /// ```
60    ///
61    /// # Errors
62    /// The writer can't be written to.
63    pub fn new(writer: W) -> PcapResult<PcapWriter<W>> {
64        let header = PcapHeader { endianness: Endianness::native(), ..Default::default() };
65
66        PcapWriter::with_header(writer, header)
67    }
68
69    /// Creates a new [`PcapWriter`] from an existing writer with a user defined [`PcapHeader`].
70    ///
71    /// It also writes the pcap header to the file.
72    ///
73    /// # Errors
74    /// The writer can't be written to.
75    pub fn with_header(mut writer: W, header: PcapHeader) -> PcapResult<PcapWriter<W>> {
76        header.write_to(&mut writer)?;
77
78        Ok(PcapWriter {
79            endianness: header.endianness,
80            snaplen: header.snaplen,
81            ts_resolution: header.ts_resolution,
82            writer,
83        })
84    }
85
86    /// Consumes [`Self`], returning the wrapped writer.
87    pub fn into_writer(self) -> W {
88        self.writer
89    }
90
91    /// Writes a [`PcapPacket`].
92    pub fn write_packet(&mut self, packet: &PcapPacket) -> PcapResult<usize> {
93        match self.endianness {
94            Endianness::Big => packet.write_to::<_, BigEndian>(&mut self.writer, self.ts_resolution, self.snaplen),
95            Endianness::Little => packet.write_to::<_, LittleEndian>(&mut self.writer, self.ts_resolution, self.snaplen),
96        }
97    }
98
99    /// Writes a [`RawPcapPacket`].
100    pub fn write_raw_packet(&mut self, packet: &RawPcapPacket) -> PcapResult<usize> {
101        match self.endianness {
102            Endianness::Big => packet.write_to::<_, BigEndian>(&mut self.writer),
103            Endianness::Little => packet.write_to::<_, LittleEndian>(&mut self.writer),
104        }
105    }
106
107    /// Returns the endianess used by the writer.
108    pub fn endianness(&self) -> Endianness {
109        self.endianness
110    }
111
112    /// Returns the snaplen used by the writer, i.e. an unsigned value indicating the maximum number of octets captured
113    /// from each packet.
114    pub fn snaplen(&self) -> u32 {
115        self.snaplen
116    }
117
118    /// Returns the timestamp resolution of the writer.
119    pub fn ts_resolution(&self) -> TsResolution {
120        self.ts_resolution
121    }
122}