]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Cull channels, warn when Extensible objects are not culled as they must be
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 18 Oct 2009 02:57:46 +0000 (02:57 +0000)
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 18 Oct 2009 02:57:46 +0000 (02:57 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11901 e03df62e-2008-0410-955e-edbf42e46eb7

14 files changed:
include/channels.h
include/extensible.h
src/base.cpp
src/channels.cpp
src/commands/cmd_kick.cpp
src/commands/cmd_part.cpp
src/modules/m_channames.cpp
src/modules/m_cycle.cpp
src/modules/m_messageflood.cpp
src/modules/m_remove.cpp
src/modules/m_sakick.cpp
src/modules/m_sapart.cpp
src/modules/m_spanningtree/svspart.cpp
src/users.cpp

index 7728bb55b16935b0b5bd1efd76d68c6320b16704..2915ed390573a35b395ad846d73b36f54b4981fc 100644 (file)
@@ -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.
index 449c7b38a46c58fccc66822eb9f72b17092c341d..62edb88967464fe901cbe6ab61f4dc989dde8cbe 100644 (file)
@@ -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<ExtensionItem*>& toRemove);
index 15a642eb403aa2145409b63b4262ea9b86e20e3d..97722744054f05272da4765e4fe8e84c876ac43c 100644 (file)
@@ -136,17 +136,27 @@ void Extensible::doUnhookExtensions(const std::vector<ExtensionItem*>& 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)
index 22ec6e4d9f394015c78c9fc2f02d41b31109be35..0e45de33fc1c7c2b9803bd7f58e8a430aefee1c5 100644 (file)
@@ -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, ...)
index d160b030b2eb99f52b126a207cbbf5a14af04611..65b22070c2dfdb9b3f72fcf201e37bf98ea0a7e3 100644 (file)
@@ -66,9 +66,7 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& 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;
 }
index a7a407ac80917dc26b2fa212996b890c90f8f4f2..c234ed681bab6c9073f84cdd8ea176861afc0f02 100644 (file)
@@ -61,9 +61,7 @@ CmdResult CommandPart::Handle (const std::vector<std::string>& parameters, User
 
        if (c)
        {
-               if (!c->PartUser(user, reason))
-                       /* Arse, who stole our channel! :/ */
-                       delete c;
+               c->PartUser(user, reason);
        }
        else
        {
index ba03f9af5480013e4942f49df79f4798a89848c5..c137d0e716a9bde936348e46b096f325a3987dae 100644 (file)
@@ -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;
        }
index dec806b5bf1f1fd7735c929e87f809e52a034c7b..fafdc336cac7c6cbe1728fed4fd94e6db0c6f7b6 100644 (file)
@@ -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());
                        }
index bf124839a4b49853206d33eb98fe2d989640cbae..9bc0f362fb77d120d8291d1c3124d9f93e050361 100644 (file)
@@ -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;
                        }
index 67f81fc65c68732519d19f400aec90f549a195aa..1bbc0931f51faf74e7e9eff2bc31469806d4b32d 100644 (file)
@@ -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
                        {
index 57783be8f99bf27dfba8b0890b9a7cd440cd892b..b81df75c6c6aac53c01035aea82cf24ae7130759 100644 (file)
@@ -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))
index 32a2e16fc66aef4d803834c869ef0b98e9769955..8f0a9e551c0e3becf51e05eca136ecd955c88d92 100644 (file)
@@ -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)
index cc49aa72e0020aeeccdc50e51888ae7f1aa40517..2a34d23c61bef49986f4165cf514b9e7333f3618 100644 (file)
@@ -40,8 +40,7 @@ bool TreeSocket::ServicePart(const std::string &prefix, parameterlist &params)
        {
                /* 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);
        }
 
index 542a6e565c57751c0c315a91e2ac1df340f4a8eb..665f1d90831eb05e58562e6f6e6fe191d8aa5cfb 100644 (file)
@@ -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<Channel*>::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();