From e50d016aa23083f81dcf181f68edb81c5b23c78d Mon Sep 17 00:00:00 2001 From: danieldg Date: Sun, 18 Oct 2009 02:57:46 +0000 Subject: [PATCH] Cull channels, warn when Extensible objects are not culled as they must be git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11901 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/channels.h | 8 ++-- include/extensible.h | 1 + src/base.cpp | 12 +++++- src/channels.cpp | 59 ++++++++++++-------------- src/commands/cmd_kick.cpp | 4 +- src/commands/cmd_part.cpp | 4 +- src/modules/m_channames.cpp | 4 +- src/modules/m_cycle.cpp | 4 +- src/modules/m_messageflood.cpp | 5 +-- src/modules/m_remove.cpp | 3 +- src/modules/m_sakick.cpp | 3 +- src/modules/m_sapart.cpp | 3 +- src/modules/m_spanningtree/svspart.cpp | 3 +- src/users.cpp | 30 +------------ 14 files changed, 54 insertions(+), 89 deletions(-) diff --git a/include/channels.h b/include/channels.h index 7728bb55b..2915ed390 100644 --- a/include/channels.h +++ b/include/channels.h @@ -204,7 +204,7 @@ class CoreExport Channel : public Extensible * @param user The user to delete * @return number of users left on the channel after deletion of the user */ - unsigned long DelUser(User* user); + void DelUser(User* user); /** Obtain the internal reference list * The internal reference list contains a list of User*. @@ -232,7 +232,7 @@ class CoreExport Channel : public Extensible * @return The number of users left on the channel. If this is zero * when the method returns, you MUST delete the Channel immediately! */ - long KickUser(User *src, User *user, const char* reason); + void KickUser(User *src, User *user, const char* reason); /** Make the server kick user from this channel with the given reason. * @param user The user being kicked (must be on this channel) @@ -241,7 +241,7 @@ class CoreExport Channel : public Extensible * @return The number of users left on the channel. If this is zero * when the method returns, you MUST delete the Channel immediately! */ - long ServerKickUser(User* user, const char* reason, const std::string& servername = ""); + void ServerKickUser(User* user, const char* reason, const std::string& servername = ""); /** Part a user from this channel with the given reason. * If the reason field is NULL, no reason will be sent. @@ -250,7 +250,7 @@ class CoreExport Channel : public Extensible * @return The number of users left on the channel. If this is zero * when the method returns, you MUST delete the Channel immediately! */ - long PartUser(User *user, std::string &reason); + void PartUser(User *user, std::string &reason); /* Join a user to a channel. May be a channel that doesnt exist yet. * @param user The user to join to the channel. diff --git a/include/extensible.h b/include/extensible.h index 449c7b38a..62edb8896 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -72,6 +72,7 @@ class CoreExport Extensible : public classbase */ inline const ExtensibleStore& GetExtList() const { return extensions; } + Extensible(); virtual CullResult cull(); virtual ~Extensible(); void doUnhookExtensions(const std::vector& toRemove); diff --git a/src/base.cpp b/src/base.cpp index 15a642eb4..977227440 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -136,17 +136,27 @@ void Extensible::doUnhookExtensions(const std::vector& toRemove) } } +Extensible::Extensible() +{ + extensions[NULL] = NULL; +} + CullResult Extensible::cull() { for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i) { - i->first->free(i->second); + if (i->first) + i->first->free(i->second); } + extensions.clear(); return classbase::cull(); } Extensible::~Extensible() { + if (!extensions.empty() && ServerInstance && ServerInstance->Logs) + ServerInstance->Logs->Log("CULLLIST", DEBUG, + "Extensible destructor called without cull @%p", (void*)this); } LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod) diff --git a/src/channels.cpp b/src/channels.cpp index 22ec6e4d9..0e45de33f 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -125,17 +125,16 @@ Membership* Channel::AddUser(User* user) return memb; } -unsigned long Channel::DelUser(User* user) +void Channel::DelUser(User* user) { UserMembIter a = userlist.find(user); if (a != userlist.end()) { + a->second->cull(); delete a->second; userlist.erase(a); } - - return userlist.size(); } bool Channel::HasUser(User* user) @@ -448,10 +447,10 @@ ModResult Channel::GetExtBanStatus(User *user, char type) * remove a channel from a users record, and return the number of users left. * Therefore, if this function returns 0 the caller should delete the Channel. */ -long Channel::PartUser(User *user, std::string &reason) +void Channel::PartUser(User *user, std::string &reason) { if (!user) - return this->GetUserCounter(); + return; Membership* memb = GetUser(user); @@ -466,39 +465,38 @@ long Channel::PartUser(User *user, std::string &reason) this->RemoveAllPrefixes(user); } - if (!this->DelUser(user)) /* if there are no users left on the channel... */ + this->DelUser(user); + if (userlist.empty()) { + ModResult res; + FIRST_MOD_RESULT(OnChannelPreDelete, res, (this)); + if (res == MOD_RES_DENY) + return; chan_hash::iterator iter = ServerInstance->chanlist->find(this->name); /* kill the record */ if (iter != ServerInstance->chanlist->end()) { - ModResult res; - FIRST_MOD_RESULT(OnChannelPreDelete, res, (this)); - if (res == MOD_RES_DENY) - return 1; // delete halted by module FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this)); ServerInstance->chanlist->erase(iter); } - return 0; + ServerInstance->GlobalCulls.AddItem(this); } - - return this->GetUserCounter(); } -long Channel::ServerKickUser(User* user, const char* reason, const std::string& servername) +void Channel::ServerKickUser(User* user, const char* reason, const std::string& servername) { if (servername.empty() || !ServerInstance->Config->HideWhoisServer.empty()) ServerInstance->FakeClient->server = ServerInstance->Config->ServerName; else ServerInstance->FakeClient->server = servername; - return this->KickUser(ServerInstance->FakeClient, user, reason); + KickUser(ServerInstance->FakeClient, user, reason); } -long Channel::KickUser(User *src, User *user, const char* reason) +void Channel::KickUser(User *src, User *user, const char* reason) { if (!src || !user || !reason) - return this->GetUserCounter(); + return; Membership* memb = GetUser(user); if (IS_LOCAL(src)) @@ -506,12 +504,12 @@ long Channel::KickUser(User *src, User *user, const char* reason) if (!memb) { src->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s %s :They are not on that channel",src->nick.c_str(), user->nick.c_str(), this->name.c_str()); - return this->GetUserCounter(); + return; } if ((ServerInstance->ULine(user->server)) && (!ServerInstance->ULine(src->server))) { src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only a u-line may kick a u-line from a channel.",src->nick.c_str(), this->name.c_str()); - return this->GetUserCounter(); + return; } ModResult res; @@ -521,7 +519,7 @@ long Channel::KickUser(User *src, User *user, const char* reason) FIRST_MOD_RESULT(OnUserPreKick, res, (src,memb,reason)); if (res == MOD_RES_DENY) - return this->GetUserCounter(); + return; if (res == MOD_RES_PASSTHRU) { @@ -530,7 +528,7 @@ long Channel::KickUser(User *src, User *user, const char* reason) if ((them < HALFOP_VALUE) || (them < us)) { src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator",src->nick.c_str(), this->name.c_str(), them >= HALFOP_VALUE ? "" : "half-"); - return this->GetUserCounter(); + return; } } } @@ -546,25 +544,22 @@ long Channel::KickUser(User *src, User *user, const char* reason) this->RemoveAllPrefixes(user); } - if (!this->DelUser(user)) - /* if there are no users left on the channel */ + this->DelUser(user); + if (userlist.empty()) { - chan_hash::iterator iter = ServerInstance->chanlist->find(this->name.c_str()); - + ModResult res; + FIRST_MOD_RESULT(OnChannelPreDelete, res, (this)); + if (res == MOD_RES_DENY) + return; + chan_hash::iterator iter = ServerInstance->chanlist->find(this->name); /* kill the record */ if (iter != ServerInstance->chanlist->end()) { - ModResult res; - FIRST_MOD_RESULT(OnChannelPreDelete, res, (this)); - if (res == MOD_RES_DENY) - return 1; // delete halted by module FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this)); ServerInstance->chanlist->erase(iter); } - return 0; + ServerInstance->GlobalCulls.AddItem(this); } - - return this->GetUserCounter(); } void Channel::WriteChannel(User* user, const char* text, ...) diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp index d160b030b..65b22070c 100644 --- a/src/commands/cmd_kick.cpp +++ b/src/commands/cmd_kick.cpp @@ -66,9 +66,7 @@ CmdResult CommandKick::Handle (const std::vector& parameters, User reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick); } - if (!c->KickUser(user, u, reason.c_str())) - /* Nobody left here, delete the Channel */ - delete c; + c->KickUser(user, u, reason.c_str()); return CMD_SUCCESS; } diff --git a/src/commands/cmd_part.cpp b/src/commands/cmd_part.cpp index a7a407ac8..c234ed681 100644 --- a/src/commands/cmd_part.cpp +++ b/src/commands/cmd_part.cpp @@ -61,9 +61,7 @@ CmdResult CommandPart::Handle (const std::vector& parameters, User if (c) { - if (!c->PartUser(user, reason)) - /* Arse, who stole our channel! :/ */ - delete c; + c->PartUser(user, reason); } else { diff --git a/src/modules/m_channames.cpp b/src/modules/m_channames.cpp index ba03f9af5..c137d0e71 100644 --- a/src/modules/m_channames.cpp +++ b/src/modules/m_channames.cpp @@ -81,8 +81,8 @@ class ModuleChannelNames : public Module } const UserMembList* users = c->GetUsers(); for(UserMembCIter j = users->begin(); j != users->end(); ++j) - if (IS_LOCAL(j->first) && !c->ServerKickUser(j->first, "Channel name no longer valid", NULL)) - delete c; + if (IS_LOCAL(j->first)) + c->ServerKickUser(j->first, "Channel name no longer valid", NULL); } badchan = false; } diff --git a/src/modules/m_cycle.cpp b/src/modules/m_cycle.cpp index dec806b5b..fafdc336c 100644 --- a/src/modules/m_cycle.cpp +++ b/src/modules/m_cycle.cpp @@ -57,9 +57,7 @@ class CommandCycle : public Command return CMD_FAILURE; } - /* XXX in the future, this may move to a static Channel method (the delete.) -- w00t */ - if (!channel->PartUser(user, reason)) - delete channel; + channel->PartUser(user, reason); Channel::JoinUser(user, parameters[0].c_str(), true, "", false, ServerInstance->Time()); } diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp index bf124839a..9bc0f362f 100644 --- a/src/modules/m_messageflood.cpp +++ b/src/modules/m_messageflood.cpp @@ -234,10 +234,7 @@ class ModuleMsgFlood : public Module char kickmessage[MAXBUF]; snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %d lines in %d secs)", f->lines, f->secs); - if (!dest->ServerKickUser(user, kickmessage)) - { - delete dest; - } + dest->ServerKickUser(user, kickmessage); return MOD_RES_DENY; } diff --git a/src/modules/m_remove.cpp b/src/modules/m_remove.cpp index 67f81fc65..1bbc0931f 100644 --- a/src/modules/m_remove.cpp +++ b/src/modules/m_remove.cpp @@ -106,8 +106,7 @@ class RemoveBase : public Command channel->WriteChannelWithServ(ServerInstance->Config->ServerName.c_str(), "NOTICE %s :%s removed %s from the channel", channel->name.c_str(), user->nick.c_str(), target->nick.c_str()); target->WriteServ("NOTICE %s :*** %s removed you from %s with the message: %s", target->nick.c_str(), user->nick.c_str(), channel->name.c_str(), reasonparam.c_str()); - if (!channel->PartUser(target, reason)) - delete channel; + channel->PartUser(target, reason); } else { diff --git a/src/modules/m_sakick.cpp b/src/modules/m_sakick.cpp index 57783be8f..b81df75c6 100644 --- a/src/modules/m_sakick.cpp +++ b/src/modules/m_sakick.cpp @@ -56,8 +56,7 @@ class CommandSakick : public Command */ if (IS_LOCAL(dest)) { - if (!channel->ServerKickUser(dest, reason, servername)) - delete channel; + channel->ServerKickUser(dest, reason, servername); Channel *n = ServerInstance->FindChan(parameters[1]); if (n && n->HasUser(dest)) diff --git a/src/modules/m_sapart.cpp b/src/modules/m_sapart.cpp index 32a2e16fc..8f0a9e551 100644 --- a/src/modules/m_sapart.cpp +++ b/src/modules/m_sapart.cpp @@ -49,8 +49,7 @@ class CommandSapart : public Command */ if (IS_LOCAL(dest)) { - if (!channel->PartUser(dest, reason)) - delete channel; + channel->PartUser(dest, reason); Channel* n = ServerInstance->FindChan(parameters[1]); if (!n) diff --git a/src/modules/m_spanningtree/svspart.cpp b/src/modules/m_spanningtree/svspart.cpp index cc49aa72e..2a34d23c6 100644 --- a/src/modules/m_spanningtree/svspart.cpp +++ b/src/modules/m_spanningtree/svspart.cpp @@ -40,8 +40,7 @@ bool TreeSocket::ServicePart(const std::string &prefix, parameterlist ¶ms) { /* only part if it's local, otherwise just pass it on! */ if (IS_LOCAL(u)) - if (!c->PartUser(u, reason)) - delete c; + c->PartUser(u, reason); Utils->DoOneToAllButSender(prefix,"SVSPART",params,prefix); } diff --git a/src/users.cpp b/src/users.cpp index 542a6e565..665f1d908 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -1708,35 +1708,7 @@ void User::PurgeEmptyChannels() { Channel* c = *f; c->RemoveAllPrefixes(this); - if (c->DelUser(this) == 0) - { - /* No users left in here, mark it for deletion */ - try - { - to_delete.push_back(c); - } - catch (...) - { - ServerInstance->Logs->Log("USERS", DEBUG,"Exception in User::PurgeEmptyChannels to_delete.push_back()"); - } - } - } - - for (std::vector::iterator n = to_delete.begin(); n != to_delete.end(); n++) - { - Channel* thischan = *n; - chan_hash::iterator i2 = ServerInstance->chanlist->find(thischan->name); - if (i2 != ServerInstance->chanlist->end()) - { - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnChannelPreDelete, MOD_RESULT, (i2->second)); - if (MOD_RESULT == MOD_RES_DENY) - continue; // delete halted by module - FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(i2->second)); - delete i2->second; - ServerInstance->chanlist->erase(i2); - this->chans.erase(*n); - } + c->DelUser(this); } this->UnOper(); -- 2.39.2