bgpkit_parser/parser/bmp/messages/
initiation_message.rs1use crate::parser::bmp::error::ParserBmpError;
2use crate::parser::ReadUtils;
3use bytes::{Buf, Bytes};
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5use std::convert::TryFrom;
6
7#[derive(Debug, Clone, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct InitiationMessage {
10 pub tlvs: Vec<InitiationTlv>,
11}
12
13#[derive(Debug, PartialEq, Clone)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct InitiationTlv {
16 pub info_type: InitiationTlvType,
17 pub info_len: u16,
18 pub info: String,
19}
20
21#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26#[repr(u16)]
27pub enum InitiationTlvType {
28 String = 0,
29 SysDescr = 1,
30 SysName = 2,
31 VrTableName = 3,
32 AdminLabel = 4,
33}
34
35pub fn parse_initiation_message(data: &mut Bytes) -> Result<InitiationMessage, ParserBmpError> {
39 let mut tlvs = vec![];
40
41 while data.remaining() > 4 {
42 let info_type: InitiationTlvType = InitiationTlvType::try_from(data.get_u16())?;
43 let info_len = data.get_u16();
44 if data.remaining() < info_len as usize {
45 break;
47 }
48 let info = data.read_n_bytes_to_string(info_len as usize)?;
49 tlvs.push(InitiationTlv {
50 info_type,
51 info_len,
52 info,
53 });
54 }
55
56 Ok(InitiationMessage { tlvs })
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use bytes::{BufMut, BytesMut};
63
64 #[test]
65 fn test_parse_initiation_message() {
66 let mut buffer = BytesMut::new();
67 buffer.put_u16(1); buffer.put_u16(5); buffer.put_slice(b"Test1"); let mut bytes = buffer.freeze();
72
73 match parse_initiation_message(&mut bytes) {
74 Ok(initiation_message) => {
75 for tlv in initiation_message.tlvs {
76 assert_eq!(tlv.info_type, InitiationTlvType::SysDescr);
77 assert_eq!(tlv.info_len, 5);
78 assert_eq!(tlv.info, "Test1".to_string());
79 }
80 }
81 Err(_) => panic!("Failed to parse initiation message"),
82 }
83 }
84
85 #[test]
86 fn test_debug() {
87 let initiation_message = InitiationMessage {
88 tlvs: vec![InitiationTlv {
89 info_type: InitiationTlvType::SysDescr,
90 info_len: 5,
91 info: "Test1".to_string(),
92 }],
93 };
94 assert_eq!(
95 format!("{:?}", initiation_message),
96 "InitiationMessage { tlvs: [InitiationTlv { info_type: SysDescr, info_len: 5, info: \"Test1\" }] }"
97 );
98 }
99}