From 50a3226b4f3a7f77cdb0220d673859e76f8f5468 Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Sat, 4 Mar 2023 10:01:26 +0000 Subject: [PATCH] Don't duplicate the map of cap handlers per client The idea here was that modules would dynamically add handlers to the map, then it needs to be per client; but a simpler way to achieve this will be in next commit --- include/znc/Client.h | 4 +- src/Client.cpp | 113 +++++++++++++++++++++++-------------------- 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/include/znc/Client.h b/include/znc/Client.h index 7afdcea3..a7b543c0 100644 --- a/include/znc/Client.h +++ b/include/znc/Client.h @@ -310,8 +310,8 @@ class CClient : public CIRCSocket { // The capabilities supported by the ZNC core - capability names mapped // to a pair which contains a bool describing whether the capability is // server-dependent, and a capability value change handler. - std::map>> - m_mCoreCaps; + static const std::map>>& + CoreCaps(); // A subset of CIRCSock::GetAcceptedCaps(), the caps that can be listed // in CAP LS and may be notified to the client with CAP NEW (cap-notify). // TODO: come up with a way for modules to work with this, and with diff --git a/src/Client.cpp b/src/Client.cpp index 1ba93631..a188dd11 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -103,47 +103,11 @@ CClient::CClient() : CIRCSocket(), m_sIdentifier(""), m_spAuth(), m_ssAcceptedCaps(), - m_ssSupportedTags(), - m_mCoreCaps({ - {"multi-prefix", - {false, [this](bool bVal) { m_bNamesx = bVal; }}}, - {"userhost-in-names", - {false, [this](bool bVal) { m_bUHNames = bVal; }}}, - {"echo-message", - {false, [this](bool bVal) { m_bEchoMessage = bVal; }}}, - {"server-time", - {false, [this](bool bVal) { - m_bServerTime = bVal; - SetTagSupport("time", bVal); - }}}, - {"batch", {false, [this](bool bVal) { - m_bBatch = bVal; - SetTagSupport("batch", bVal); - }}}, - {"cap-notify", - {false, [this](bool bVal) { m_bCapNotify = bVal; }}}, - {"away-notify", - {true, [this](bool bVal) { m_bAwayNotify = bVal; }}}, - {"account-notify", - {true, [this](bool bVal) { m_bAccountNotify = bVal; }}}, - {"account-tag", - {true, [this](bool bVal) { - m_bAccountTag = bVal; - SetTagSupport("account", bVal); - }}}, - {"extended-join", - {true, [this](bool bVal) { m_bExtendedJoin = bVal; }}}, - }) { + m_ssSupportedTags() { EnableReadLine(); // RFC says a line can have 512 chars max, but we are // a little more gentle ;) SetMaxBufferThreshold(1024); - - // For compatibility with older clients - m_mCoreCaps["znc.in/server-time-iso"] = m_mCoreCaps["server-time"]; - m_mCoreCaps["znc.in/batch"] = m_mCoreCaps["batch"]; - m_mCoreCaps["znc.in/self-message"] = { - false, [this](bool bVal) { m_bSelfMessage = bVal; }}; } CClient::~CClient() { @@ -773,13 +737,58 @@ static VCString MultiLine(const SCString& ssCaps) { return vsRes; } +const std::map>>& +CClient::CoreCaps() { + static const std::map>> mCoreCaps = []{ + std::map>> mCoreCaps = { + {"multi-prefix", + {false, [](CClient* pClient, bool bVal) { pClient->m_bNamesx = bVal; }}}, + {"userhost-in-names", + {false, [](CClient* pClient, bool bVal) { pClient->m_bUHNames = bVal; }}}, + {"echo-message", + {false, [](CClient* pClient, bool bVal) { pClient->m_bEchoMessage = bVal; }}}, + {"server-time", + {false, [](CClient* pClient, bool bVal) { + pClient->m_bServerTime = bVal; + pClient->SetTagSupport("time", bVal); + }}}, + {"batch", {false, [](CClient* pClient, bool bVal) { + pClient->m_bBatch = bVal; + pClient->SetTagSupport("batch", bVal); + }}}, + {"cap-notify", + {false, [](CClient* pClient, bool bVal) { pClient->m_bCapNotify = bVal; }}}, + {"away-notify", + {true, [](CClient* pClient, bool bVal) { pClient->m_bAwayNotify = bVal; }}}, + {"account-notify", + {true, [](CClient* pClient, bool bVal) { pClient->m_bAccountNotify = bVal; }}}, + {"account-tag", + {true, [](CClient* pClient, bool bVal) { + pClient->m_bAccountTag = bVal; + pClient->SetTagSupport("account", bVal); + }}}, + {"extended-join", + {true, [](CClient* pClient, bool bVal) { pClient->m_bExtendedJoin = bVal; }}}, + }; + + // For compatibility with older clients + mCoreCaps["znc.in/server-time-iso"] = mCoreCaps["server-time"]; + mCoreCaps["znc.in/batch"] = mCoreCaps["batch"]; + mCoreCaps["znc.in/self-message"] = { + false, [](CClient* pClient, bool bVal) { pClient->m_bSelfMessage = bVal; }}; + + return mCoreCaps; + }(); + return mCoreCaps; +} + void CClient::HandleCap(const CMessage& Message) { CString sSubCmd = Message.GetParam(0); if (sSubCmd.Equals("LS")) { m_uCapVersion = Message.GetParam(1).ToInt(); SCString ssOfferCaps; - for (const auto& it : m_mCoreCaps) { + for (const auto& it : CoreCaps()) { bool bServerDependent = std::get<0>(it.second); if (!bServerDependent || m_ssServerDependentCaps.count(it.first) > 0) @@ -817,8 +826,8 @@ void CClient::HandleCap(const CMessage& Message) { if (sCap.TrimPrefix("-")) bVal = false; bool bAccepted = false; - const auto& it = m_mCoreCaps.find(sCap); - if (m_mCoreCaps.end() != it) { + const auto& it = CoreCaps().find(sCap); + if (CoreCaps().end() != it) { bool bServerDependent = std::get<0>(it->second); bAccepted = !bServerDependent || m_ssServerDependentCaps.count(sCap) > 0; @@ -839,10 +848,10 @@ void CClient::HandleCap(const CMessage& Message) { CString sCap = sToken; if (sCap.TrimPrefix("-")) bVal = false; - auto handler_it = m_mCoreCaps.find(sCap); - if (m_mCoreCaps.end() != handler_it) { + auto handler_it = CoreCaps().find(sCap); + if (CoreCaps().end() != handler_it) { const auto& handler = std::get<1>(handler_it->second); - handler(bVal); + handler(this, bVal); } GLOBALMODULECALL(OnClientCapRequest(this, sCap, bVal), NOTHING); @@ -924,9 +933,9 @@ void CClient::SetTagSupport(const CString& sTag, bool bState) { } void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue) { - auto it = m_mCoreCaps.find(sCap); + auto it = CoreCaps().find(sCap); if (bValue) { - if (m_mCoreCaps.end() != it) { + if (CoreCaps().end() != it) { bool bServerDependent = std::get<0>(it->second); if (bServerDependent) { if (m_ssServerDependentCaps.count(sCap) == 0) { @@ -941,11 +950,11 @@ void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue) { if (HasCapNotify() && m_ssServerDependentCaps.count(sCap) > 0) { PutClient(":irc.znc.in CAP " + GetNick() + " DEL :" + sCap); } - if (m_mCoreCaps.end() != it) { + if (CoreCaps().end() != it) { bool bServerDependent = std::get<0>(it->second); const auto& handler = std::get<1>(it->second); if (bServerDependent) { - handler(false); + handler(this, false); } } m_ssServerDependentCaps.erase(sCap); @@ -954,8 +963,8 @@ void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue) { void CClient::NotifyServerDependentCaps(const SCString& ssCaps) { for (const CString& sCap : ssCaps) { - auto it = m_mCoreCaps.find(sCap); - if (m_mCoreCaps.end() != it) { + auto it = CoreCaps().find(sCap); + if (CoreCaps().end() != it) { bool bServerDependent = std::get<0>(it->second); if (bServerDependent) { m_ssServerDependentCaps.insert(sCap); @@ -979,10 +988,10 @@ void CClient::ClearServerDependentCaps() { } for (const CString& sCap : m_ssServerDependentCaps) { - auto it = m_mCoreCaps.find(sCap); - if (m_mCoreCaps.end() != it) { + auto it = CoreCaps().find(sCap); + if (CoreCaps().end() != it) { const auto& handler = std::get<1>(it->second); - handler(false); + handler(this, false); } m_ssAcceptedCaps.erase(sCap); }