pcaparse/pcap/
reader.rs

1use std::io::Read;
2
3#[cfg(feature = "tokio")]
4use tokio::io::AsyncRead;
5
6use super::{PcapParser, RawPcapPacket};
7use crate::pcap::{PcapHeader, PcapPacket};
8use crate::read_buffer::ReadBuffer;
9use crate::{DataLink, Packet, errors::*};
10
11/// Reads a pcap from a reader.
12///
13/// # Example
14///
15/// ```rust,no_run
16/// use std::fs::File;
17///
18/// use pcaparse::pcap::PcapReader;
19///
20/// let file_in = File::open("test.pcap").expect("Error opening file");
21/// let mut pcap_reader = PcapReader::new(file_in).unwrap();
22///
23/// // Read test.pcap
24/// while let Some(pkt) = pcap_reader.next_packet() {
25///     //Check if there is no error
26///     let pkt = pkt.unwrap();
27///
28///     //Do something
29/// }
30/// ```
31#[derive(Debug)]
32pub struct PcapReader<R> {
33    parser: PcapParser,
34    reader: ReadBuffer<R>,
35}
36
37impl<R> From<(PcapParser, ReadBuffer<R>)> for PcapReader<R> {
38    fn from(value: (PcapParser, ReadBuffer<R>)) -> Self {
39        Self { parser: value.0, reader: value.1 }
40    }
41}
42
43impl<'a> From<(PcapPacket<'a>, DataLink)> for Packet<'a> {
44    fn from(value: (PcapPacket<'a>, DataLink)) -> Self {
45        Self {
46            timestamp: Some(value.0.timestamp),
47            orig_len: value.0.orig_len,
48            data: value.0.data,
49            datalink: value.1,
50        }
51    }
52}
53
54impl<R> PcapReader<R> {
55    /// Returns the global header of the pcap.
56    pub fn header(&self) -> PcapHeader {
57        self.parser.header()
58    }
59
60    /// Returns the datalink
61    pub fn datalink(&self) -> DataLink {
62        self.parser.header().datalink
63    }
64}
65
66impl<R: Read> PcapReader<R> {
67    /// Creates a new [`PcapReader`] from an existing reader.
68    ///
69    /// This function reads the global pcap header of the file to verify its integrity.
70    ///
71    /// The underlying reader must point to a valid pcap file/stream.
72    ///
73    /// # Errors
74    /// The data stream is not in a valid pcap file format.
75    ///
76    /// The underlying data are not readable.
77    pub fn new(reader: R) -> Result<PcapReader<R>, PcapError> {
78        let mut reader = ReadBuffer::new(reader);
79        let parser = reader.parse_with(PcapParser::new)?;
80
81        Ok(PcapReader { parser, reader })
82    }
83
84    /// Consumes [`Self`], returning the wrapped reader.
85    pub fn into_reader(self) -> R {
86        self.reader.into_inner()
87    }
88
89    /// Returns the next [`PcapPacket`].
90    pub fn next_packet(&mut self) -> Option<Result<PcapPacket<'_>, PcapError>> {
91        match self.reader.has_data_left() {
92            Ok(has_data) => {
93                if has_data {
94                    Some(self.reader.parse_with(|src| self.parser.next_packet(src)))
95                } else {
96                    None
97                }
98            },
99            Err(e) => Some(Err(PcapError::IoError(e))),
100        }
101    }
102
103    /// Returns the next [`RawPcapPacket`].
104    pub fn next_raw_packet(&mut self) -> Option<Result<RawPcapPacket<'_>, PcapError>> {
105        match self.reader.has_data_left() {
106            Ok(has_data) => {
107                if has_data {
108                    Some(self.reader.parse_with(|src| self.parser.next_raw_packet(src)))
109                } else {
110                    None
111                }
112            },
113            Err(e) => Some(Err(PcapError::IoError(e))),
114        }
115    }
116}
117
118impl<R> AsRef<R> for PcapReader<R> {
119    fn as_ref(&self) -> &R {
120        self.reader.as_ref()
121    }
122}
123
124impl<R> AsMut<R> for PcapReader<R> {
125    fn as_mut(&mut self) -> &mut R {
126        self.reader.as_mut()
127    }
128}
129
130#[cfg(feature = "tokio")]
131impl<R: AsyncRead + Unpin> PcapReader<R> {
132    /// Creates a new [`PcapReader`] from an existing reader.
133    ///
134    /// This function reads the global pcap header of the file to verify its integrity.
135    ///
136    /// The underlying reader must point to a valid pcap file/stream.
137    ///
138    /// # Errors
139    /// The data stream is not in a valid pcap file format.
140    ///
141    /// The underlying data are not readable.
142    pub async fn async_new(reader: R) -> Result<PcapReader<R>, PcapError> {
143        let mut reader = ReadBuffer::new(reader);
144        let parser = reader.async_parse_with(PcapParser::async_new).await?;
145
146        Ok(PcapReader { parser, reader })
147    }
148
149    /// Consumes [`Self`], returning the wrapped reader.
150    pub fn into_async_reader(self) -> R {
151        self.reader.into_inner()
152    }
153
154    /// Returns the next [`PcapPacket`].
155    pub async fn async_next_packet(&mut self) -> Option<Result<PcapPacket<'_>, PcapError>> {
156        match self.reader.async_has_data_left().await {
157            Ok(has_data) => {
158                if has_data {
159                    Some(self.reader.async_parse_with(|src| self.parser.async_next_packet(src)).await)
160                } else {
161                    None
162                }
163            },
164            Err(e) => Some(Err(PcapError::IoError(e))),
165        }
166    }
167
168    /// Returns the next [`RawPcapPacket`].
169    pub async fn async_next_raw_packet(&mut self) -> Option<Result<RawPcapPacket<'_>, PcapError>> {
170        match self.reader.async_has_data_left().await {
171            Ok(has_data) => {
172                if has_data {
173                    Some(self.reader.async_parse_with(|src| self.parser.async_next_raw_packet(src)).await)
174                } else {
175                    None
176                }
177            },
178            Err(e) => Some(Err(PcapError::IoError(e))),
179        }
180    }
181}