use crate::core::PacketNumber;
use super::TimeoutEvent;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RetransmitDecision {
Retransmit {
packet_number: PacketNumber,
},
Wait {
packet_number: PacketNumber,
},
Drop {
packet_number: PacketNumber,
},
}
pub trait RetransmitPolicy {
fn on_timeout(&mut self, event: TimeoutEvent) -> RetransmitDecision;
fn should_retransmit(&self, packet_number: PacketNumber) -> bool;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RetryLimitPolicy {
pub max_attempts: u8,
}
impl RetryLimitPolicy {
#[must_use]
pub const fn new(max_attempts: u8) -> Self {
Self { max_attempts }
}
}
impl RetransmitPolicy for RetryLimitPolicy {
fn on_timeout(&mut self, event: TimeoutEvent) -> RetransmitDecision {
if event.attempts < self.max_attempts {
RetransmitDecision::Retransmit {
packet_number: event.packet_number,
}
} else {
RetransmitDecision::Drop {
packet_number: event.packet_number,
}
}
}
fn should_retransmit(&self, _packet_number: PacketNumber) -> bool {
self.max_attempts > 0
}
}
#[cfg(test)]
mod tests {
use crate::core::PacketNumber;
use super::{RetransmitDecision, RetransmitPolicy, RetryLimitPolicy, TimeoutEvent};
#[test]
fn retry_limit_policy_drops_after_limit() {
let packet_number = PacketNumber::new(3);
let mut policy = RetryLimitPolicy::new(2);
assert_eq!(
policy.on_timeout(TimeoutEvent::new(packet_number, 10, 1)),
RetransmitDecision::Retransmit { packet_number }
);
assert_eq!(
policy.on_timeout(TimeoutEvent::new(packet_number, 20, 2)),
RetransmitDecision::Drop { packet_number }
);
}
}