Skip to main content

tower_defense/auth/
timestamp.rs

1use std::{
2    collections::HashMap,
3    sync::{Arc, Mutex},
4    time::{Duration, UNIX_EPOCH},
5};
6
7use crate::{crypto::PeerId, error::Error};
8
9pub trait VerifyTimestamp {
10    fn verify(&self, peer: &PeerId, timestamp: u64) -> bool;
11}
12
13#[derive(Debug, Clone)]
14pub struct WithinDuration(pub Duration);
15
16impl VerifyTimestamp for WithinDuration {
17    fn verify(&self, _peer: &PeerId, timestamp: u64) -> bool {
18        let Ok(now) = now() else {
19            // now is not valid, we cant compare
20            return false;
21        };
22
23        Duration::from_millis(now.abs_diff(timestamp)) < self.0
24    }
25}
26
27#[derive(Debug, Clone)]
28pub struct LaterThanLast {
29    log: Arc<Mutex<HashMap<PeerId, u64>>>,
30}
31
32impl Default for LaterThanLast {
33    fn default() -> Self {
34        Self {
35            log: Arc::new(Mutex::new(HashMap::new())),
36        }
37    }
38}
39
40impl VerifyTimestamp for LaterThanLast {
41    fn verify(&self, peer: &PeerId, timestamp: u64) -> bool {
42        let Ok(mut log) = self.log.lock() else {
43            return false;
44        };
45
46        let Some(last) = log.get(peer) else {
47            log.insert(peer.clone(), timestamp);
48            return true;
49        };
50
51        if *last >= timestamp {
52            return false;
53        }
54
55        log.insert(peer.clone(), timestamp);
56
57        true
58    }
59}
60
61/// Number of milliseconds from the unix epoch
62pub(crate) fn now() -> Result<u64, Error> {
63    let millis = std::time::SystemTime::now()
64        .duration_since(UNIX_EPOCH)?
65        .as_millis();
66
67    Ok(u64::try_from(millis)?)
68}