use crate::protocol::heartbeat::{build_ping, is_pong};
use crate::protocol::message::Message;
use crate::utils::timeout::KEEPALIVE_INTERVAL;
use std::time::{Duration, Instant};
use tracing::{debug, instrument, warn};
#[derive(Debug)]
pub struct KeepAliveManager {
last_send: Instant,
last_recv: Instant,
pub ping_interval: Duration,
dead_timeout: Duration,
}
impl KeepAliveManager {
pub fn new() -> Self {
Self {
last_send: Instant::now(),
last_recv: Instant::now(),
ping_interval: KEEPALIVE_INTERVAL,
dead_timeout: KEEPALIVE_INTERVAL.mul_f32(4.0), }
}
pub fn with_settings(ping_interval: Duration, dead_timeout: Duration) -> Self {
Self {
last_send: Instant::now(),
last_recv: Instant::now(),
ping_interval,
dead_timeout,
}
}
pub fn update_send(&mut self) {
self.last_send = Instant::now();
}
pub fn update_recv(&mut self) {
self.last_recv = Instant::now();
}
pub fn should_ping(&self) -> bool {
self.last_send.elapsed() >= self.ping_interval
}
pub fn ping_interval(&self) -> Duration {
self.ping_interval
}
pub fn is_connection_dead(&self) -> bool {
self.last_recv.elapsed() >= self.dead_timeout
}
pub fn time_since_last_recv(&self) -> Duration {
self.last_recv.elapsed()
}
#[instrument]
pub fn build_ping_message() -> Message {
debug!("Building ping message for keep-alive");
build_ping()
}
#[instrument(skip(msg))]
pub fn process_message(&mut self, msg: &Message) -> bool {
let is_pong_msg = is_pong(msg);
self.update_recv();
if is_pong_msg {
debug!("Received pong message");
}
is_pong_msg
}
}
impl Default for KeepAliveManager {
fn default() -> Self {
Self::new()
}
}