Documentation
use pea_core::*;
use std::collections::HashMap;
use std::net::IpAddr;
pub enum Endpoint {
    Block,
    Transaction,
    Stake,
    Multiaddr,
    SyncRequest,
    SyncResponse,
}
#[derive(Debug, Default)]
pub struct Ratelimit {
    map: HashMap<IpAddr, ([usize; 6], Option<u32>)>,
}
impl Ratelimit {
    pub fn get(&self, addr: &IpAddr) -> ([usize; 6], Option<u32>) {
        *self.map.get(addr).unwrap_or(&([0; 6], None))
    }
    pub fn is_ratelimited(&self, b: &Option<u32>) -> bool {
        if let Some(timestamp) = b {
            if timestamp + RATELIMIT_DURATION > pea_util::timestamp() {
                return true;
            }
        }
        false
    }
    pub fn add(&mut self, addr: IpAddr, endpoint: Endpoint) -> bool {
        let mut value = self.get(&addr);
        let a = &mut value.0;
        let b = &mut value.1;
        if self.is_ratelimited(b) {
            return true;
        }
        let ratelimited = match endpoint {
            Endpoint::Block => {
                a[0] += 1;
                a[0] > RATELIMIT_BLOCK
            }
            Endpoint::Transaction => {
                a[1] += 1;
                a[1] > RATELIMIT_TRANSACTION
            }
            Endpoint::Stake => {
                a[2] += 1;
                a[2] > RATELIMIT_STAKE
            }
            Endpoint::Multiaddr => {
                a[3] += 1;
                a[3] > RATELIMIT_MULTIADDR
            }
            Endpoint::SyncRequest => {
                a[4] += 1;
                a[4] > RATELIMIT_SYNC_REQUEST
            }
            Endpoint::SyncResponse => {
                a[5] += 1;
                a[5] > RATELIMIT_SYNC_RESPONSE
            }
        };
        if ratelimited {
            *b = Some(pea_util::timestamp());
        }
        self.map.insert(addr, value);
        ratelimited
    }
    pub fn reset(&mut self) {
        for value in self.map.values_mut() {
            let a = &mut value.0;
            a[0] = a[0].saturating_sub(RATELIMIT_BLOCK);
            a[1] = a[1].saturating_sub(RATELIMIT_TRANSACTION);
            a[2] = a[2].saturating_sub(RATELIMIT_STAKE);
            a[3] = a[3].saturating_sub(RATELIMIT_MULTIADDR);
            a[4] = a[4].saturating_sub(RATELIMIT_SYNC_REQUEST);
            a[5] = a[5].saturating_sub(RATELIMIT_SYNC_RESPONSE);
        }
    }
}