pub use super::packet::PacketState;
use super::{
packet::{PacketMetaData, PacketMetaDataError, StateMutator, MULTICAST_RESERVED_IDENTIFIER},
AddressType,
};
pub struct PacketRouter {
current_device_identifier: AddressType,
}
pub enum RouteResult {
Received(PacketMetaData),
Transit(PacketMetaData),
ReceivedAndTransit {
received: PacketMetaData,
transit: PacketMetaData,
},
}
pub struct PacketLifetimeEnded;
impl PacketRouter {
pub fn new(current_device_identifier: AddressType) -> Self {
Self {
current_device_identifier,
}
}
fn handle_multicast(
&self,
packet_meta_data: PacketMetaData,
) -> Result<RouteResult, PacketLifetimeEnded> {
let received = packet_meta_data.clone();
let transit: Option<PacketMetaData> = match packet_meta_data.deacrease_lifetime() {
Ok(packet_meta_data) => Some(packet_meta_data),
Err(PacketMetaDataError::PacketLifetimeEnded) => None,
};
if let Some(transit) = transit {
return Ok(RouteResult::ReceivedAndTransit { received, transit });
}
return Ok(RouteResult::Received(received));
}
fn keep_copy_and_prepare_transit(
&self,
packet_meta_data: PacketMetaData,
) -> Result<RouteResult, PacketLifetimeEnded> {
let received = packet_meta_data.clone();
let transit = packet_meta_data.mutated();
Ok(RouteResult::ReceivedAndTransit { received, transit })
}
pub fn route(
&self,
packet_meta_data: PacketMetaData,
) -> Result<RouteResult, PacketLifetimeEnded> {
if packet_meta_data.is_destination_identifier_reached(self.current_device_identifier) {
match packet_meta_data.spec_state {
PacketState::Normal => Ok(RouteResult::Received(packet_meta_data)), PacketState::Ping => self.keep_copy_and_prepare_transit(packet_meta_data),
PacketState::Pong => Ok(RouteResult::Received(packet_meta_data)),
PacketState::SendTransaction => {
Ok(RouteResult::Transit(packet_meta_data.mutated()))
}
PacketState::AcceptTransaction => {
Ok(RouteResult::Transit(packet_meta_data.mutated()))
}
PacketState::InitTransaction => {
self.keep_copy_and_prepare_transit(packet_meta_data)
}
PacketState::FinishTransaction => Ok(RouteResult::Received(packet_meta_data)),
}
} else if packet_meta_data.is_destination_identifier_reached(MULTICAST_RESERVED_IDENTIFIER)
{
self.handle_multicast(packet_meta_data)
} else {
let packet_decreased_lifettime = match packet_meta_data.deacrease_lifetime() {
Ok(packet_decreased_lifettime) => packet_decreased_lifettime,
Err(PacketMetaDataError::PacketLifetimeEnded) => return Err(PacketLifetimeEnded), };
Ok(RouteResult::Transit(packet_decreased_lifettime))
}
}
}