Skip to main content

bgpkit_parser/parser/iters/
raw.rs

1/*!
2The RawMrtRecord Iterator module provides functionality for iterating over raw MRT records
3from a BGP data source. This iterator is responsible for:
4
5* Reading and parsing raw MRT records sequentially from an input stream
6* Handling parsing errors and warnings appropriately
7* Providing a clean interface for processing MRT records one at a time
8
9The iterator implements error recovery strategies, allowing it to skip malformed records
10when possible and continue processing the remaining data. It also supports configurable
11warning messages and core dump generation for debugging purposes.
12*/
13
14use crate::parser::iters::write_mrt_core_dump;
15use crate::{chunk_mrt_record, BgpkitParser, ParserError, RawMrtRecord};
16use log::{error, warn};
17use std::io::Read;
18
19pub struct RawRecordIterator<R> {
20    parser: BgpkitParser<R>,
21    count: u64,
22}
23
24impl<R> RawRecordIterator<R> {
25    pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
26        RawRecordIterator { parser, count: 0 }
27    }
28}
29
30impl<R: Read> Iterator for RawRecordIterator<R> {
31    type Item = RawMrtRecord;
32
33    fn next(&mut self) -> Option<RawMrtRecord> {
34        // Text-dump parsers have no MRT-record representation; short-circuit.
35        if self.parser.text_dump_iter.is_some() {
36            return None;
37        }
38        self.count += 1;
39        loop {
40            match chunk_mrt_record(&mut self.parser.reader) {
41                Ok(raw_record) => return Some(raw_record),
42                Err(e) => match e.error {
43                    ParserError::TruncatedMsg(err_str) | ParserError::Unsupported(err_str) => {
44                        if self.parser.options.show_warnings {
45                            warn!("parser warn: {}", err_str);
46                        }
47                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
48                        continue;
49                    }
50                    ParserError::ParseError(err_str) => {
51                        error!("parser error: {}", err_str);
52                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
53                        if self.parser.core_dump {
54                            return None;
55                        } else {
56                            continue;
57                        }
58                    }
59                    ParserError::EofExpected => {
60                        // normal end of file
61                        return None;
62                    }
63                    ParserError::IoError(err) | ParserError::EofError(err) => {
64                        // when reaching IO error, stop iterating
65                        error!("{:?}", err);
66                        write_mrt_core_dump(self.parser.core_dump, e.bytes);
67                        return None;
68                    }
69                    #[cfg(feature = "oneio")]
70                    ParserError::OneIoError(_) => return None,
71                    ParserError::FilterError(_) => {
72                        // this should not happen at this stage
73                        return None;
74                    }
75                    // Labeled NLRI parsing errors - treat as malformed and skip
76                    ParserError::InvalidLabeledNlriLength
77                    | ParserError::TruncatedLabeledNlri
78                    | ParserError::TruncatedPrefix
79                    | ParserError::MaxLabelStackDepthExceeded
80                    | ParserError::PeerMaxLabelsExceeded
81                    | ParserError::InvalidPrefix => {
82                        if self.parser.options.show_warnings {
83                            warn!("parser warn: labeled NLRI parsing error: {:?}", e.error);
84                        }
85                        continue;
86                    }
87                },
88            }
89        }
90    }
91}