diff --git a/include/znc/IRCNetwork.h b/include/znc/IRCNetwork.h index 6af760ec..289451ec 100644 --- a/include/znc/IRCNetwork.h +++ b/include/znc/IRCNetwork.h @@ -32,6 +32,8 @@ class CConfig; class CChan; class CServer; class CIRCSock; +class CIRCNetworkPingTimer; +class CIRCNetworkJoinTimer; class CIRCNetwork { public: @@ -41,6 +43,10 @@ public: CIRCNetwork(CUser *pUser, const CIRCNetwork& Network); ~CIRCNetwork(); + enum { + PING_TIMEOUT = 270 + }; + void Clone(const CIRCNetwork& Network, bool bCloneName = true); CString GetNetworkPath(); @@ -196,6 +202,9 @@ protected: CBuffer m_RawBuffer; CBuffer m_MotdBuffer; CBuffer m_QueryBuffer; + + CIRCNetworkPingTimer* m_pPingTimer; + CIRCNetworkJoinTimer* m_pJoinTimer; }; #endif // !_IRCNETWORK_H diff --git a/modules/q.cpp b/modules/q.cpp index 9b6a6acf..a4e70956 100644 --- a/modules/q.cpp +++ b/modules/q.cpp @@ -257,6 +257,11 @@ public: if (sLine.Token(1) == "396" && sLine.Token(3).find("users.quakenet.org") != CString::npos) { m_bCloaked = true; PutModule("Cloak successful: Your hostname is now cloaked."); + + // Join channels immediately after our spoof is set. + if (m_bJoinAfterCloaked) { + m_pNetwork->JoinChans(); + } } return CONTINUE; } diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index fc1bc60d..00c5787a 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -25,6 +25,59 @@ using std::vector; using std::set; +class CIRCNetworkPingTimer : public CCron { +public: + CIRCNetworkPingTimer(CIRCNetwork *pNetwork) : CCron() { + m_pNetwork = pNetwork; + SetName("CIRCNetworkPingTimer::" + m_pNetwork->GetUser()->GetUserName() + "::" + m_pNetwork->GetName()); + Start(30); + } + + virtual ~CIRCNetworkPingTimer() {} + +protected: + virtual void RunJob() { + CIRCSock* pIRCSock = m_pNetwork->GetIRCSock(); + + if (pIRCSock && pIRCSock->GetTimeSinceLastDataTransaction() >= CIRCNetwork::PING_TIMEOUT) { + pIRCSock->PutIRC("PING :ZNC"); + } + + vector& vClients = m_pNetwork->GetClients(); + for (size_t b = 0; b < vClients.size(); b++) { + CClient* pClient = vClients[b]; + + if (pClient->GetTimeSinceLastDataTransaction() >= CIRCNetwork::PING_TIMEOUT) { + pClient->PutClient("PING :ZNC"); + } + } + } + +private: + CIRCNetwork* m_pNetwork; +}; + +class CIRCNetworkJoinTimer : public CCron { +public: + CIRCNetworkJoinTimer(CIRCNetwork *pNetwork) : CCron() { + m_pNetwork = pNetwork; + SetName("CIRCNetworkJoinTimer::" + m_pNetwork->GetUser()->GetUserName() + "::" + m_pNetwork->GetName()); + Start(30); + } + + virtual ~CIRCNetworkJoinTimer() {} + +protected: + virtual void RunJob() { + if (m_pNetwork->IsIRCConnected()) { + m_pNetwork->JoinChans(); + } + } + +private: + CIRCNetwork* m_pNetwork; +}; + bool CIRCNetwork::IsValidNetwork(const CString& sNetwork) { // ^[-\w]+$ @@ -65,6 +118,12 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CString& sName) { m_MotdBuffer.SetLineCount(200, true); // This should be more than enough motd lines m_QueryBuffer.SetLineCount(250, true); + m_pPingTimer = new CIRCNetworkPingTimer(this); + CZNC::Get().GetManager().AddCron(m_pPingTimer); + + m_pJoinTimer = new CIRCNetworkJoinTimer(this); + CZNC::Get().GetManager().AddCron(m_pJoinTimer); + SetIRCConnectEnabled(true); } @@ -226,6 +285,9 @@ CIRCNetwork::~CIRCNetwork() { // Make sure we are not in the connection queue CZNC::Get().GetConnectionQueue().remove(this); + + CZNC::Get().GetManager().DelCronByAddr(m_pPingTimer); + CZNC::Get().GetManager().DelCronByAddr(m_pJoinTimer); } void CIRCNetwork::DelServers() { @@ -718,8 +780,11 @@ void CIRCNetwork::JoinChans() { sChans.insert(pChan); // Limit the number of joins - if (uJoins != 0 && --uJoins == 0) + if (uJoins != 0 && --uJoins == 0) { + // Reset the timer. + m_pJoinTimer->Reset(); break; + } } } diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index 2ef12f64..1e0c7931 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -199,6 +199,10 @@ void CIRCSock::ReadLine(const CString& sData) { m_pNetwork->ClearRawBuffer(); m_pNetwork->AddRawBuffer(":" + _NAMEDFMT(sServer) + " " + sCmd + " {target} " + _NAMEDFMT(sRest)); + // Join the first set of channels as soon as we are connected + // and let the CIRCNetworkJoinTimer join the rest. + m_pNetwork->JoinChans(); + break; } case 5: diff --git a/src/User.cpp b/src/User.cpp index cf664f1b..ee672b09 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -36,35 +36,11 @@ public: private: protected: virtual void RunJob() { - vector vNetworks = m_pUser->GetNetworks(); - - for (size_t a = 0; a < vNetworks.size(); a++) { - CIRCNetwork* pNetwork = vNetworks[a]; - CIRCSock* pIRCSock = pNetwork->GetIRCSock(); - - if (pIRCSock && pIRCSock->GetTimeSinceLastDataTransaction() >= 270) { - pIRCSock->PutIRC("PING :ZNC"); - } - - if (pNetwork->IsIRCConnected()) { - pNetwork->JoinChans(); - } - - vector& vClients = pNetwork->GetClients(); - for (size_t b = 0; b < vClients.size(); b++) { - CClient* pClient = vClients[b]; - - if (pClient->GetTimeSinceLastDataTransaction() >= 270) { - pClient->PutClient("PING :ZNC"); - } - } - } - vector& vUserClients = m_pUser->GetUserClients(); for (size_t c = 0; c < vUserClients.size(); ++c) { CClient* pUserClient = vUserClients[c]; - if (pUserClient->GetTimeSinceLastDataTransaction() >= 270) { + if (pUserClient->GetTimeSinceLastDataTransaction() >= CIRCNetwork::PING_TIMEOUT) { pUserClient->PutClient("PING :ZNC"); } }