use bgpkit_parser::{BgpkitParser, DiagnosticEvent};
use std::path::{Path, PathBuf};
fn main() {
let source = std::env::args().nth(1).unwrap_or_else(|| {
eprintln!("Usage: diagnostic_iterator <MRT_FILE_OR_URL> [OUTPUT_DIR]");
std::process::exit(2);
});
let output_dir = std::env::args()
.nth(2)
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from("diagnostic-records"));
let parser = BgpkitParser::new(&source).unwrap_or_else(|error| {
eprintln!("Unable to open {source}: {error}");
std::process::exit(1);
});
let mut clean = 0;
let mut validation = 0;
let mut parse_errors = 0;
for (index, event) in parser.into_diagnostic_iter().enumerate() {
match event {
DiagnosticEvent::Record(_) => clean += 1,
DiagnosticEvent::Validation {
warnings,
raw_record,
..
} => {
validation += 1;
let path = output_path(&output_dir, index, "validation");
save_raw_record(&raw_record, &path);
eprintln!(
"record {index}: {} validation finding(s) -> {}",
warnings.len(),
path.display()
);
}
DiagnosticEvent::ParseError {
error,
common_header,
raw_bytes,
} => {
parse_errors += 1;
eprintln!("record {index}: {error}");
if let Some(header) = common_header {
eprintln!(" header: {header}");
}
if let Some(bytes) = raw_bytes {
let path = output_path(&output_dir, index, "parse-error");
save_bytes(&bytes, &path);
}
}
_ => {}
}
}
println!("clean records: {clean}");
println!("records with validation findings: {validation}");
println!("fatal parse errors: {parse_errors}");
}
fn output_path(output_dir: &Path, index: usize, kind: &str) -> PathBuf {
output_dir.join(format!("{index:08}-{kind}.mrt"))
}
fn save_raw_record(raw_record: &bgpkit_parser::RawMrtRecord, path: &PathBuf) {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("failed to create output directory");
}
raw_record
.write_raw_bytes(path)
.expect("failed to write diagnostic record");
}
fn save_bytes(bytes: &[u8], path: &PathBuf) {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("failed to create output directory");
}
std::fs::write(path, bytes).expect("failed to write diagnostic record");
eprintln!(" saved {} bytes to {}", bytes.len(), path.display());
}