pcap_file_tokio/pcap/
reader.rs

1use tokio::io::AsyncRead;
2
3use super::{PcapParser, RawPcapPacket};
4use crate::errors::*;
5use crate::pcap::{PcapHeader, PcapPacket};
6use crate::read_buffer::ReadBuffer;
7
8
9/// Reads a pcap from a reader.
10///
11/// # Example
12///
13/// ```rust,no_run
14/// # tokio_test::block_on(async {
15/// use tokio::fs::File;
16///
17/// use pcap_file_tokio::pcap::PcapReader;
18///
19/// let file_in = File::open("test.pcap").await.expect("Error opening file");
20/// let mut pcap_reader = PcapReader::new(file_in).await.unwrap();
21///
22/// // Read test.pcap
23/// while let Some(pkt) = pcap_reader.next_packet().await {
24///     //Check if there is no error
25///     let pkt = pkt.unwrap();
26///
27///     //Do something
28/// }
29/// # });
30/// ```
31#[derive(Debug)]
32pub struct PcapReader<R: AsyncRead + Unpin> {
33    parser: PcapParser,
34    reader: ReadBuffer<R>,
35}
36
37impl<R: AsyncRead + Unpin> PcapReader<R> {
38    /// Creates a new [`PcapReader`] from an existing reader.
39    ///
40    /// This function reads the global pcap header of the file to verify its integrity.
41    ///
42    /// The underlying reader must point to a valid pcap file/stream.
43    ///
44    /// # Errors
45    /// The data stream is not in a valid pcap file format.
46    ///
47    /// The underlying data are not readable.
48    pub async fn new(reader: R) -> Result<PcapReader<R>, PcapError> {
49        let mut reader = ReadBuffer::new(reader);
50        let parser = reader.parse_with(PcapParser::new).await?;
51
52        Ok(PcapReader { parser, reader })
53    }
54
55    /// Consumes [`Self`], returning the wrapped reader.
56    pub fn into_reader(self) -> R {
57        self.reader.into_inner()
58    }
59
60    /// Returns the next [`PcapPacket`].
61    pub async fn next_packet(&mut self) -> Option<Result<PcapPacket, PcapError>> {
62        match self.reader.has_data_left().await {
63            Ok(has_data) => {
64                if has_data {
65                    Some(self.reader.parse_with(|src|  self.parser.next_packet(src)).await)
66                }
67                else {
68                    None
69                }
70            },
71            Err(e) => Some(Err(PcapError::IoError(e))),
72        }
73    }
74
75    /// Returns the next [`RawPcapPacket`].
76    pub async fn next_raw_packet(&mut self) -> Option<Result<RawPcapPacket, PcapError>> {
77        match self.reader.has_data_left().await {
78            Ok(has_data) => {
79                if has_data {
80                    Some(self.reader.parse_with(|src| self.parser.next_raw_packet(src)).await)
81                }
82                else {
83                    None
84                }
85            },
86            Err(e) => Some(Err(PcapError::IoError(e))),
87        }
88    }
89
90    /// Returns the global header of the pcap.
91    pub fn header(&self) -> PcapHeader {
92        self.parser.header()
93    }
94}