From 6a1d27d149b39eff7f93dd51bd5c6d51848d992d Mon Sep 17 00:00:00 2001 From: psychon Date: Mon, 15 Nov 2010 21:06:18 +0000 Subject: [PATCH] Overhaul channel join handling Instead of sending a single JOIN line for each channel, znc now tries to stuff all of the channel that it has decided to join into a single JOIN command. Apparently this helps with some IRCds which decide when to flood someone off based on the number of lines received, not based on the number of bytes. Let's hope for the best... git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2182 726aef4b-f618-498e-8847-2d620e286838 --- User.cpp | 38 +++++++++++++++++++++++++++++++++++--- User.h | 1 + 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/User.cpp b/User.cpp index 061e4b80..53315c07 100644 --- a/User.cpp +++ b/User.cpp @@ -770,10 +770,42 @@ void CUser::JoinChans() { } } - for (set::iterator it = sChans.begin(); - it != sChans.end(); ++it) { - PutIRC("JOIN " + (*it)->GetName() + " " + (*it)->GetKey()); + while (!sChans.empty()) + JoinChans(sChans); +} + +void CUser::JoinChans(set& sChans) { + CString sKeys, sJoin; + bool bHaveKey = false; + size_t uiJoinLength = strlen("JOIN "); + + while (!sChans.empty()) { + set::iterator it = sChans.begin(); + const CString& sName = (*it)->GetName(); + const CString& sKey = (*it)->GetKey(); + size_t len = sName.length() + sKey.length(); + len += 2; // two comma + + if (!sKeys.empty() && uiJoinLength + len >= 512) + break; + + if (!sJoin.empty()) { + sJoin += ","; + sKeys += ","; + } + uiJoinLength += len; + sJoin += sName; + if (!sKey.empty()) { + sKeys += sKey; + bHaveKey = true; + } + sChans.erase(it); } + + if (bHaveKey) + PutIRC("JOIN " + sJoin + " " + sKeys); + else + PutIRC("JOIN " + sJoin); } bool CUser::JoinChan(CChan* pChan) { diff --git a/User.h b/User.h index c18e847a..1a0cc33e 100644 --- a/User.h +++ b/User.h @@ -224,6 +224,7 @@ public: // !Getters private: bool JoinChan(CChan* pChan); + void JoinChans(set& sChans); protected: CString m_sUserName;