mod constants;
mod packet;
mod receiver;
mod router;
mod timer;
mod transmitter;
mod types;
pub use packet::{
ExactAddressType, GeneralAddressType, IdType, LifeTimeType, Packet, PacketDataBytes,
};
pub use router::PacketState;
use types::PacketQueue;
pub use types::{ms, NodeString};
use self::router::{RouteError, RouteResult, Router};
pub struct Node {
transmitter: transmitter::Transmitter,
receiver: receiver::Receiver,
my_address: ExactAddressType,
timer: timer::Timer,
received_packet_queue: PacketQueue,
router: Router,
}
pub struct NodeUpdateError {
pub is_receive_queue_full: bool,
pub is_transit_queue_full: bool,
}
pub enum SendError {
SendingQueueIsFull,
}
impl core::fmt::Debug for SendError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
SendError::SendingQueueIsFull => write!(f, "SendingQueueIsFull"),
}
}
}
pub enum SpecialSendError {
Timeout,
SendingQueueIsFull,
}
impl core::fmt::Debug for SpecialSendError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
SpecialSendError::Timeout => write!(f, "Timeout"),
SpecialSendError::SendingQueueIsFull => write!(f, "SendingQueueIsFull"),
}
}
}
impl From<SendError> for SpecialSendError {
fn from(value: SendError) -> Self {
match value {
SendError::SendingQueueIsFull => SpecialSendError::SendingQueueIsFull,
}
}
}
pub struct NodeConfig {
pub device_address: ExactAddressType,
pub listen_period: ms,
}
impl Node {
pub fn new(config: NodeConfig) -> Node {
Node {
transmitter: transmitter::Transmitter::new(),
receiver: receiver::Receiver::new(),
my_address: config.device_address.clone(),
timer: timer::Timer::new(config.listen_period),
received_packet_queue: PacketQueue::new(),
router: Router::new(config.device_address.into()),
}
}
pub fn send_ping_pong<I, M>(
&mut self,
data: PacketDataBytes,
destination_device_identifier: ExactAddressType,
lifetime: LifeTimeType,
timeout: ms,
millis_provider: M,
interface_driver: &mut I,
) -> Result<(), SpecialSendError>
where
I: embedded_io::ReadReady + embedded_io::Read + embedded_io::Write,
M: Fn() -> ms,
{
self._special_send(
data,
destination_device_identifier,
PacketState::Ping,
PacketState::Pong,
lifetime,
timeout,
millis_provider,
interface_driver,
)
}
pub fn send_with_transaction<I, M>(
&mut self,
data: PacketDataBytes,
destination_device_identifier: ExactAddressType,
lifetime: LifeTimeType,
timeout: ms,
millis_provider: M,
interface_driver: &mut I,
) -> Result<(), SpecialSendError>
where
I: embedded_io::ReadReady + embedded_io::Read + embedded_io::Write,
M: Fn() -> ms,
{
self._special_send(
data,
destination_device_identifier,
PacketState::SendTransaction,
PacketState::FinishTransaction,
lifetime,
timeout,
millis_provider,
interface_driver,
)
}
fn _special_send<I, M>(
&mut self,
data: PacketDataBytes,
destination_device_identifier: ExactAddressType,
request_state: PacketState,
expected_response_state: PacketState,
lifetime: LifeTimeType,
timeout: ms,
millis_provider: M,
interface_driver: &mut I,
) -> Result<(), SpecialSendError>
where
I: embedded_io::ReadReady + embedded_io::Read + embedded_io::Write,
M: Fn() -> ms,
{
let mut current_time = millis_provider();
let start_time = current_time;
while let Some(_) = self.receive() {}
let expected_response_packet_id = match self._send(Packet::new(
self.my_address.into(),
destination_device_identifier.into(),
0,
lifetime,
request_state.clone(),
true,
data,
)) {
Err(any_err) => return Err(any_err.into()),
Ok(expected_response_packet_id) => match request_state {
PacketState::SendTransaction => expected_response_packet_id + 1,
PacketState::Ping => expected_response_packet_id,
_ => expected_response_packet_id,
},
};
while current_time.wrapping_sub(start_time) < timeout {
let _ = self.update(interface_driver, current_time);
if let Some(answer) = self.receive() {
if !(answer.source_device_identifier == destination_device_identifier.into()) {
continue;
}
if !(answer.get_spec_state() == expected_response_state) {
continue;
}
if !(answer.get_id() == expected_response_packet_id) {
continue;
}
return Ok(());
}
current_time = millis_provider();
}
Err(SpecialSendError::Timeout)
}
pub fn send_to_exact(
&mut self,
data: PacketDataBytes,
destination_device_identifier: ExactAddressType,
lifetime: LifeTimeType,
filter_out_duplication: bool,
) -> Result<(), SendError> {
match self._send(Packet::new(
self.my_address.into(),
destination_device_identifier.into(),
0, lifetime,
PacketState::Normal,
filter_out_duplication,
data,
)) {
Ok(_) => Ok(()),
Err(err) => Err(err),
}
}
pub fn broadcast(
&mut self,
data: PacketDataBytes,
lifetime: LifeTimeType,
) -> Result<(), SendError> {
match self._send(Packet::new(
self.my_address.into(),
GeneralAddressType::Broadcast.into(),
0,
lifetime,
PacketState::Normal,
true,
data,
)) {
Ok(_) => Ok(()),
Err(err) => Err(err),
}
}
fn _send(&mut self, packet: Packet) -> Result<IdType, SendError> {
match self.transmitter.send(packet) {
Ok(generated_packet_id) => Ok(generated_packet_id),
Err(transmitter::PacketQueueIsFull) => Err(SendError::SendingQueueIsFull),
}
}
pub fn receive(&mut self) -> Option<Packet> {
self.received_packet_queue.pop_front()
}
pub fn update<I>(
&mut self,
interface_driver: &mut I,
current_time: ms,
) -> Result<(), NodeUpdateError>
where
I: embedded_io::ReadReady + embedded_io::Read + embedded_io::Write,
{
if self.timer.is_time_to_speak(current_time) {
self.transmitter.update(interface_driver);
self.timer.record_speak_time(current_time);
}
self.receiver.update(current_time, interface_driver);
let packet_to_route = match self.receiver.receive(current_time) {
Some(packet_to_handle) => packet_to_handle,
None => return Ok(()),
};
let (received_packet, transit_packet) = match self.router.route(packet_to_route) {
Ok(ok_case) => match ok_case {
RouteResult::ReceivedOnly(packet) => (Some(packet), None),
RouteResult::TransitOnly(transit) => (None, Some(transit)),
RouteResult::ReceivedAndTransit { received, transit } => {
(Some(received), Some(transit))
}
},
Err(RouteError::PacketLifetimeEnded) => (None, None),
Err(RouteError::RespondToBroadcastAddressError) => (None, None),
};
let (mut is_receive_queue_full, mut is_transit_queue_full): (bool, bool) = (false, false);
if let Some(received_packet) = received_packet {
match self.received_packet_queue.push_back(received_packet) {
Ok(()) => (),
Err(_) => {
is_receive_queue_full = true;
}
}
}
if let Some(transit_packet) = transit_packet {
match self.transmitter.send_transit(transit_packet) {
Ok(_) => (),
Err(transmitter::PacketTransitQueueIsFull) => {
is_transit_queue_full = true;
}
}
}
if is_receive_queue_full || is_transit_queue_full {
return Err(NodeUpdateError {
is_receive_queue_full,
is_transit_queue_full,
});
} else {
Ok(())
}
}
}