use crate::seed::SeedRng;
pub struct ReKeyScheduler {
_rng: SeedRng,
min_interval: u64,
max_interval: u64,
next_rekey_at: u64,
}
impl ReKeyScheduler {
pub fn new(rng: SeedRng, min_interval: u64, max_interval: u64) -> Self {
let (min_interval, max_interval) = if min_interval <= max_interval {
(min_interval, max_interval)
} else {
(max_interval, min_interval)
};
let mut s = Self {
_rng: rng,
min_interval,
max_interval,
next_rekey_at: 0,
};
s.schedule_next();
s
}
#[must_use]
pub fn next_rekey_at(&self) -> u64 {
self.next_rekey_at
}
pub fn should_rekey(&self, packet_count: u64) -> bool {
packet_count >= self.next_rekey_at
}
pub fn schedule_next(&mut self) {
let hi = self
.max_interval
.saturating_add(1)
.max(self.min_interval.saturating_add(1));
let span = self._rng.range(self.min_interval, hi);
self.next_rekey_at = self.next_rekey_at.saturating_add(span);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rekey_threshold_moves_forward() {
let mut s = ReKeyScheduler::new(SeedRng::new([7u8; 32]), 10, 20);
let t = s.next_rekey_at;
s.schedule_next();
assert!(s.next_rekey_at > t);
}
#[test]
fn swapped_min_max_normalized() {
let s = ReKeyScheduler::new(SeedRng::new([1u8; 32]), 100, 50);
assert!(s.min_interval <= s.max_interval);
}
}