use crate::blocks::{PcapBlock, PcapBlockOwned};
use crate::error::PcapError;
use crate::pcapng::*;
use crate::traits::PcapReaderIterator;
use circular::Buffer;
use nom::{complete, do_parse, many1, IResult, Offset};
use std::fmt;
use std::io::Read;
pub struct PcapNGReader<R>
where
R: Read,
{
info: CurrentSectionInfo,
reader: R,
buffer: Buffer,
reader_exhausted: bool,
}
impl<R> PcapNGReader<R>
where
R: Read,
{
pub fn new(capacity: usize, mut reader: R) -> Result<PcapNGReader<R>, PcapError> {
let mut buffer = Buffer::with_capacity(capacity);
let sz = reader.read(buffer.space()).or(Err(PcapError::ReadError))?;
buffer.fill(sz);
let (_rem, _shb) = match parse_sectionheaderblock(buffer.data()) {
Ok((r, h)) => Ok((r, h)),
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(_) => Err(PcapError::Incomplete),
}?;
let info = CurrentSectionInfo::default();
Ok(PcapNGReader {
info,
reader,
buffer,
reader_exhausted: false,
})
}
pub fn from_buffer(mut buffer: Buffer, mut reader: R) -> Result<PcapNGReader<R>, PcapError> {
let sz = reader.read(buffer.space()).or(Err(PcapError::ReadError))?;
buffer.fill(sz);
let (_rem, _shb) = match parse_sectionheaderblock(buffer.data()) {
Ok((r, h)) => Ok((r, h)),
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(_) => Err(PcapError::Incomplete),
}?;
let info = CurrentSectionInfo::default();
Ok(PcapNGReader {
info,
reader,
buffer,
reader_exhausted: false,
})
}
}
impl<R> PcapReaderIterator<R> for PcapNGReader<R>
where
R: Read,
{
fn next(&mut self) -> Result<(usize, PcapBlockOwned), PcapError> {
if self.buffer.position() == 0 && self.buffer.available_data() == 0 || self.reader_exhausted
{
return Err(PcapError::Eof);
}
let data = self.buffer.data();
let parse = if self.info.big_endian {
parse_block_be
} else {
parse_block
};
match parse(data) {
Ok((rem, b)) => {
let offset = data.offset(rem);
if let Block::SectionHeader(ref shb) = b {
self.info.big_endian = shb.is_bigendian();
}
Ok((offset, PcapBlockOwned::from(b)))
}
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(_) => Err(PcapError::Incomplete),
}
}
fn consume(&mut self, offset: usize) {
self.buffer.consume(offset);
}
fn consume_noshift(&mut self, offset: usize) {
self.buffer.consume_noshift(offset);
}
fn refill(&mut self) -> Result<(), PcapError> {
self.buffer.shift();
let sz = self
.reader
.read(self.buffer.space())
.or(Err(PcapError::ReadError))?;
self.reader_exhausted = sz == 0;
self.buffer.fill(sz);
Ok(())
}
fn position(&self) -> usize {
self.buffer.position()
}
fn grow(&mut self, new_size: usize) -> bool {
self.buffer.grow(new_size)
}
fn data(&self) -> &[u8] {
self.buffer.data()
}
}
#[derive(Default)]
pub struct CurrentSectionInfo {
big_endian: bool,
}
pub struct PcapNGSlice<'a> {
info: CurrentSectionInfo,
rem: &'a [u8],
}
impl<'a> PcapNGSlice<'a> {
pub fn from_slice(i: &[u8]) -> Result<PcapNGSlice, nom::Err<PcapError>> {
let (_rem, _shb) = parse_sectionheaderblock(i)?;
let info = CurrentSectionInfo::default();
let rem = i;
Ok(PcapNGSlice { info, rem })
}
}
impl<'a> Iterator for PcapNGSlice<'a> {
type Item = Result<PcapBlockOwned<'a>, nom::Err<PcapError>>;
fn next(&mut self) -> Option<Result<PcapBlockOwned<'a>, nom::Err<PcapError>>> {
if self.rem.is_empty() {
return None;
}
let parse = if self.info.big_endian {
parse_block_be
} else {
parse_block
};
let r = parse(self.rem).map(|(rem, b)| {
self.rem = rem;
if let Block::SectionHeader(ref shb) = b {
self.info.big_endian = shb.is_bigendian();
}
PcapBlockOwned::from(b)
});
Some(r)
}
}
pub struct PcapNGCapture<'a> {
pub sections: Vec<Section<'a>>,
}
impl<'a> fmt::Debug for PcapNGCapture<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "PcapNGCapture:")
}
}
pub struct PcapNGCaptureIterator<'a> {
cap: &'a PcapNGCapture<'a>,
idx: usize,
}
impl<'a> Iterator for PcapNGCaptureIterator<'a> {
type Item = PcapBlock<'a>;
fn next(&mut self) -> Option<PcapBlock<'a>> {
if self.cap.sections.len() != 1 {
unimplemented!();
}
self.cap.sections[0].blocks.get(self.idx).map(|b| {
self.idx += 1;
PcapBlock::from(b)
})
}
}
impl<'a> PcapNGCapture<'a> {
pub fn from_file(i: &[u8]) -> Result<PcapNGCapture, PcapError> {
match parse_pcapng(i) {
Ok((_, pcap)) => Ok(pcap),
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(_) => Err(PcapError::Incomplete),
}
}
pub fn iter(&'a self) -> PcapNGCaptureIterator<'a> {
PcapNGCaptureIterator { cap: self, idx: 0 }
}
}
pub fn parse_pcapng(i: &[u8]) -> IResult<&[u8], PcapNGCapture, PcapError> {
do_parse!(
i,
sections: many1!(complete!(parse_section)) >> (PcapNGCapture { sections })
)
}