pcaparse/pcap/
parser.rs

1use byteorder::{BigEndian, LittleEndian};
2
3use super::RawPcapPacket;
4use crate::errors::*;
5use crate::pcap::{PcapHeader, PcapPacket};
6use crate::Endianness;
7
8/// Parses a Pcap from a slice of bytes.
9///
10/// You can match on [`PcapError::IncompleteBuffer`](crate::errors::PcapError) to known if the parser need more data.
11///
12/// # Example
13/// ```no_run
14/// use pcaparse::pcap::PcapParser;
15/// use pcaparse::PcapError;
16///
17/// let pcap = vec![0_u8; 0];
18/// let mut src = &pcap[..];
19///
20/// // Creates a new parser and parse the pcap header
21/// let (rem, pcap_parser) = PcapParser::new(&pcap[..]).unwrap();
22/// src = rem;
23///
24/// loop {
25///     match pcap_parser.next_packet(src) {
26///         Ok((rem, packet)) => {
27///             // Do something
28///
29///             // Don't forget to update src
30///             src = rem;
31///
32///             // No more data, if no more incoming either then this is the end of the file
33///             if rem.is_empty() {
34///                 break;
35///             }
36///         },
37///         Err(PcapError::IncompleteBuffer) => {}, // Load more data into src
38///         Err(_) => {},                           // Parsing error
39///     }
40/// }
41/// ```
42#[derive(Debug)]
43pub struct PcapParser {
44    header: PcapHeader,
45}
46
47impl PcapParser {
48    /// Creates a new [`PcapParser`].
49    ///
50    /// Returns the remainder and the parser.
51    pub fn new(slice: &[u8]) -> PcapResult<(&[u8], PcapParser)> {
52        let (slice, header) = PcapHeader::from_slice(slice)?;
53
54        let parser = PcapParser { header };
55
56        Ok((slice, parser))
57    }
58
59    /// Creates a new Asynchronously [`PcapParser`].
60    ///
61    /// Returns the remainder and the parser.
62    #[cfg(feature = "tokio")]
63    pub async fn async_new(slice: &[u8]) -> PcapResult<(&[u8], PcapParser)> {
64        let (slice, header) = PcapHeader::async_from_slice(slice).await?;
65
66        let parser = PcapParser { header };
67
68        Ok((slice, parser))
69    }
70
71    /// Returns the remainder and the next [`PcapPacket`].
72    pub fn next_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], PcapPacket<'a>)> {
73        match self.header.endianness {
74            Endianness::Big => PcapPacket::from_slice::<BigEndian>(slice, self.header.ts_resolution, self.header.snaplen),
75            Endianness::Little => PcapPacket::from_slice::<LittleEndian>(slice, self.header.ts_resolution, self.header.snaplen),
76        }
77    }
78
79    /// Asynchronously returns the remainder and the next [`PcapPacket`].
80    #[cfg(feature = "tokio")]
81    pub async fn async_next_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], PcapPacket<'a>)> {
82        match self.header.endianness {
83            Endianness::Big => PcapPacket::async_from_slice::<BigEndian>(slice, self.header.ts_resolution, self.header.snaplen).await,
84            Endianness::Little => PcapPacket::async_from_slice::<LittleEndian>(slice, self.header.ts_resolution, self.header.snaplen).await,
85        }
86    }
87
88    /// Returns the remainder and the next [`RawPcapPacket`].
89    pub fn next_raw_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], RawPcapPacket<'a>)> {
90        match self.header.endianness {
91            Endianness::Big => RawPcapPacket::from_slice::<BigEndian>(slice),
92            Endianness::Little => RawPcapPacket::from_slice::<LittleEndian>(slice),
93        }
94    }
95
96    /// Asynchronously returns the remainder and the next [`RawPcapPacket`].
97    #[cfg(feature = "tokio")]
98    pub async fn async_next_raw_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], RawPcapPacket<'a>)> {
99        match self.header.endianness {
100            Endianness::Big => RawPcapPacket::async_from_slice::<BigEndian>(slice).await,
101            Endianness::Little => RawPcapPacket::async_from_slice::<LittleEndian>(slice).await,
102        }
103    }
104
105    /// Returns the header of the pcap file.
106    pub fn header(&self) -> PcapHeader {
107        self.header
108    }
109}