diff --git a/src/modules/account_registration.rs b/src/modules/account_registration.rs index fbfafee..701d260 100644 --- a/src/modules/account_registration.rs +++ b/src/modules/account_registration.rs @@ -23,6 +23,7 @@ use std::collections::HashMap; use crate::command::{CmdResult, Command}; use crate::http::{json_str, urlencode}; +use crate::module::Module; use crate::server::{now, Server}; use crate::Uid; @@ -30,6 +31,26 @@ use crate::Uid; #[derive(Default)] struct RateState(HashMap>); +/// Ticks the rate-limit table: prunes each IP's timestamps to the window and drops +/// IPs with none left, so the map can't accumulate one entry per distinct IP that +/// ever issued a REGISTER over the process lifetime. +pub struct AcctRegGc; +impl Module for AcctRegGc { + fn name(&self) -> &'static str { + "account_registration" + } + fn on_tick(&mut self, s: &mut Server) { + let window = s.conf_num("acctregister_ratetime", 3600u64); + let n = now(); + if let Some(st) = s.ext.get_mut::() { + st.0.retain(|_, hist| { + hist.retain(|&t| n.saturating_sub(t) < window); + !hist.is_empty() + }); + } + } +} + fn enabled(s: &Server) -> bool { s.conf_bool("account_registration", false) && s.conf("acctregister_registerurl").is_some() } diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 148b796..8f8dbe9 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -112,6 +112,7 @@ pub fn default_modules() -> Vec> { Box::new(operprefix::OperPrefix), Box::new(permchannels::PermChannels::default()), Box::new(chathistory::ChatHistoryGc), + Box::new(account_registration::AcctRegGc), ] }