use core::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KeepalivePolicy {
pub interval: Duration,
pub timeout: Option<Duration>,
pub max_missed: u32,
}
impl Default for KeepalivePolicy {
fn default() -> Self {
Self {
interval: Duration::from_secs(60),
timeout: None,
max_missed: 2,
}
}
}
impl KeepalivePolicy {
pub fn every(interval: Duration) -> Self {
Self {
interval,
..Self::default()
}
}
pub(crate) fn misses_allowed(&self) -> u32 {
self.max_missed.max(1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum KeepaliveBehavior {
Enabled(KeepalivePolicy),
#[default]
Disabled,
}
impl KeepaliveBehavior {
pub(crate) fn initial_interval(&self) -> Option<Duration> {
match self {
KeepaliveBehavior::Enabled(policy) if !policy.interval.is_zero() => {
Some(policy.interval)
}
_ => None,
}
}
pub(crate) fn policy(&self) -> KeepalivePolicy {
match self {
KeepaliveBehavior::Enabled(policy) => *policy,
KeepaliveBehavior::Disabled => KeepalivePolicy::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zero_interval_reads_as_disabled() {
let behavior = KeepaliveBehavior::Enabled(KeepalivePolicy::every(Duration::ZERO));
assert_eq!(behavior.initial_interval(), None);
}
#[test]
fn disabled_still_carries_a_policy_for_later_enabling() {
assert_eq!(
KeepaliveBehavior::Disabled.policy(),
KeepalivePolicy::default()
);
assert_eq!(KeepaliveBehavior::Disabled.initial_interval(), None);
}
#[test]
fn zero_misses_allowed_normalizes_to_one() {
let policy = KeepalivePolicy {
max_missed: 0,
..KeepalivePolicy::default()
};
assert_eq!(policy.misses_allowed(), 1);
}
#[test]
fn default_tolerates_one_miss_before_redialling() {
assert_eq!(KeepalivePolicy::default().misses_allowed(), 2);
assert_eq!(KeepalivePolicy::default().interval, Duration::from_secs(60));
}
}