bgpkit_parser/parser/bmp/messages/
peer_down_notification.rsuse crate::parser::bmp::error::ParserBmpError;
use crate::parser::ReadUtils;
use bytes::{Buf, Bytes};
use num_enum::{IntoPrimitive, TryFromPrimitive};
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PeerDownNotification {
pub reason: PeerDownReason,
pub data: Option<Vec<u8>>,
}
#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum PeerDownReason {
Reserved = 0,
LocalSystemClosedNotificationPduFollows = 1,
LocalSystemClosedFsmEvenFollows = 2,
RemoteSystemClosedNotificationPduFollows = 3,
RemoteSystemsClosedNoData,
PeerDeConfigured = 5,
LocalSystemClosedTlvDataFollows = 6,
}
pub fn parse_peer_down_notification(
data: &mut Bytes,
) -> Result<PeerDownNotification, ParserBmpError> {
let reason = PeerDownReason::try_from(data.read_u8()?)?;
let bytes_left = data.remaining();
let data: Option<Vec<u8>> = match reason {
PeerDownReason::Reserved => match bytes_left {
0 => None,
_ => Some(data.read_n_bytes(bytes_left)?),
},
PeerDownReason::LocalSystemClosedNotificationPduFollows => {
Some(data.read_n_bytes(bytes_left)?)
}
PeerDownReason::LocalSystemClosedFsmEvenFollows => {
Some(data.read_n_bytes(bytes_left)?)
}
PeerDownReason::RemoteSystemClosedNotificationPduFollows => {
Some(data.read_n_bytes(bytes_left)?)
}
PeerDownReason::RemoteSystemsClosedNoData => {
None
}
PeerDownReason::PeerDeConfigured => {
None
}
PeerDownReason::LocalSystemClosedTlvDataFollows => {
Some(data.read_n_bytes(bytes_left)?)
}
};
Ok(PeerDownNotification { reason, data })
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BufMut;
#[test]
fn test_parse_peer_down_notification() {
let mut data = bytes::BytesMut::new();
data.put_u8(1);
data.put_slice(&[0u8; 10]);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::LocalSystemClosedNotificationPduFollows
);
assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
let mut data = bytes::BytesMut::new();
data.put_u8(2);
data.put_slice(&[0u8; 10]);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::LocalSystemClosedFsmEvenFollows
);
assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
let mut data = bytes::BytesMut::new();
data.put_u8(3);
data.put_slice(&[0u8; 10]);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::RemoteSystemClosedNotificationPduFollows
);
assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
let mut data = bytes::BytesMut::new();
data.put_u8(4);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::RemoteSystemsClosedNoData
);
assert!(peer_down_notification.data.is_none());
let mut data = bytes::BytesMut::new();
data.put_u8(5);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::PeerDeConfigured
);
assert!(peer_down_notification.data.is_none());
let mut data = bytes::BytesMut::new();
data.put_u8(6);
data.put_slice(&[0u8; 10]);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_ok());
let peer_down_notification = result.unwrap();
assert_eq!(
peer_down_notification.reason,
PeerDownReason::LocalSystemClosedTlvDataFollows
);
assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
let mut data = bytes::BytesMut::new();
data.put_u8(7);
let mut data = data.freeze();
let result = parse_peer_down_notification(&mut data);
assert!(result.is_err());
}
}