]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree.cpp
Cache channel max bans value to save an O(n) loop of match() on every ban (etc) add
[user/henk/code/inspircd.git] / src / modules / m_spanningtree.cpp
index f423f76171d416265b0c08433bb8d0d2fc94840f..871675ed6afc65d03c0ed822de801aa82ca9cf92 100644 (file)
@@ -357,7 +357,7 @@ class TreeServer : public classbase
                ServerInstance->Log(DEBUG,"Removing all users from server %s",this->ServerName.c_str());
                const char* reason_s = reason.c_str();
                std::vector<userrec*> time_to_die;
-               for (user_hash::iterator n = ServerInstance->clientlist.begin(); n != ServerInstance->clientlist.end(); n++)
+               for (user_hash::iterator n = ServerInstance->clientlist->begin(); n != ServerInstance->clientlist->end(); n++)
                {
                        if (!strcmp(n->second->server, this->ServerName.c_str()))
                        {
@@ -619,12 +619,22 @@ class cmd_rconnect : public command_t
        cmd_rconnect (InspIRCd* Instance, Module* Callback, SpanningTreeUtilities* Util) : command_t(Instance, "RCONNECT", 'o', 2), Creator(Callback), Utils(Util)
        {
                this->source = "m_spanningtree.so";
-               syntax = "<remote-server-mask> <servermask>";
+               syntax = "<remote-server-mask> <target-server-mask>";
        }
 
        CmdResult Handle (const char** parameters, int pcnt, userrec *user)
        {
-               user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick,parameters[0],parameters[1]);
+               if (IS_LOCAL(user))
+               {
+                       if (!Utils->FindServer(parameters[0]))
+                       {
+                               user->WriteServ("NOTICE %s :*** RCONNECT: Server \002%s\002 isn't connected to the network!", user->nick, parameters[0]);
+                               return CMD_FAILURE;
+                       }
+                       
+                       user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick,parameters[0],parameters[1]);
+               }
+               
                /* Is this aimed at our server? */
                if (ServerInstance->MatchText(ServerInstance->Config->ServerName,parameters[0]))
                {
@@ -634,11 +644,9 @@ class cmd_rconnect : public command_t
                        para[0] = parameters[1];
                        std::string original_command = std::string("CONNECT ") + parameters[1];
                        Creator->OnPreCommand("CONNECT", para, 1, user, true, original_command);
-
-                       return CMD_SUCCESS;
                }
-
-               return CMD_FAILURE;
+               
+               return CMD_SUCCESS;
        }
 };
  
@@ -1627,20 +1635,6 @@ class TreeSocket : public InspSocket
                else
                        created = true; /* don't perform deops, and set TS to correct time after processing. */
 
-               /* Check if there are any local users on this channel. If there are not, set created = true.
-                * If there are no local users here, theres no need for us to bounce the modes, we leave this
-                * to servers which do have local users and save some bandwidth and prevent spurious deops
-                */
-               if (!created)
-               {
-                       CUList elist;
-                       TreeServerList list;
-                       Utils->GetListOfServersForChannel(chan, list, 0, elist);
-                       if (list.find(Utils->TreeRoot) == list.end())
-                               created = true;
-               }
-
-
                /* In 1.1, if they have the newer channel, we immediately clear
                 * all status modes from our users. We then accept their modes.
                 * If WE have the newer channel its the other side's job to do this.
@@ -1649,6 +1643,7 @@ class TreeSocket : public InspSocket
                 */
                if (ourTS > TS)
                {
+                       Instance->Log(DEBUG,"************ WE LOST TS COMPARE, DEOPPING EVERYONE ********************* ");
                        std::deque<std::string> param_list;
 
                        /* Lower the TS here */
@@ -1661,8 +1656,9 @@ class TreeSocket : public InspSocket
                        if (!created)
                        {
                                param_list.push_back(channel);
-                               this->RemoveStatus(Instance->Config->ServerName, param_list);
+                               /* Do this first! */
                                chan->age = TS;
+                               this->RemoveStatus(Instance->Config->ServerName, param_list);
                        }
                }
 
@@ -1870,19 +1866,12 @@ class TreeSocket : public InspSocket
                //       0    1   2     3     4      5   6     7
                time_t age = atoi(params[0].c_str());
                
-               /* This used to have a pretty craq'y loop doing the same thing,
-                * now we just let the STL do the hard work (more efficiently)
-                */
-               std::string::size_type pos_after_plus = params[5].find_first_not_of('+');
-               if (pos_after_plus != std::string::npos)
-                       params[5] = params[5].substr(pos_after_plus);
-               
                const char* tempnick = params[1].c_str();
                Instance->Log(DEBUG,"Introduce client %s!%s@%s",tempnick,params[4].c_str(),params[2].c_str());
                
-               user_hash::iterator iter = this->Instance->clientlist.find(tempnick);
+               user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
                
-               if (iter != this->Instance->clientlist.end())
+               if (iter != this->Instance->clientlist->end())
                {
                        // nick collision
                        Instance->Log(DEBUG,"Nick collision on %s!%s@%s: %lu %lu",tempnick,params[4].c_str(),params[2].c_str(),(unsigned long)age,(unsigned long)iter->second->age);
@@ -1892,7 +1881,7 @@ class TreeSocket : public InspSocket
                }
 
                userrec* _new = new userrec(this->Instance);
-               this->Instance->clientlist[tempnick] = _new;
+               (*(this->Instance->clientlist))[tempnick] = _new;
                _new->SetFd(FD_MAGIC_NUMBER);
                strlcpy(_new->nick, tempnick,NICKMAX-1);
                strlcpy(_new->host, params[2].c_str(),63);
@@ -1903,8 +1892,25 @@ class TreeSocket : public InspSocket
                _new->registered = REG_ALL;
                _new->signon = age;
                
+               /*
+                * we need to remove the + from the modestring, so we can do our stuff
+                */
+               std::string::size_type pos_after_plus = params[5].find_first_not_of('+');
+               if (pos_after_plus != std::string::npos)
+                       params[5] = params[5].substr(pos_after_plus);
+               
+
                for (std::string::iterator v = params[5].begin(); v != params[5].end(); v++)
+               {
                        _new->modes[(*v)-65] = 1;
+                       /* For each mode thats set, increase counter */
+                       ModeHandler* mh = Instance->Modes->FindMode(*v, MODETYPE_USER);
+                       if (mh)
+                               mh->ChangeCount(1);
+               }
+
+               /* now we've done with modes processing, put the + back for remote servers */
+               params[5] = "+" + params[5];
 
 #ifdef SUPPORT_IP6LINKS
                if (params[6].find_first_of(":") != std::string::npos)
@@ -1918,7 +1924,7 @@ class TreeSocket : public InspSocket
                this->Instance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s]",_new->server,_new->nick,_new->ident,_new->host, _new->GetIPString());
 
                params[7] = ":" + params[7];
-               Utils->DoOneToAllButSender(source,"NICK",params,source);
+               Utils->DoOneToAllButSender(source,"NICK", params, source);
 
                // Increment the Source Servers User Count..
                TreeServer* SourceServer = Utils->FindServer(source);
@@ -2027,44 +2033,44 @@ class TreeSocket : public InspSocket
                std::string buffer;
                std::string n = this->Instance->Config->ServerName;
                const char* sn = n.c_str();
-               int iterations = 0;
+
                /* Yes, these arent too nice looking, but they get the job done */
-               for (std::vector<ZLine*>::iterator i = Instance->XLines->zlines.begin(); i != Instance->XLines->zlines.end(); i++, iterations++)
+               for (std::vector<ZLine*>::iterator i = Instance->XLines->zlines.begin(); i != Instance->XLines->zlines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<QLine*>::iterator i = Instance->XLines->qlines.begin(); i != Instance->XLines->qlines.end(); i++, iterations++)
+               for (std::vector<QLine*>::iterator i = Instance->XLines->qlines.begin(); i != Instance->XLines->qlines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<GLine*>::iterator i = Instance->XLines->glines.begin(); i != Instance->XLines->glines.end(); i++, iterations++)
+               for (std::vector<GLine*>::iterator i = Instance->XLines->glines.begin(); i != Instance->XLines->glines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<ELine*>::iterator i = Instance->XLines->elines.begin(); i != Instance->XLines->elines.end(); i++, iterations++)
+               for (std::vector<ELine*>::iterator i = Instance->XLines->elines.begin(); i != Instance->XLines->elines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<ZLine*>::iterator i = Instance->XLines->pzlines.begin(); i != Instance->XLines->pzlines.end(); i++, iterations++)
+               for (std::vector<ZLine*>::iterator i = Instance->XLines->pzlines.begin(); i != Instance->XLines->pzlines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE Z %s %s %lu %lu :%s\r\n",sn,(*i)->ipaddr,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<QLine*>::iterator i = Instance->XLines->pqlines.begin(); i != Instance->XLines->pqlines.end(); i++, iterations++)
+               for (std::vector<QLine*>::iterator i = Instance->XLines->pqlines.begin(); i != Instance->XLines->pqlines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE Q %s %s %lu %lu :%s\r\n",sn,(*i)->nick,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<GLine*>::iterator i = Instance->XLines->pglines.begin(); i != Instance->XLines->pglines.end(); i++, iterations++)
+               for (std::vector<GLine*>::iterator i = Instance->XLines->pglines.begin(); i != Instance->XLines->pglines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE G %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
                }
-               for (std::vector<ELine*>::iterator i = Instance->XLines->pelines.begin(); i != Instance->XLines->pelines.end(); i++, iterations++)
+               for (std::vector<ELine*>::iterator i = Instance->XLines->pelines.begin(); i != Instance->XLines->pelines.end(); i++)
                {
                        snprintf(data,MAXBUF,":%s ADDLINE E %s@%s %s %lu %lu :%s\r\n",sn,(*i)->identmask,(*i)->hostmask,(*i)->source,(unsigned long)(*i)->set_time,(unsigned long)(*i)->duration,(*i)->reason);
                        buffer.append(data);
@@ -2079,10 +2085,9 @@ class TreeSocket : public InspSocket
        {
                char data[MAXBUF];
                std::deque<std::string> list;
-               int iterations = 0;
                std::string n = this->Instance->Config->ServerName;
                const char* sn = n.c_str();
-               for (chan_hash::iterator c = this->Instance->chanlist.begin(); c != this->Instance->chanlist.end(); c++, iterations++)
+               for (chan_hash::iterator c = this->Instance->chanlist->begin(); c != this->Instance->chanlist->end(); c++)
                {
                        SendFJoins(Current, c->second);
                        if (*c->second->topic)
@@ -2106,8 +2111,7 @@ class TreeSocket : public InspSocket
                char data[MAXBUF];
                std::deque<std::string> list;
                std::string dataline;
-               int iterations = 0;
-               for (user_hash::iterator u = this->Instance->clientlist.begin(); u != this->Instance->clientlist.end(); u++, iterations++)
+               for (user_hash::iterator u = this->Instance->clientlist->begin(); u != this->Instance->clientlist->end(); u++)
                {
                        if (u->second->registered == REG_ALL)
                        {
@@ -2363,6 +2367,7 @@ class TreeSocket : public InspSocket
                if (u)
                {
                        u->modes[UM_OPERATOR] = 1;
+                       this->Instance->all_opers.push_back(u);
                        strlcpy(u->oper,opertype.c_str(),NICKMAX-1);
                        Utils->DoOneToAllButSender(u->nick,"OPERTYPE",params,u->server);
                        this->Instance->SNO->WriteToSnoMask('o',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server, u->nick,u->ident,u->host,irc::Spacify(opertype.c_str()));
@@ -2459,7 +2464,9 @@ class TreeSocket : public InspSocket
 
                if (u)
                {
-                       chanrec::JoinUser(this->Instance, u, params[1].c_str(), false);
+                       /* only join if it's local, otherwise just pass it on! */
+                       if (IS_LOCAL(u))
+                               chanrec::JoinUser(this->Instance, u, params[1].c_str(), false);
                        Utils->DoOneToAllButSender(prefix,"SVSJOIN",params,prefix);
                }
                return true;
@@ -2474,7 +2481,7 @@ class TreeSocket : public InspSocket
 
                if (this->Instance->MatchText(this->Instance->Config->ServerName,servermask))
                {
-                       this->Instance->SNO->WriteToSnoMask('l',"Remote rehash initiated from server \002"+prefix+"\002.");
+                       this->Instance->SNO->WriteToSnoMask('l',"Remote rehash initiated by \002"+prefix+"\002.");
                        this->Instance->RehashServer();
                        Utils->ReadConfiguration(false);
                        InitializeDisabledCommands(Instance->Config->DisabledCommands, Instance);
@@ -3707,12 +3714,12 @@ class ServernameResolver : public Resolver
        Link MyLink;
        SpanningTreeUtilities* Utils;
  public: 
-       ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(Util)
+       ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x, bool &cached) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), MyLink(x), Utils(Util)
        {
                /* Nothing in here, folks */
        }
 
-       void OnLookupComplete(const std::string &result)
+       void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
        {
                /* Initiate the connection, now that we have an IP to use.
                 * Passing a hostname directly to InspSocket causes it to
@@ -3757,11 +3764,11 @@ class SecurityIPResolver : public Resolver
        Link MyLink;
        SpanningTreeUtilities* Utils;
  public:
-       SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(U)
+       SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x, bool &cached) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), MyLink(x), Utils(U)
        {
        }
 
-       void OnLookupComplete(const std::string &result)
+       void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
        {
                ServerInstance->Log(DEBUG,"Security IP cache: Adding IP address '%s' for Link '%s'",result.c_str(),MyLink.Name.c_str());
                Utils->ValidIPs.push_back(result);
@@ -4115,8 +4122,9 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind)
                                {
                                        try
                                        {
-                                               SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L);
-                                               ServerInstance->AddResolver(sr);
+                                               bool cached;
+                                               SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L, cached);
+                                               ServerInstance->AddResolver(sr, cached);
                                        }
                                        catch (ModuleException& e)
                                        {
@@ -4342,13 +4350,13 @@ class ModuleSpanningTree : public Module
 
                        float percent;
                        char text[80];
-                       if (ServerInstance->clientlist.size() == 0) {
+                       if (ServerInstance->clientlist->size() == 0) {
                                // If there are no users, WHO THE HELL DID THE /MAP?!?!?!
                                percent = 0;
                        }
                        else
                        {
-                               percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist.size()) * 100;
+                               percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist->size()) * 100;
                        }
                        snprintf(text, 80, "%s %s%5d [%5.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
                        totusers += Current->GetUserCount();
@@ -4646,8 +4654,9 @@ class ModuleSpanningTree : public Module
                {
                        try
                        {
-                               ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x);
-                               ServerInstance->AddResolver(snr);
+                               bool cached;
+                               ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x, cached);
+                               ServerInstance->AddResolver(snr, cached);
                        }
                        catch (ModuleException& e)
                        {
@@ -4994,25 +5003,29 @@ class ModuleSpanningTree : public Module
                // Only do this for local users
                if (IS_LOCAL(user))
                {
-                       std::deque<std::string> params;
-                       params.clear();
-                       params.push_back(channel->name);
-                       // set up their permissions and the channel TS with FJOIN.
-                       // All users are FJOINed now, because a module may specify
-                       // new joining permissions for the user.
-                       params.clear();
-                       params.push_back(channel->name);
-                       params.push_back(ConvToStr(channel->age));
-                       params.push_back(std::string(channel->GetAllPrefixChars(user))+","+std::string(user->nick));
-                       Utils->DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params);
                        if (channel->GetUserCounter() == 1)
                        {
+                               std::deque<std::string> params;
+                               // set up their permissions and the channel TS with FJOIN.
+                               // All users are FJOINed now, because a module may specify
+                               // new joining permissions for the user.
+                               params.push_back(channel->name);
+                               params.push_back(ConvToStr(channel->age));
+                               params.push_back(std::string(channel->GetAllPrefixChars(user))+","+std::string(user->nick));
+                               Utils->DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params);
                                /* First user in, sync the modes for the channel */
                                params.pop_back();
                                /* This is safe, all inspircd servers default to +nt */
                                params.push_back("+nt");
                                Utils->DoOneToMany(ServerInstance->Config->ServerName,"FMODE",params);
                        }
+                       else
+                       {
+                               std::deque<std::string> params;
+                               params.push_back(channel->name);
+                               params.push_back(ConvToStr(channel->age));
+                               Utils->DoOneToMany(user->nick,"JOIN",params);
+                       }
                }
        }
 
@@ -5130,21 +5143,22 @@ class ModuleSpanningTree : public Module
                Utils->DoOneToMany(source->nick,"KILL",params);
        }
 
-       virtual void OnRehash(const std::string &parameter)
+       virtual void OnRehash(userrec* user, const std::string &parameter)
        {
                if (parameter != "")
                {
                        std::deque<std::string> params;
                        params.push_back(parameter);
-                       Utils->DoOneToMany(ServerInstance->Config->ServerName,"REHASH",params);
+                       Utils->DoOneToMany(user ? user->nick : ServerInstance->Config->ServerName, "REHASH", params);
                        // check for self
                        if (ServerInstance->MatchText(ServerInstance->Config->ServerName,parameter))
                        {
-                               ServerInstance->WriteOpers("*** Remote rehash initiated from server \002%s\002",ServerInstance->Config->ServerName);
+                               ServerInstance->WriteOpers("*** Remote rehash initiated locally by \002%s\002", user ? user->nick : ServerInstance->Config->ServerName);
                                ServerInstance->RehashServer();
                        }
                }
                Utils->ReadConfiguration(false);
+               InitializeDisabledCommands(ServerInstance->Config->DisabledCommands, ServerInstance);
        }
 
        // note: the protocol does not allow direct umode +o except