use crate::blocks::{PcapBlock, PcapBlockOwned};
use crate::error::PcapError;
use crate::pcapng::*;
use crate::traits::PcapReaderIterator;
use circular::Buffer;
use nom::combinator::{complete, map};
use nom::multi::many1;
use nom::{IResult, Offset};
use std::fmt;
use std::io::Read;
pub struct PcapNGReader<R>
where
R: Read,
{
info: CurrentSectionInfo,
reader: R,
buffer: Buffer,
consumed: usize,
reader_exhausted: bool,
}
impl<R> PcapNGReader<R>
where
R: Read,
{
pub fn new(capacity: usize, reader: R) -> Result<PcapNGReader<R>, PcapError<&'static [u8]>> {
let buffer = Buffer::with_capacity(capacity);
Self::from_buffer(buffer, reader)
}
pub fn from_buffer(
mut buffer: Buffer,
mut reader: R,
) -> Result<PcapNGReader<R>, PcapError<&'static [u8]>> {
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.to_owned_vec()),
Err(_) => Err(PcapError::Incomplete),
}?;
let info = CurrentSectionInfo::default();
Ok(PcapNGReader {
info,
reader,
buffer,
consumed: 0,
reader_exhausted: false,
})
}
}
impl<R> PcapReaderIterator for PcapNGReader<R>
where
R: Read,
{
fn next(&mut self) -> Result<(usize, PcapBlockOwned), PcapError<&[u8]>> {
if self.buffer.available_data() == 0
&& (self.buffer.position() == 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_le
};
match parse(data) {
Ok((rem, b)) => {
let offset = data.offset(rem);
if let Block::SectionHeader(ref shb) = b {
self.info.big_endian = shb.big_endian();
}
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.consumed += offset;
self.buffer.consume(offset);
}
fn consume_noshift(&mut self, offset: usize) {
self.consumed += offset;
self.buffer.consume_noshift(offset);
}
fn consumed(&self) -> usize {
self.consumed
}
fn refill(&mut self) -> Result<(), PcapError<&[u8]>> {
self.buffer.shift();
let space = self.buffer.space();
if space.is_empty() {
return Ok(());
}
let sz = self.reader.read(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()
}
fn reader_exhausted(&self) -> bool {
self.reader_exhausted
}
}
#[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<&[u8]>>> {
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<&'a [u8]>>>;
fn next(&mut self) -> Option<Self::Item> {
if self.rem.is_empty() {
return None;
}
let parse = if self.info.big_endian {
parse_block_be
} else {
parse_block_le
};
let r = parse(self.rem).map(|(rem, b)| {
self.rem = rem;
if let Block::SectionHeader(ref shb) = b {
self.info.big_endian = shb.big_endian();
}
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<&[u8]>> {
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<&[u8]>> {
map(many1(complete(parse_section)), |sections| PcapNGCapture {
sections,
})(i)
}