From bbde9f7960514b8bdcb9fd79a7554c7860bd6aa4 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sun, 31 Aug 2025 15:37:50 +0100 Subject: Switch messageflood to using a per-user flood reset time. --- src/modules/m_messageflood.cpp | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp index 2ad6fee05..993076f0d 100644 --- a/src/modules/m_messageflood.cpp +++ b/src/modules/m_messageflood.cpp @@ -38,11 +38,22 @@ enum class MsgFloodAction KICK_BAN, }; +struct MsgFloodData final +{ + time_t reset; + double messages = 0; + + MsgFloodData(unsigned long period) + : reset(ServerInstance->Time() + period) + { + } +}; + class MsgFloodSettings final { private: - insp::flat_map counters; - time_t reset; + using CounterMap = insp::flat_map; + CounterMap counters; public: MsgFloodAction action; @@ -51,8 +62,7 @@ public: MsgFloodSettings(MsgFloodAction a, unsigned int m, unsigned long p) - : reset(ServerInstance->Time() + p) - , action(a) + : action(a) , messages(m) , period(p) { @@ -60,19 +70,29 @@ public: bool Add(User* who, double weight) { - if (ServerInstance->Time() > reset) - { - counters.clear(); - reset = ServerInstance->Time() + period; - } + auto it = Find(who); + if (it == counters.end()) + it = counters.emplace(who, MsgFloodData(period)).first; - counters[who] += weight; - return (counters[who] >= this->messages); + it->second.messages += weight; + return (it->second.messages >= this->messages); } - void Clear(User* who) + CounterMap::iterator Find(User* who) { - counters.erase(who); + CounterMap::iterator ret = counters.end(); + for (auto it = counters.begin(); it != counters.end(); ) + { + if (it->second.reset <= ServerInstance->Time()) + it = counters.erase(it); + else + { + if (it->first == who) + ret = it; + it++; + } + } + return ret; } }; @@ -311,13 +331,11 @@ public: case MsgFloodAction::KICK: dest->KickUser(ServerInstance->FakeClient, user, msg); - f->Clear(user); break; case MsgFloodAction::KICK_BAN: CreateBan(dest, user, false); dest->KickUser(ServerInstance->FakeClient, user, msg); - f->Clear(user); break; case MsgFloodAction::MUTE: -- cgit v1.3.1-10-gc9f91