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}