use crate::blocks::{PcapBlock, PcapBlockOwned};
use crate::capture::Capture;
use crate::error::PcapError;
use crate::linktype::Linktype;
use crate::pcap::{parse_pcap_frame, parse_pcap_header, LegacyPcapBlock, PcapHeader};
use nom::combinator::complete;
use nom::multi::many0;
use nom::{IResult, Needed, Parser as _};
use std::fmt;
pub struct LegacyPcapSlice<'a> {
pub header: PcapHeader,
rem: &'a [u8],
}
impl LegacyPcapSlice<'_> {
pub fn from_slice(i: &[u8]) -> Result<LegacyPcapSlice<'_>, nom::Err<PcapError<&[u8]>>> {
let (rem, header) = parse_pcap_header(i)?;
Ok(LegacyPcapSlice { header, rem })
}
}
impl<'a> Iterator for LegacyPcapSlice<'a> {
type Item = Result<PcapBlockOwned<'a>, nom::Err<PcapError<&'a [u8]>>>;
fn next(&mut self) -> Option<Self::Item> {
if self.rem.is_empty() {
return None;
}
let r = parse_pcap_frame(self.rem).map(|(rem, b)| {
self.rem = rem;
PcapBlockOwned::from(b)
});
Some(r)
}
}
pub struct PcapCapture<'a> {
pub header: PcapHeader,
pub blocks: Vec<LegacyPcapBlock<'a>>,
}
impl PcapCapture<'_> {
pub fn from_file(i: &[u8]) -> Result<PcapCapture<'_>, PcapError<&[u8]>> {
match parse_pcap(i) {
Ok((_, pcap)) => Ok(pcap),
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
}
}
}
impl fmt::Debug for PcapCapture<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "PcapCapture:")
}
}
pub struct LegacyPcapIterator<'a> {
cap: &'a PcapCapture<'a>,
idx: usize,
}
impl<'a> Iterator for LegacyPcapIterator<'a> {
type Item = PcapBlock<'a>;
fn next(&mut self) -> Option<PcapBlock<'a>> {
self.cap.blocks.get(self.idx).map(|b| {
self.idx += 1;
PcapBlock::from(b)
})
}
}
impl Capture for PcapCapture<'_> {
fn get_datalink(&self) -> Linktype {
self.header.network
}
fn get_snaplen(&self) -> u32 {
self.header.snaplen
}
fn iter<'b>(&'b self) -> Box<dyn Iterator<Item = PcapBlock<'b>> + 'b> {
Box::new(LegacyPcapIterator { cap: self, idx: 0 })
}
}
pub fn parse_pcap(i: &[u8]) -> IResult<&[u8], PcapCapture<'_>, PcapError<&[u8]>> {
let (i, header) = parse_pcap_header(i)?;
let (i, blocks) = many0(complete(parse_pcap_frame)).parse(i)?;
Ok((i, PcapCapture { header, blocks }))
}