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}