mirror of
https://github.com/mii443/miibgpd.git
synced 2025-08-22 15:55:26 +00:00
add OpenMessage
This commit is contained in:
@ -1,8 +1,13 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use bytes::BytesMut;
|
||||
|
||||
use crate::error::ConvertBytesToBgpMessageError;
|
||||
use crate::{bgp_type::AutonomousSystemNumber, error::ConvertBytesToBgpMessageError};
|
||||
|
||||
use super::open::OpenMessage;
|
||||
use super::{
|
||||
header::{Header, MessageType},
|
||||
open::OpenMessage,
|
||||
};
|
||||
|
||||
pub enum Message {
|
||||
Open(OpenMessage),
|
||||
@ -11,13 +16,38 @@ pub enum Message {
|
||||
impl TryFrom<BytesMut> for Message {
|
||||
type Error = ConvertBytesToBgpMessageError;
|
||||
|
||||
fn try_from(value: BytesMut) -> Result<Self, Self::Error> {
|
||||
todo!();
|
||||
fn try_from(bytes: BytesMut) -> Result<Self, Self::Error> {
|
||||
let header_bytes_length = 19;
|
||||
|
||||
if bytes.len() < header_bytes_length {
|
||||
return Err(ConvertBytesToBgpMessageError::from(anyhow::anyhow!(
|
||||
"Message length is too short: {}",
|
||||
bytes.len()
|
||||
)));
|
||||
}
|
||||
|
||||
let header = Header::try_from(BytesMut::from(&bytes[0..header_bytes_length]))?;
|
||||
|
||||
match header.type_ {
|
||||
MessageType::Open => {
|
||||
let open_message = OpenMessage::try_from(bytes)?;
|
||||
Ok(Self::Open(open_message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Message> for BytesMut {
|
||||
fn from(value: Message) -> Self {
|
||||
todo!();
|
||||
fn from(message: Message) -> Self {
|
||||
match message {
|
||||
Message::Open(open) => open.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new_open(my_as_number: AutonomousSystemNumber, my_ip_addr: Ipv4Addr) -> Self {
|
||||
let open_message = OpenMessage::new(my_as_number, my_ip_addr);
|
||||
Self::Open(open_message)
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,105 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use anyhow::Context;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
||||
use crate::{
|
||||
bgp_type::{AutonomousSystemNumber, HoldTime, Version},
|
||||
error::ConvertBytesToBgpMessageError,
|
||||
};
|
||||
|
||||
use super::header::{Header, MessageType};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
|
||||
pub struct OpenMessage;
|
||||
pub struct OpenMessage {
|
||||
header: Header,
|
||||
version: Version,
|
||||
my_as_number: AutonomousSystemNumber,
|
||||
hold_time: HoldTime,
|
||||
bgp_identifier: Ipv4Addr,
|
||||
optional_parameters_length: u8,
|
||||
optional_parameters: BytesMut,
|
||||
}
|
||||
|
||||
impl OpenMessage {
|
||||
pub fn new(my_as_number: AutonomousSystemNumber, my_ip_addr: Ipv4Addr) -> Self {
|
||||
let header = Header::new(29, MessageType::Open);
|
||||
Self {
|
||||
header,
|
||||
version: Version::new(),
|
||||
my_as_number,
|
||||
hold_time: HoldTime::new(),
|
||||
bgp_identifier: my_ip_addr,
|
||||
optional_parameters_length: 0,
|
||||
optional_parameters: BytesMut::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<BytesMut> for OpenMessage {
|
||||
type Error = ConvertBytesToBgpMessageError;
|
||||
|
||||
fn try_from(bytes: BytesMut) -> Result<Self, Self::Error> {
|
||||
let header = Header::try_from(BytesMut::from(&bytes[0..19]))?;
|
||||
let version: Version = bytes[19].try_into()?;
|
||||
|
||||
let my_as_number = AutonomousSystemNumber::from(u16::from_be_bytes(
|
||||
bytes[20..22]
|
||||
.try_into()
|
||||
.context(format!("cannot parse AS number: {:?}", &bytes[20..22]))?,
|
||||
));
|
||||
|
||||
let hold_time = HoldTime::from(u16::from_be_bytes(
|
||||
bytes[22..24]
|
||||
.try_into()
|
||||
.context(format!("cannot parse HoldTime: {:?}", &bytes[22..24]))?,
|
||||
));
|
||||
|
||||
let bgp_identifier: [u8; 4] = bytes[24..28]
|
||||
.try_into()
|
||||
.context(format!("cannot parse BGP Identifier: {:?}", &bytes[24..28]))?;
|
||||
let bgp_identifier = Ipv4Addr::from(bgp_identifier);
|
||||
let optional_parameters_length = bytes[28];
|
||||
let optional_parameters = BytesMut::from(&bytes[29..]);
|
||||
|
||||
Ok(Self {
|
||||
header,
|
||||
version,
|
||||
my_as_number,
|
||||
hold_time,
|
||||
bgp_identifier,
|
||||
optional_parameters_length,
|
||||
optional_parameters,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpenMessage> for BytesMut {
|
||||
fn from(message: OpenMessage) -> BytesMut {
|
||||
let mut bytes = BytesMut::new();
|
||||
let header_bytes: &BytesMut = &message.header.into();
|
||||
bytes.put(&header_bytes[..]);
|
||||
bytes.put_u8(message.version.into());
|
||||
bytes.put_u16(message.my_as_number.into());
|
||||
bytes.put_u16(message.hold_time.into());
|
||||
bytes.put(&message.bgp_identifier.octets()[..]);
|
||||
bytes.put_u8(message.optional_parameters_length);
|
||||
bytes.put(&message.optional_parameters[..]);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn convert_bytes_to_open_message_and_open_message_to_bytes() {
|
||||
let open_message = OpenMessage::new(64512.into(), "127.0.0.1".parse().unwrap());
|
||||
let open_message_bytes: BytesMut = open_message.clone().into();
|
||||
let open_message2: OpenMessage = open_message_bytes.try_into().unwrap();
|
||||
|
||||
assert_eq!(open_message, open_message2);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user