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}