peerman 0.2.0

DN42 peer manager with WireGuard, BIRD, and cluster support
use std::collections::HashMap;
use std::sync::{LazyLock, Mutex};
use std::time::Instant;

pub struct LoginRateLimiter {
    attempts: Mutex<HashMap<String, (u32, Instant)>>,
}

impl LoginRateLimiter {
    fn new() -> Self {
        Self {
            attempts: Mutex::new(HashMap::new()),
        }
    }

    pub fn check(&self, ip: &str) -> Result<(), u64> {
        let mut attempts = self.attempts.lock().unwrap();
        let now = Instant::now();
        let entry = attempts.entry(ip.to_string()).or_insert((0, now));

        if now.duration_since(entry.1).as_secs() >= 60 {
            *entry = (0, now);
        }

        entry.0 += 1;
        if entry.0 > 5 {
            let elapsed = now.duration_since(entry.1).as_secs();
            let retry_after = 60_u64.saturating_sub(elapsed);
            Err(retry_after)
        } else {
            Ok(())
        }
    }
}

pub static LOGIN_RATE_LIMITER: LazyLock<LoginRateLimiter> = LazyLock::new(LoginRateLimiter::new);