Code cleanup

Since now there are no server-dependent caps defined in the core
This commit is contained in:
Alexey Sokolov
2024-01-13 23:45:30 +00:00
parent f7ff0ee3f3
commit b1009bd809
9 changed files with 66 additions and 198 deletions
+6 -27
View File
@@ -227,23 +227,7 @@ class CClient : public CIRCSocket {
/** Notifies client about one specific cap which server has just notified us about.
*/
void NotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue,
const std::function<void(CClient*, bool)>& handler);
/** Notifies client if the cap is server-dependent, otherwise noop.
*/
void PotentiallyNotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue);
/** Notifies client that all these caps are now available.
*
* This function will internally filter only those which are server-dependent.
* This is when new client connects to an already connected server, and
* when server has just connected and finished negotiating caps.
*/
void NotifyServerDependentCaps(const SCString& ssCaps);
/** Notifies client that all server-dependent caps are not available anymore.
*
* Called when server disconnects.
*/
void ClearServerDependentCaps();
void NotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue);
void ReadLine(const CString& sData) override;
bool SendMotd();
@@ -323,16 +307,11 @@ class CClient : public CIRCSocket {
std::shared_ptr<CAuthBase> m_spAuth;
SCString m_ssAcceptedCaps;
SCString m_ssSupportedTags;
// 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.
static const std::map<CString, std::pair<bool, std::function<void(CClient*, bool bVal)>>>&
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
// =values in NEW.
SCString m_ssServerDependentCaps;
// The capabilities supported by the ZNC core - capability names mapped to
// change handler. Note: this lists caps which don't require support on IRC
// server.
static const std::map<CString, std::function<void(CClient*, bool bVal)>>&
CoreCaps();
friend class ClientTest;
friend class CCoreCaps;
+1 -2
View File
@@ -156,8 +156,7 @@ class CIRCNetwork : private CCoreTranslationMixin {
void IRCConnected();
void IRCDisconnected();
void CheckIRCConnect();
void PotentiallyNotifyServerDependentCap(const CString& sCap, bool bValue);
void NotifyClientsAboutServerDependentCap(const CString& sCap, bool bValue, const std::function<void(CClient*, bool)>& handler);
void NotifyClientsAboutServerDependentCap(const CString& sCap, bool bValue);
bool IsServerCapAccepted(const CString& sCap) const;
bool PutIRC(const CString& sLine);
+2 -2
View File
@@ -1312,7 +1312,7 @@ class CModule {
virtual void OnClientDetached();
#ifndef SWIG
void AddCapability(const CString& sName, std::unique_ptr<CCapability> pCap);
void AddServerDependentCapability(const CString& sName, std::unique_ptr<CCapability> pCap);
#endif
/** Called when a client told us CAP LS. Use ssCaps.insert("cap-name")
@@ -1410,7 +1410,7 @@ class CModule {
CString m_sArgs;
CString m_sModPath;
CTranslationDomainRefHolder m_Translation;
std::map<CString, std::unique_ptr<CCapability>> m_mCaps;
std::map<CString, std::unique_ptr<CCapability>> m_mServerDependentCaps;
private:
MCString
+7 -4
View File
@@ -22,6 +22,9 @@
#include <memory>
class CCoreCaps : public CModule {
// Note: for historical reasons CClient and CIRCSock have such fields, but
// really they should not.
// TODO: move these fields and their handling from core to this module.
class AwayNotify : public CCapability {
void OnServerChangedSupport(CIRCNetwork* pNetwork,
bool bState) override {
@@ -65,10 +68,10 @@ class CCoreCaps : public CModule {
public:
MODCONSTRUCTOR(CCoreCaps) {
AddCapability("away-notify", std::make_unique<AwayNotify>());
AddCapability("account-notify", std::make_unique<AccountNotify>());
AddCapability("account-tag", std::make_unique<AccountTag>());
AddCapability("extended-join", std::make_unique<ExtendedJoin>());
AddServerDependentCapability("away-notify", std::make_unique<AwayNotify>());
AddServerDependentCapability("account-notify", std::make_unique<AccountNotify>());
AddServerDependentCapability("account-tag", std::make_unique<AccountTag>());
AddServerDependentCapability("extended-join", std::make_unique<ExtendedJoin>());
}
};
+18 -104
View File
@@ -272,7 +272,6 @@ void CClient::SetNetwork(CIRCNetwork* pNetwork, bool bDisconnect,
if (bDisconnect) {
NETWORKMODULECALL(OnClientDetached(), m_pUser, m_pNetwork, this, NOTHING);
ClearServerDependentCaps();
// Tell the client they are no longer in these channels.
const vector<CChan*>& vChans = m_pNetwork->GetChans();
for (const CChan* pChan : vChans) {
@@ -743,34 +742,35 @@ static VCString MultiLine(const SCString& ssCaps) {
return vsRes;
}
const std::map<CString, std::pair<bool, std::function<void(CClient*, bool bVal)>>>&
const std::map<CString, std::function<void(CClient*, bool bVal)>>&
CClient::CoreCaps() {
static const std::map<CString, std::pair<bool, std::function<void(CClient*, bool bVal)>>> mCoreCaps = []{
std::map<CString, std::pair<bool, std::function<void(CClient*, bool bVal)>>> mCoreCaps = {
static const std::map<CString, std::function<void(CClient*, bool bVal)>> mCoreCaps = []{
std::map<CString, std::function<void(CClient*, bool bVal)>> mCoreCaps = {
{"multi-prefix",
{false, [](CClient* pClient, bool bVal) { pClient->m_bNamesx = bVal; }}},
[](CClient* pClient, bool bVal) { pClient->m_bNamesx = bVal; }},
{"userhost-in-names",
{false, [](CClient* pClient, bool bVal) { pClient->m_bUHNames = bVal; }}},
[](CClient* pClient, bool bVal) { pClient->m_bUHNames = bVal; }},
{"echo-message",
{false, [](CClient* pClient, bool bVal) { pClient->m_bEchoMessage = bVal; }}},
[](CClient* pClient, bool bVal) { pClient->m_bEchoMessage = bVal; }},
{"server-time",
{false, [](CClient* pClient, bool bVal) {
[](CClient* pClient, bool bVal) {
pClient->m_bServerTime = bVal;
pClient->SetTagSupport("time", bVal);
}}},
{"batch", {false, [](CClient* pClient, bool bVal) {
}},
{"batch", [](CClient* pClient, bool bVal) {
pClient->m_bBatch = bVal;
pClient->SetTagSupport("batch", bVal);
}}},
}},
{"cap-notify",
{false, [](CClient* pClient, bool bVal) { pClient->m_bCapNotify = bVal; }}},
[](CClient* pClient, bool bVal) { pClient->m_bCapNotify = 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; }};
mCoreCaps["znc.in/self-message"] = [](CClient* pClient, bool bVal) {
pClient->m_bSelfMessage = bVal;
};
return mCoreCaps;
}();
@@ -784,10 +784,7 @@ void CClient::HandleCap(const CMessage& Message) {
m_uCapVersion = std::max(m_uCapVersion, Message.GetParam(1).ToUShort());
SCString ssOfferCaps;
for (const auto& it : CoreCaps()) {
bool bServerDependent = std::get<0>(it.second);
if (!bServerDependent ||
m_ssServerDependentCaps.count(it.first) > 0)
ssOfferCaps.insert(it.first);
ssOfferCaps.insert(it.first);
}
NETWORKMODULECALL(OnClientCapLs(this, ssOfferCaps), GetUser(), GetNetwork(), this, NOTHING);
VCString vsCaps = MultiLine(ssOfferCaps);
@@ -823,9 +820,7 @@ void CClient::HandleCap(const CMessage& Message) {
bool bAccepted = false;
auto it = CoreCaps().find(sCap);
if (CoreCaps().end() != it) {
bool bServerDependent = std::get<0>(it->second);
bAccepted = !bServerDependent ||
m_ssServerDependentCaps.count(sCap) > 0;
bAccepted = true;
}
NETWORKMODULECALL(IsClientCapSupported(this, sCap, bVal), GetUser(), GetNetwork(), this,
&bAccepted);
@@ -845,7 +840,7 @@ void CClient::HandleCap(const CMessage& Message) {
auto handler_it = CoreCaps().find(sCap);
if (CoreCaps().end() != handler_it) {
const auto& handler = std::get<1>(handler_it->second);
const auto& handler = handler_it->second;
handler(this, bVal);
}
NETWORKMODULECALL(OnClientCapRequest(this, sCap, bVal), GetUser(), GetNetwork(), this, NOTHING);
@@ -927,8 +922,7 @@ void CClient::SetTagSupport(const CString& sTag, bool bState) {
}
}
void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue,
const std::function<void(CClient*, bool)>& handler) {
void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue) {
if (bValue) {
if (HasCapNotify()) {
if (HasCap302() && !sValue.empty()) {
@@ -941,90 +935,10 @@ void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue, const C
if (HasCapNotify()) {
PutClient(":irc.znc.in CAP " + GetNick() + " DEL :" + sCap);
}
handler(this, false);
m_ssAcceptedCaps.erase(sCap);
}
}
void CClient::PotentiallyNotifyServerDependentCap(const CString& sCap, bool bValue, const CString& sValue) {
auto it = CoreCaps().find(sCap);
if (CoreCaps().end() != it) {
const auto& [bServerDependent, handler] = it->second;
if (bServerDependent) {
NotifyServerDependentCap(sCap, bValue, sValue, handler);
}
}
if (!bValue) {
m_ssServerDependentCaps.erase(sCap);
}
return;
if (bValue) {
if (CoreCaps().end() != it) {
bool bServerDependent = std::get<0>(it->second);
if (bServerDependent) {
if (m_ssServerDependentCaps.count(sCap) == 0) {
m_ssServerDependentCaps.insert(sCap);
if (HasCapNotify()) {
PutClient(":irc.znc.in CAP " + GetNick() + " NEW :" + sCap);
}
}
}
}
} else {
if (HasCapNotify() && m_ssServerDependentCaps.count(sCap) > 0) {
PutClient(":irc.znc.in CAP " + GetNick() + " DEL :" + sCap);
}
if (CoreCaps().end() != it) {
bool bServerDependent = std::get<0>(it->second);
const auto& handler = std::get<1>(it->second);
if (bServerDependent) {
handler(this, false);
}
}
m_ssServerDependentCaps.erase(sCap);
}
}
void CClient::NotifyServerDependentCaps(const SCString& ssCaps) {
for (const CString& sCap : ssCaps) {
auto it = CoreCaps().find(sCap);
if (CoreCaps().end() != it) {
bool bServerDependent = std::get<0>(it->second);
if (bServerDependent) {
m_ssServerDependentCaps.insert(sCap);
}
}
}
if (HasCapNotify() && !m_ssServerDependentCaps.empty()) {
VCString vsCaps = MultiLine(m_ssServerDependentCaps);
for (const CString& sLine : vsCaps) {
PutClient(":irc.znc.in CAP " + GetNick() + " NEW :" + sLine);
}
}
}
void CClient::ClearServerDependentCaps() {
if (HasCapNotify() && !m_ssServerDependentCaps.empty()) {
VCString vsCaps = MultiLine(m_ssServerDependentCaps);
for (const CString& sLine : vsCaps) {
PutClient(":irc.znc.in CAP " + GetNick() + " DEL :" + sLine);
}
for (const CString& sCap : m_ssServerDependentCaps) {
auto it = CoreCaps().find(sCap);
if (CoreCaps().end() != it) {
const auto& handler = std::get<1>(it->second);
handler(this, false);
}
m_ssAcceptedCaps.erase(sCap);
}
}
m_ssServerDependentCaps.clear();
}
template <typename T>
void CClient::AddBuffer(const T& Message) {
if (!m_pNetwork) {
+2 -20
View File
@@ -660,10 +660,6 @@ void CIRCNetwork::ClientConnected(CClient* pClient) {
size_t uIdx, uSize;
if (m_pIRCSock) {
pClient->NotifyServerDependentCaps(m_pIRCSock->GetAcceptedCaps());
}
pClient->SetPlaybackActive(true);
if (m_RawBuffer.IsEmpty()) {
@@ -1393,10 +1389,6 @@ bool CIRCNetwork::IsIRCConnected() const {
void CIRCNetwork::SetIRCSocket(CIRCSock* pIRCSock) { m_pIRCSock = pIRCSock; }
void CIRCNetwork::IRCConnected() {
const SCString& ssCaps = m_pIRCSock->GetAcceptedCaps();
for (CClient* pClient : m_vClients) {
pClient->NotifyServerDependentCaps(ssCaps);
}
if (m_uJoinDelay > 0) {
m_pJoinTimer->Delay(m_uJoinDelay);
} else {
@@ -1405,9 +1397,6 @@ void CIRCNetwork::IRCConnected() {
}
void CIRCNetwork::IRCDisconnected() {
for (CClient* pClient : m_vClients) {
pClient->ClearServerDependentCaps();
}
m_pIRCSock = nullptr;
SetIRCServer("");
@@ -1417,17 +1406,10 @@ void CIRCNetwork::IRCDisconnected() {
CheckIRCConnect();
}
void CIRCNetwork::PotentiallyNotifyServerDependentCap(const CString& sCap, bool bValue) {
void CIRCNetwork::NotifyClientsAboutServerDependentCap(const CString& sCap, bool bValue) {
CString sValue = GetIRCSock() ? GetIRCSock()->GetCapLsValue(sCap) : "";
for (CClient* pClient : m_vClients) {
pClient->PotentiallyNotifyServerDependentCap(sCap, bValue, sValue);
}
}
void CIRCNetwork::NotifyClientsAboutServerDependentCap(const CString& sCap, bool bValue, const std::function<void(CClient*, bool)>& handler) {
CString sValue = GetIRCSock() ? GetIRCSock()->GetCapLsValue(sCap) : "";
for (CClient* pClient : m_vClients) {
pClient->NotifyServerDependentCap(sCap, bValue, sValue, handler);
pClient->NotifyServerDependentCap(sCap, bValue, sValue);
}
}
-6
View File
@@ -393,9 +393,6 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) {
}
m_ssAcceptedCaps.erase(sCap);
m_ssPendingCaps.erase(sCap);
if (m_bAuthed) {
m_pNetwork->PotentiallyNotifyServerDependentCap(sCap, false);
}
};
if (sSubCmd == "LS" || sSubCmd == "NEW") {
@@ -424,9 +421,6 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) {
it->second(true);
}
m_ssAcceptedCaps.insert(sArgs);
if (m_bAuthed) {
m_pNetwork->PotentiallyNotifyServerDependentCap(sArgs, true);
}
} else if (sSubCmd == "NAK") {
// This should work because there's no [known]
// capability with length of name more than 100 characters.
+29 -32
View File
@@ -161,19 +161,19 @@ CModule::CModule(ModHandle pDLL, CUser* pUser, CIRCNetwork* pNetwork,
}
CModule::~CModule() {
for (const auto& [sName, pCap] : m_mCaps) {
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
switch (GetType()) {
case CModInfo::NetworkModule:
GetNetwork()->NotifyClientsAboutServerDependentCap(
sName, false, [&](CClient* pClient, bool bState) {});
GetNetwork()->NotifyClientsAboutServerDependentCap(sName,
false);
for (CClient* pClient : GetNetwork()->GetClients()) {
pCap->OnClientChangedSupport(pClient, false);
}
break;
case CModInfo::UserModule:
for (CIRCNetwork* pNetwork : GetUser()->GetNetworks()) {
pNetwork->NotifyClientsAboutServerDependentCap(
sName, false, [&](CClient* pClient, bool bState) {});
pNetwork->NotifyClientsAboutServerDependentCap(sName,
false);
for (CClient* pClient : pNetwork->GetClients()) {
pCap->OnClientChangedSupport(pClient, false);
}
@@ -182,8 +182,8 @@ CModule::~CModule() {
case CModInfo::GlobalModule:
for (auto& [_, pUser] : CZNC::Get().GetUserMap()) {
for (CIRCNetwork* pNetwork : pUser->GetNetworks()) {
pNetwork->NotifyClientsAboutServerDependentCap(
sName, false, [&](CClient* pClient, bool bState) {});
pNetwork->NotifyClientsAboutServerDependentCap(sName,
false);
for (CClient* pClient : pNetwork->GetClients()) {
pCap->OnClientChangedSupport(pClient, false);
}
@@ -638,18 +638,17 @@ bool CModule::OnBoot() { return true; }
void CModule::OnPreRehash() {}
void CModule::OnPostRehash() {}
void CModule::OnIRCDisconnected() {
for (const auto& [sName, pCap] : m_mCaps) {
GetNetwork()->NotifyClientsAboutServerDependentCap(
sName, false, [&](CClient* pClient, bool bState) {});
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
GetNetwork()->NotifyClientsAboutServerDependentCap(sName, false);
for (CClient* pClient : GetNetwork()->GetClients()) {
pCap->OnClientChangedSupport(pClient, false);
}
}
}
void CModule::OnIRCConnected() {
for (const auto& [sName, pCap] : m_mCaps) {
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
if (GetNetwork()->IsServerCapAccepted(sName)) {
GetNetwork()->NotifyClientsAboutServerDependentCap(sName, true, [](CClient* pClient, bool bState){});
GetNetwork()->NotifyClientsAboutServerDependentCap(sName, true);
}
}
}
@@ -1045,16 +1044,15 @@ CModule::EModRet CModule::OnSendToIRCMessage(CMessage& Message) {
}
void CModule::OnClientAttached() {
if (!GetNetwork()) return;
for (const auto& [sName, pCap] : m_mCaps) {
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
if (GetNetwork()->IsServerCapAccepted(sName)) {
GetClient()->NotifyServerDependentCap(sName, true, GetNetwork()->GetIRCSock()->GetCapLsValue(sName), nullptr);
GetClient()->NotifyServerDependentCap(sName, true, GetNetwork()->GetIRCSock()->GetCapLsValue(sName));
}
}
}
void CModule::OnClientDetached() {
for (const auto& [sName, pCap] : m_mCaps) {
GetClient()->NotifyServerDependentCap(sName, false, "",
[](CClient*, bool) {});
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
GetClient()->NotifyServerDependentCap(sName, false, "");
pCap->OnClientChangedSupport(GetClient(), false);
}
}
@@ -1062,23 +1060,22 @@ void CModule::OnClientDetached() {
bool CModule::OnServerCapAvailable(const CString& sCap) { return false; }
bool CModule::OnServerCap302Available(const CString& sCap,
const CString& sValue) {
auto it = m_mCaps.find(sCap);
if (it == m_mCaps.end()) return OnServerCapAvailable(sCap);
auto it = m_mServerDependentCaps.find(sCap);
if (it == m_mServerDependentCaps.end()) return OnServerCapAvailable(sCap);
if (GetNetwork()->IsServerCapAccepted(sCap)) {
// This can happen when server sent CAP NEW with another value.
GetNetwork()->NotifyClientsAboutServerDependentCap(sCap, true, nullptr);
GetNetwork()->NotifyClientsAboutServerDependentCap(sCap, true);
// It's enabled already, no need to REQ it again.
return false;
}
return true;
}
void CModule::OnServerCapResult(const CString& sCap, bool bSuccess) {
auto it = m_mCaps.find(sCap);
if (it == m_mCaps.end()) return;
auto it = m_mServerDependentCaps.find(sCap);
if (it == m_mServerDependentCaps.end()) return;
it->second->OnServerChangedSupport(GetNetwork(), bSuccess);
if (GetNetwork()->GetIRCSock()->IsAuthed()) {
GetNetwork()->NotifyClientsAboutServerDependentCap(
sCap, bSuccess, [&](CClient* pClient, bool bState) {});
GetNetwork()->NotifyClientsAboutServerDependentCap(sCap, bSuccess);
if (!bSuccess) {
for (CClient* pClient : GetNetwork()->GetClients()) {
it->second->OnClientChangedSupport(pClient, false);
@@ -1155,7 +1152,7 @@ CModule::EModRet CModule::OnUnknownUserRawMessage(CMessage& Message) {
return CONTINUE;
}
void CModule::OnClientCapLs(CClient* pClient, SCString& ssCaps) {
for (const auto& [sName, pCap] : m_mCaps) {
for (const auto& [sName, pCap] : m_mServerDependentCaps) {
if (GetNetwork() && GetNetwork()->IsServerCapAccepted(sName)) {
if (pClient->HasCap302()) {
CString sValue =
@@ -1173,15 +1170,15 @@ void CModule::OnClientCapLs(CClient* pClient, SCString& ssCaps) {
}
bool CModule::IsClientCapSupported(CClient* pClient, const CString& sCap,
bool bState) {
auto it = m_mCaps.find(sCap);
if (it == m_mCaps.end()) return false;
auto it = m_mServerDependentCaps.find(sCap);
if (it == m_mServerDependentCaps.end()) return false;
if (!bState) return true;
return GetNetwork() && GetNetwork()->IsServerCapAccepted(sCap);
}
void CModule::OnClientCapRequest(CClient* pClient, const CString& sCap,
bool bState) {
auto it = m_mCaps.find(sCap);
if (it == m_mCaps.end()) return;
auto it = m_mServerDependentCaps.find(sCap);
if (it == m_mServerDependentCaps.end()) return;
it->second->OnClientChangedSupport(pClient, bState);
}
CModule::EModRet CModule::OnModuleLoading(const CString& sModName,
@@ -1201,10 +1198,10 @@ CModule::EModRet CModule::OnGetModInfo(CModInfo& ModInfo,
}
void CModule::OnGetAvailableMods(set<CModInfo>& ssMods,
CModInfo::EModuleType eType) {}
void CModule::AddCapability(const CString& sName,
std::unique_ptr<CCapability> pCap) {
void CModule::AddServerDependentCapability(const CString& sName,
std::unique_ptr<CCapability> pCap) {
pCap->SetModule(this);
m_mCaps[sName] = std::move(pCap);
m_mServerDependentCaps[sName] = std::move(pCap);
}
CModules::CModules()
+1 -1
View File
@@ -553,7 +553,7 @@ TEST_F(ZNCTest, ServerDependentCapInModule) {
};
public:
MODCONSTRUCTOR(TestModule) {
AddCapability("testcap", std::make_unique<TestCap>());
AddServerDependentCapability("testcap", std::make_unique<TestCap>());
}
};
MODULEDEFS(TestModule, "Test")