use std::{
fmt::{self, Debug, Formatter},
net::SocketAddr,
time::{Duration, Instant},
};
use crate::common::Id;
pub const STALE_TIME: Duration = Duration::from_secs(15 * 60);
const MIN_PING_BACKOFF_INTERVAL: Duration = Duration::from_secs(10);
pub const TOKEN_ROTATE_INTERVAL: Duration = Duration::from_secs(60 * 5);
#[derive(Clone, PartialEq)]
pub struct Node {
pub id: Id,
pub address: SocketAddr,
pub token: Option<Vec<u8>>,
last_seen: Instant,
}
impl Debug for Node {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Node")
.field("id", &self.id)
.field("address", &self.address)
.field("last_seen", &self.last_seen.elapsed().as_secs())
.finish()
}
}
impl Node {
pub fn new(id: Id, address: SocketAddr) -> Node {
Node {
id,
address,
token: None,
last_seen: Instant::now(),
}
}
#[cfg(test)]
pub fn random() -> Node {
Node {
id: Id::random(),
address: SocketAddr::from(([0, 0, 0, 0], 0)),
token: None,
last_seen: Instant::now(),
}
}
pub fn with_id(mut self, id: Id) -> Self {
self.id = id;
self
}
pub fn with_address(mut self, address: SocketAddr) -> Self {
self.address = address;
self
}
pub fn with_token(mut self, token: Vec<u8>) -> Self {
self.token = Some(token);
self
}
pub fn is_stale(&self) -> bool {
self.last_seen.elapsed() > STALE_TIME
}
pub fn valid_token(&self) -> bool {
self.last_seen.elapsed() <= TOKEN_ROTATE_INTERVAL
}
pub(crate) fn should_ping(&self) -> bool {
self.last_seen.elapsed() > MIN_PING_BACKOFF_INTERVAL
}
pub fn same_adress(&self, other: &Self) -> bool {
self.address == other.address
}
pub(crate) fn is_secure(&self) -> bool {
self.id.is_valid_for_ip(&self.address.ip())
}
}