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::{chunk_mrt_record, BgpkitParser, ParserError, RawMrtRecord};
15use log::{error, warn};
16use std::io::Read;
17
18pub struct RawRecordIterator<R> {
19    parser: BgpkitParser<R>,
20    count: u64,
21}
22
23impl<R> RawRecordIterator<R> {
24    pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
25        RawRecordIterator { parser, count: 0 }
26    }
27}
28
29impl<R: Read> Iterator for RawRecordIterator<R> {
30    type Item = RawMrtRecord;
31
32    fn next(&mut self) -> Option<RawMrtRecord> {
33        self.count += 1;
34        match chunk_mrt_record(&mut self.parser.reader) {
35            Ok(raw_record) => Some(raw_record),
36            Err(e) => {
37                match e.error {
38                    ParserError::TruncatedMsg(err_str) | ParserError::Unsupported(err_str) => {
39                        if self.parser.options.show_warnings {
40                            warn!("parser warn: {}", err_str);
41                        }
42                        if let Some(bytes) = e.bytes {
43                            std::fs::write("mrt_core_dump", bytes)
44                                .expect("Unable to write to mrt_core_dump");
45                        }
46                        // skip this record and try next
47                        self.next()
48                    }
49                    ParserError::ParseError(err_str) => {
50                        error!("parser error: {}", err_str);
51                        if self.parser.core_dump {
52                            if let Some(bytes) = e.bytes {
53                                std::fs::write("mrt_core_dump", bytes)
54                                    .expect("Unable to write to mrt_core_dump");
55                            }
56                            None
57                        } else {
58                            // skip this record and try next
59                            self.next()
60                        }
61                    }
62                    ParserError::EofExpected => {
63                        // normal end of file
64                        None
65                    }
66                    ParserError::IoError(err) | ParserError::EofError(err) => {
67                        // when reaching IO error, stop iterating
68                        error!("{:?}", err);
69                        if self.parser.core_dump {
70                            if let Some(bytes) = e.bytes {
71                                std::fs::write("mrt_core_dump", bytes)
72                                    .expect("Unable to write to mrt_core_dump");
73                            }
74                        }
75                        None
76                    }
77                    #[cfg(feature = "oneio")]
78                    ParserError::OneIoError(_) => None,
79                    ParserError::FilterError(_) => {
80                        // this should not happen at this stage
81                        None
82                    }
83                }
84            }
85        }
86    }
87}