Skip to main content

bgpkit_parser/parser/iters/
default.rs

1/*!
2Default iterator implementations that skip errors and return successfully parsed items.
3*/
4use crate::error::ParserError;
5use crate::models::*;
6use crate::parser::BgpkitParser;
7use crate::{Elementor, Filterable};
8use log::{error, warn};
9use std::io::Read;
10
11/*********
12MrtRecord Iterator
13**********/
14
15pub struct RecordIterator<R> {
16    pub parser: BgpkitParser<R>,
17    pub count: u64,
18    elementor: Elementor,
19}
20
21impl<R> RecordIterator<R> {
22    pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
23        RecordIterator {
24            parser,
25            count: 0,
26            elementor: Elementor::new(),
27        }
28    }
29}
30
31impl<R: Read> Iterator for RecordIterator<R> {
32    type Item = MrtRecord;
33
34    fn next(&mut self) -> Option<MrtRecord> {
35        self.count += 1;
36        loop {
37            return match self.parser.next_record() {
38                Ok(v) => {
39                    // if None, the reaches EoF.
40                    let filters = &self.parser.filters;
41                    if filters.is_empty() {
42                        Some(v)
43                    } else {
44                        if let MrtMessage::TableDumpV2Message(TableDumpV2Message::PeerIndexTable(
45                            _,
46                        )) = &v.message
47                        {
48                            let _ = self.elementor.record_to_elems(v.clone());
49                            return Some(v);
50                        }
51                        let elems = self.elementor.record_to_elems(v.clone());
52                        if elems.iter().any(|e| e.match_filters(&self.parser.filters)) {
53                            Some(v)
54                        } else {
55                            continue;
56                        }
57                    }
58                }
59                Err(e) => {
60                    match e.error {
61                        ParserError::TruncatedMsg(err_str) | ParserError::Unsupported(err_str) => {
62                            if self.parser.options.show_warnings {
63                                warn!("parser warn: {}", err_str);
64                            }
65                            if let Some(bytes) = e.bytes {
66                                std::fs::write("mrt_core_dump", bytes)
67                                    .expect("Unable to write to mrt_core_dump");
68                            }
69                            continue;
70                        }
71                        ParserError::ParseError(err_str) => {
72                            error!("parser error: {}", err_str);
73                            if self.parser.core_dump {
74                                if let Some(bytes) = e.bytes {
75                                    std::fs::write("mrt_core_dump", bytes)
76                                        .expect("Unable to write to mrt_core_dump");
77                                }
78                                None
79                            } else {
80                                continue;
81                            }
82                        }
83                        ParserError::EofExpected => {
84                            // normal end of file
85                            None
86                        }
87                        ParserError::IoError(err) | ParserError::EofError(err) => {
88                            // when reaching IO error, stop iterating
89                            error!("{:?}", err);
90                            if self.parser.core_dump {
91                                if let Some(bytes) = e.bytes {
92                                    std::fs::write("mrt_core_dump", bytes)
93                                        .expect("Unable to write to mrt_core_dump");
94                                }
95                            }
96                            None
97                        }
98                        #[cfg(feature = "oneio")]
99                        ParserError::OneIoError(_) => None,
100                        ParserError::FilterError(_) => {
101                            // this should not happen at this stage
102                            None
103                        }
104                        // Labeled NLRI parsing errors - treat as malformed and skip
105                        ParserError::InvalidLabeledNlriLength
106                        | ParserError::TruncatedLabeledNlri
107                        | ParserError::TruncatedPrefix
108                        | ParserError::MaxLabelStackDepthExceeded
109                        | ParserError::PeerMaxLabelsExceeded
110                        | ParserError::InvalidPrefix => {
111                            if self.parser.options.show_warnings {
112                                warn!("parser warn: labeled NLRI parsing error: {:?}", e.error);
113                            }
114                            continue;
115                        }
116                    }
117                }
118            };
119        }
120    }
121}
122
123/*********
124BgpElem Iterator
125**********/
126
127pub struct ElemIterator<R> {
128    cache_elems: Vec<BgpElem>,
129    record_iter: RecordIterator<R>,
130    elementor: Elementor,
131    count: u64,
132}
133
134impl<R> ElemIterator<R> {
135    pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
136        ElemIterator {
137            record_iter: RecordIterator::new(parser),
138            count: 0,
139            cache_elems: vec![],
140            elementor: Elementor::new(),
141        }
142    }
143}
144
145impl<R: Read> Iterator for ElemIterator<R> {
146    type Item = BgpElem;
147
148    fn next(&mut self) -> Option<BgpElem> {
149        self.count += 1;
150
151        loop {
152            if self.cache_elems.is_empty() {
153                // refill cache elems
154                loop {
155                    match self.record_iter.next() {
156                        None => {
157                            // no more records
158                            return None;
159                        }
160                        Some(r) => {
161                            let mut elems = self.elementor.record_to_elems(r);
162                            if elems.is_empty() {
163                                // somehow this record does not contain any elems, continue to parse next record
164                                continue;
165                            } else {
166                                elems.reverse();
167                                self.cache_elems = elems;
168                                break;
169                            }
170                        }
171                    }
172                }
173                // when reaching here, the `self.cache_elems` has been refilled with some more elems
174            }
175
176            // popping cached elems. note that the original elems order is preseved by reversing the
177            // vector before putting it on to cache_elems.
178            let elem = self.cache_elems.pop();
179            match elem {
180                None => return None,
181                Some(e) => match e.match_filters(&self.record_iter.parser.filters) {
182                    true => return Some(e),
183                    false => continue,
184                },
185            }
186        }
187    }
188}