use std::{collections::HashMap, net::IpAddr, sync::Arc};
use tokio::{
sync::{Mutex, mpsc},
time::{Duration, Instant, sleep},
};
pub(crate) const PERMISSION_LIFETIME: Duration = Duration::from_secs(5 * 60);
#[derive(Debug)]
pub(crate) struct Permission {
ip: IpAddr,
reset_tx: mpsc::Sender<Duration>,
}
impl Permission {
pub(crate) fn new(
ip: IpAddr,
permissions: Arc<Mutex<HashMap<IpAddr, Self>>>,
lifetime: Duration,
) -> Self {
let (reset_tx, mut reset_rx) = mpsc::channel(1);
drop(tokio::spawn(async move {
let timer = sleep(lifetime);
tokio::pin!(timer);
loop {
tokio::select! {
() = &mut timer => {
drop(permissions.lock().await.remove(&ip));
break;
},
result = reset_rx.recv() => {
if let Some(d) = result {
timer.as_mut().reset(Instant::now() + d);
} else {
break;
}
},
}
}
}));
Self { ip, reset_tx }
}
pub(crate) const fn ip(&self) -> IpAddr {
self.ip
}
pub(crate) async fn refresh(&self, lifetime: Duration) {
_ = self.reset_tx.send(lifetime).await;
}
}