Permalink
Browse files

Properly handle CIRCNetwork's when we rehash

This commit does the following:
- Do not segfault on rehash
- Delete CIRCNetwork's when they are removed from config
- Update to the configs nick/altnick/realname/ident
  • Loading branch information...
1 parent 18989a2 commit 0b57b7d4371a9bc312f732f7be4cb3c821aeeb94 @kylef kylef committed Nov 8, 2011
Showing with 85 additions and 12 deletions.
  1. +3 −1 include/znc/IRCNetwork.h
  2. +1 −1 include/znc/User.h
  3. +47 −5 src/IRCNetwork.cpp
  4. +34 −5 src/User.cpp
View
@@ -30,9 +30,11 @@ class CIRCNetwork {
static bool IsValidNetwork(const CString& sNetwork);
CIRCNetwork(CUser *pUser, const CString& sName);
- CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneChans = true);
+ CIRCNetwork(CUser *pUser, const CIRCNetwork& Network, bool bCloneChans = true);
~CIRCNetwork();
+ void Clone(const CIRCNetwork& Network, bool bCloneChans = true);
+
CString GetNetworkPath();
void DelServers();
View
@@ -68,7 +68,7 @@ class CUser {
bool DeleteNetwork(const CString& sNetwork);
bool AddNetwork(CIRCNetwork *pNetwork);
void RemoveNetwork(CIRCNetwork *pNetwork);
- CIRCNetwork* FindNetwork(const CString& sNetwork);
+ CIRCNetwork* FindNetwork(const CString& sNetwork) const;
const vector<CIRCNetwork*>& GetNetworks() const;
// !Networks
View
@@ -54,10 +54,9 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CString& sName) {
m_QueryBuffer.SetLineCount(250, true);
}
-CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneChans) {
+CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork &Network, bool bCloneChans) {
m_pUser = NULL;
SetUser(pUser);
- m_sName = pNetwork->GetName();
m_pModules = new CModules;
@@ -71,8 +70,19 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneC
m_MotdBuffer.SetLineCount(200, true); // This should be more than enough motd lines
m_QueryBuffer.SetLineCount(250, true);
+ Clone(Network, bCloneChans);
+}
+
+void CIRCNetwork::Clone(const CIRCNetwork& Network, bool bCloneChans) {
+ m_sName = Network.GetName();
+
+ SetNick(Network.GetNick());
+ SetAltNick(Network.GetAltNick());
+ SetIdent(Network.GetIdent());
+ SetRealName(Network.GetRealName());
+
// Servers
- const vector<CServer*>& vServers = pNetwork->GetServers();
+ const vector<CServer*>& vServers = Network.GetServers();
CString sServer;
CServer* pCurServ = GetCurrentServer();
@@ -107,7 +117,7 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneC
// !Servers
// Chans
- const vector<CChan*>& vChans = pNetwork->GetChans();
+ const vector<CChan*>& vChans = Network.GetChans();
for (a = 0; a < vChans.size(); a++) {
CChan* pNewChan = vChans[a];
CChan* pChan = FindChan(pNewChan->GetName());
@@ -121,7 +131,7 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneC
for (a = 0; a < m_vChans.size(); a++) {
CChan* pChan = m_vChans[a];
- CChan* pNewChan = pNetwork->FindChan(pChan->GetName());
+ CChan* pNewChan = Network.FindChan(pChan->GetName());
if (!pNewChan) {
pChan->SetInConfig(false);
@@ -131,6 +141,38 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneC
}
}
// !Chans
+
+ // Modules
+ set<CString> ssUnloadMods;
+ CModules& vCurMods = GetModules();
+ const CModules& vNewMods = Network.GetModules();
+
+ for (a = 0; a < vNewMods.size(); a++) {
+ CString sModRet;
+ CModule* pNewMod = vNewMods[a];
+ CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName());
+
+ if (!pCurMod) {
+ vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::NetworkModule, m_pUser, this, sModRet);
+ } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) {
+ vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), m_pUser, this, sModRet);
+ }
+ }
+
+ for (a = 0; a < vCurMods.size(); a++) {
+ CModule* pCurMod = vCurMods[a];
+ CModule* pNewMod = vNewMods.FindModule(pCurMod->GetModName());
+
+ if (!pNewMod) {
+ ssUnloadMods.insert(pCurMod->GetModName());
+ }
+ }
+
+ for (set<CString>::iterator it = ssUnloadMods.begin(); it != ssUnloadMods.end(); ++it) {
+ vCurMods.UnloadModule(*it);
+ }
+ // !Modules
+
}
CIRCNetwork::~CIRCNetwork() {
View
@@ -449,8 +449,8 @@ bool CUser::DeleteNetwork(const CString& sNetwork) {
return false;
}
-CIRCNetwork* CUser::FindNetwork(const CString& sNetwork) {
- for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
+CIRCNetwork* CUser::FindNetwork(const CString& sNetwork) const {
+ for (vector<CIRCNetwork*>::const_iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
CIRCNetwork *pNetwork = *it;
if (pNetwork->GetName().Equals(sNetwork)) {
return pNetwork;
@@ -528,7 +528,7 @@ CString CUser::AddTimestamp(time_t tm, const CString& sStr) const {
// The Control+O key combination in mIRC inserts ascii character 15,
// which turns off all previous attributes, including color, bold, underline, and italics.
sRet += "\x0F ";
-
+
sRet += szTimestamp;
}
}
@@ -616,8 +616,37 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) {
// Networks
const vector<CIRCNetwork*>& vNetworks = User.GetNetworks();
- for (a = 0; a < vNetworks.size(); a++) {
- new CIRCNetwork(this, vNetworks[a], bCloneChans);
+ for (vector<CIRCNetwork*>::const_iterator it = vNetworks.begin(); it != vNetworks.end(); ++it) {
+ CIRCNetwork *pNetwork = FindNetwork((*it)->GetName());
+
+ if (pNetwork) {
+ pNetwork->Clone(*(*it), bCloneChans);
+ } else {
+ new CIRCNetwork(this, *(*it), bCloneChans);
+ }
+ }
+
+ set<CString> ssDeleteNetworks;
+ for (vector<CIRCNetwork*>::const_iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
+ if (!(User.FindNetwork((*it)->GetName()))) {
+ ssDeleteNetworks.insert((*it)->GetName());
+ }
+ }
+
+ for (set<CString>::const_iterator it = ssDeleteNetworks.begin(); it != ssDeleteNetworks.end(); ++it) {
+ // The following will move all the clients to the user.
+ // So the clients are not disconnected. The client could
+ // have requested the rehash. Then when we do
+ // client->PutStatus("Rehashing succeeded!") we would
+ // crash if there was no client anymore.
+ vector<CClient*>& vClients = FindNetwork(*it)->GetClients();
+
+ while (vClients.begin() != vClients.end()) {
+ CClient *pClient = vClients.front();
+ pClient->SetNetwork(NULL);
+ }
+
+ DeleteNetwork(*it);
}
// !Networks

0 comments on commit 0b57b7d

Please sign in to comment.