bgpkit-parser 0.20.0

MRT/BGP/BMP data processing library
Documentation
/*!
The RawMrtRecord Iterator module provides functionality for iterating over raw MRT records
from a BGP data source. This iterator is responsible for:

* Reading and parsing raw MRT records sequentially from an input stream
* Handling parsing errors and warnings appropriately
* Providing a clean interface for processing MRT records one at a time

The iterator implements error recovery strategies, allowing it to skip malformed records
when possible and continue processing the remaining data. It also supports configurable
warning messages and core dump generation for debugging purposes.
*/

use crate::parser::iters::write_mrt_core_dump;
use crate::{chunk_mrt_record, BgpkitParser, ParserError, RawMrtRecord};
use log::{error, warn};
use std::io::Read;

pub struct RawRecordIterator<R> {
    parser: BgpkitParser<R>,
    count: u64,
}

impl<R> RawRecordIterator<R> {
    pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
        RawRecordIterator { parser, count: 0 }
    }
}

impl<R: Read> Iterator for RawRecordIterator<R> {
    type Item = RawMrtRecord;

    fn next(&mut self) -> Option<RawMrtRecord> {
        // Text-dump parsers have no MRT-record representation; short-circuit.
        if self.parser.text_dump_iter.is_some() {
            return None;
        }
        self.count += 1;
        loop {
            match chunk_mrt_record(&mut self.parser.reader) {
                Ok(raw_record) => return Some(raw_record),
                Err(e) => match e.error {
                    ParserError::TruncatedMsg(err_str) | ParserError::Unsupported(err_str) => {
                        if self.parser.options.show_warnings {
                            warn!("parser warn: {}", err_str);
                        }
                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
                        continue;
                    }
                    ParserError::ParseError(err_str) => {
                        error!("parser error: {}", err_str);
                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
                        if self.parser.core_dump {
                            return None;
                        } else {
                            continue;
                        }
                    }
                    ParserError::EofExpected => {
                        // normal end of file
                        return None;
                    }
                    ParserError::IoError(err) | ParserError::EofError(err) => {
                        // when reaching IO error, stop iterating
                        error!("{:?}", err);
                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
                        return None;
                    }
                    #[cfg(feature = "oneio")]
                    ParserError::OneIoError(_) => return None,
                    ParserError::FilterError(_) => {
                        // this should not happen at this stage
                        return None;
                    }
                    // Labeled NLRI parsing errors - treat as malformed and skip
                    ParserError::InvalidLabeledNlriLength
                    | ParserError::TruncatedLabeledNlri
                    | ParserError::TruncatedPrefix
                    | ParserError::MaxLabelStackDepthExceeded
                    | ParserError::PeerMaxLabelsExceeded
                    | ParserError::InvalidPrefix => {
                        if self.parser.options.show_warnings {
                            warn!("parser warn: labeled NLRI parsing error: {:?}", e.error);
                        }
                        continue;
                    }
                },
            }
        }
    }
}