mirror of
https://github.com/znc/znc.git
synced 2026-07-02 07:51:26 +02:00
Rearrange CAP requests between ZNC and server in a way
that each next REQ is sent only after receiving ACK/NAK of previous REQ. Also now you can call CIRCSock::PauseCap() and CIRCSock::ResumeCap() if you need to pause CAP negotiation and process of logging in for a while. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2137 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
+25
-10
@@ -24,6 +24,7 @@ CIRCSock::CIRCSock(CUser* pUser) : CZNCSock() {
|
||||
m_Nick.SetHost(pUser->GetBindHost());
|
||||
|
||||
m_uMaxNickLen = 9;
|
||||
m_uCapPaused = 0;
|
||||
m_sPerms = "*!@%+";
|
||||
m_sPermModes = "qaohv";
|
||||
m_mueChanModes['b'] = ListArg;
|
||||
@@ -679,15 +680,11 @@ void CIRCSock::ReadLine(const CString& sData) {
|
||||
|
||||
for (it = vsTokens.begin(); it != vsTokens.end(); ++it) {
|
||||
if (OnServerCapAvailable(*it) || *it == "multi-prefix" || *it == "userhost-in-names") {
|
||||
// For real support of ack (~) modifier need also
|
||||
// to queue these cap requests.
|
||||
PutIRC("CAP REQ :" + *it);
|
||||
m_ssPendingCaps.insert(*it);
|
||||
}
|
||||
}
|
||||
} else if (sSubCmd == "ACK") {
|
||||
sArgs.Trim();
|
||||
m_ssPendingCaps.erase(sArgs);
|
||||
MODULECALL(OnServerCapResult(sArgs, true), m_pUser, NULL, );
|
||||
if ("multi-prefix" == sArgs) {
|
||||
m_bNamesx = true;
|
||||
@@ -699,14 +696,10 @@ void CIRCSock::ReadLine(const CString& sData) {
|
||||
// This should work because there's no [known]
|
||||
// capability with length of name more than 100 characters.
|
||||
sArgs.Trim();
|
||||
m_ssPendingCaps.erase(sArgs);
|
||||
MODULECALL(OnServerCapResult(sArgs, false), m_pUser, NULL, );
|
||||
}
|
||||
|
||||
if (m_ssPendingCaps.empty()) {
|
||||
// We already got all needed ACK/NAK replies.
|
||||
PutIRC("CAP END");
|
||||
}
|
||||
|
||||
SendNextCap();
|
||||
}
|
||||
// Don't forward any CAP stuff to the client
|
||||
return;
|
||||
@@ -716,6 +709,28 @@ void CIRCSock::ReadLine(const CString& sData) {
|
||||
m_pUser->PutUser(sLine);
|
||||
}
|
||||
|
||||
void CIRCSock::SendNextCap() {
|
||||
if (!m_uCapPaused) {
|
||||
if (m_ssPendingCaps.empty()) {
|
||||
// We already got all needed ACK/NAK replies.
|
||||
PutIRC("CAP END");
|
||||
} else {
|
||||
CString sCap = *m_ssPendingCaps.begin();
|
||||
m_ssPendingCaps.erase(m_ssPendingCaps.begin());
|
||||
PutIRC("CAP REQ :" + sCap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CIRCSock::PauseCap() {
|
||||
++m_uCapPaused;
|
||||
}
|
||||
|
||||
void CIRCSock::ResumeCap() {
|
||||
--m_uCapPaused;
|
||||
SendNextCap();
|
||||
}
|
||||
|
||||
bool CIRCSock::OnServerCapAvailable(const CString& sCap) {
|
||||
MODULECALL(OnServerCapAvailable(sCap), m_pUser, NULL, return true);
|
||||
return false;
|
||||
|
||||
@@ -55,6 +55,16 @@ public:
|
||||
void ResetChans();
|
||||
void Quit(const CString& sQuitMsg = "");
|
||||
|
||||
/** You can call this from CModule::OnServerCapResult to suspend
|
||||
* sending other CAP requests and CAP END for a while. Each
|
||||
* call to PauseCap should be balanced with a call to ResumeCap.
|
||||
*/
|
||||
void PauseCap();
|
||||
/** If you used PauseCap, call this when CAP negotiation and logging in
|
||||
* should be resumed again.
|
||||
*/
|
||||
void ResumeCap();
|
||||
|
||||
// Setters
|
||||
void SetPass(const CString& s) { m_sPass = s; }
|
||||
// !Setters
|
||||
@@ -88,6 +98,7 @@ private:
|
||||
void ParseISupport(const CString& sLine);
|
||||
// This is called when we connect and the nick we want is already taken
|
||||
void SendAltNick(const CString& sBadNick);
|
||||
void SendNextCap();
|
||||
protected:
|
||||
bool m_bISpoofReleased;
|
||||
bool m_bAuthed;
|
||||
@@ -102,6 +113,7 @@ protected:
|
||||
CString m_sPass;
|
||||
map<CString, CChan*> m_msChans;
|
||||
unsigned int m_uMaxNickLen;
|
||||
unsigned int m_uCapPaused;
|
||||
SCString m_ssAcceptedCaps;
|
||||
SCString m_ssPendingCaps;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user