]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree.cpp
Change error from 'connection established' to 'connection started'
[user/henk/code/inspircd.git] / src / modules / m_spanningtree.cpp
index 8b410900af4be5718ffd72c691db5c57aa61298e..7e7e91382e44cad7cc3e2c6d0e31bf60e65cbf8c 100644 (file)
@@ -37,7 +37,7 @@ using namespace std;
 /** If you make a change which breaks the protocol, increment this.
  * If you  completely change the protocol, completely change the number.
  */
-const long ProtocolVersion = 1100;
+const long ProtocolVersion = 1101;
 
 /*
  * The server list in InspIRCd is maintained as two structures
@@ -728,7 +728,7 @@ class TreeSocket : public InspSocket
                        {
                                if (x->Name == this->myhost)
                                {
-                                       this->Instance->SNO->WriteToSnoMask('l',"Connection to \2"+myhost+"\2["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] established.");
+                                       this->Instance->SNO->WriteToSnoMask('l',"Connection to \2"+myhost+"\2["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] started.");
                                        this->SendCapabilities();
                                        if (x->EncryptionKey != "")
                                        {
@@ -1546,7 +1546,23 @@ class TreeSocket : public InspSocket
                        ourTS = us->age;
                }
 
-               Instance->Log(DEBUG,"FJOIN detected, our TS=%lu, their TS=%lu",ourTS,TS);
+               /* XXX: PAY ATTENTION:
+                * 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.
+                * Note that this causes the losing server to send out confirming
+                * FMODE lines.
+                */
+               if ((ourTS > TS) || (this->Instance->ULine(source.c_str())))
+               {
+                       Instance->Log(DEBUG,"FJOIN detected, our TS=%lu, their TS=%lu",ourTS,TS);
+                       std::deque<std::string> param_list;
+                       us->age = TS;
+                       ourTS = TS;
+                       param_list.push_back(chan->name);
+                       Instance->Log(DEBUG,"REMOVE ALL STATUS MODES FROM OUR USERS *NOW*");
+                       this->RemoveStatus(Instance->Config->ServerName, param_list);
+               }
 
                irc::tokenstream users(params[2]);
                std::string item = "*";
@@ -1611,25 +1627,6 @@ class TreeSocket : public InspSocket
                                                                ourTS = TS;
                                                        }
                                                }
-                                               else
-                                               {
-                                                       Instance->Log(DEBUG,"Their channel newer than ours, bouncing their modes");
-                                                       /* bouncy bouncy! */
-                                                       std::deque<std::string> params;
-                                                       /* modes are now being UNSET... */
-                                                       *mode_users[1] = '-';
-                                                       for (unsigned int x = 0; x < modectr; x++)
-                                                       {
-                                                               if (x == 1)
-                                                               {
-                                                                       params.push_back(ConvToStr(us->age));
-                                                               }
-                                                               params.push_back(mode_users[x]);
-                                                               
-                                                       }
-                                                       // tell everyone to bounce the modes. bad modes, bad!
-                                                       DoOneToMany(this->Instance->Config->ServerName,"FMODE",params);
-                                               }
                                                strcpy(mode_users[1],"+");
                                                for (unsigned int f = 2; f < modectr; f++)
                                                        free(mode_users[f]);
@@ -1638,7 +1635,7 @@ class TreeSocket : public InspSocket
                                }
                                else
                                {
-                                       Instance->Log(SPARSE,"Warning! Invalid user %s in FJOIN to channel %s IGNORED", who->nick, channel.c_str());
+                                       Instance->Log(SPARSE,"Warning! Invalid user in FJOIN to channel %s IGNORED", channel.c_str());
                                        continue;
                                }
                        }
@@ -1659,21 +1656,6 @@ class TreeSocket : public InspSocket
                                        ourTS = TS;
                                }
                        }
-                       else
-                       {
-                               Instance->Log(DEBUG,"Their channel newer than ours, bouncing their modes");
-                               std::deque<std::string> params;
-                               *mode_users[1] = '-';
-                               for (unsigned int x = 0; x < modectr; x++)
-                               {
-                                       if (x == 1)
-                                       {
-                                               params.push_back(ConvToStr(us->age));
-                                       }
-                                       params.push_back(mode_users[x]);
-                               }
-                               DoOneToMany(this->Instance->Config->ServerName,"FMODE",params);
-                       }
 
                        for (unsigned int f = 2; f < modectr; f++)
                                free(mode_users[f]);
@@ -2620,6 +2602,52 @@ class TreeSocket : public InspSocket
                }
        }
 
+       bool RemoveStatus(std::string prefix, std::deque<std::string> &params)
+       {
+               if (params.size() < 1)
+                       return true;
+
+               chanrec* c = Instance->FindChan(params[0]);
+
+               if (c)
+               {
+                       CUList *ulist = c->GetUsers();
+                       for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+                       {
+                               std::string modesequence = Instance->Modes->ModeString(i->second, c);
+                               if (modesequence.length())
+                               {
+                                       modesequence = "-" + modesequence;
+
+                                       std::deque<std::string> items;
+                                       const char* y[127];
+                                       unsigned int z = 0;
+                                       std::string x = "*";
+                                       irc::spacesepstream sep(modesequence);
+                                       
+                                       while ((x = sep.GetToken()) != "")
+                                       {
+                                               if (!z)
+                                               {
+                                                       y[z++] = c->name;
+                                                       items.push_back(c->name);
+                                                       items.push_back(ConvToStr(c->age));
+                                               }
+                                               items.push_back(x);
+                                               y[z++] = (items.end() - 1)->c_str();
+                                       }
+
+                                       DoOneToMany(Instance->Config->ServerName, "FMODE", items);
+                                       userrec* n = new userrec(Instance);
+                                       n->SetFd(FD_MAGIC_NUMBER);
+                                       Instance->SendMode(y,z,n);
+                                       delete n;
+                               }
+                       }
+               }
+               return true;
+       }
+
        bool RemoteServer(std::string prefix, std::deque<std::string> &params)
        {
                if (params.size() < 4)
@@ -3015,6 +3043,10 @@ class TreeSocket : public InspSocket
                                {
                                        return this->MetaData(prefix,params);
                                }
+                               else if (command == "REMSTATUS")
+                               {
+                                       return this->RemoveStatus(prefix,params);
+                               }
                                else if (command == "PING")
                                {
                                        /*
@@ -4463,34 +4495,17 @@ class ModuleSpanningTree : public Module
                // Only do this for local users
                if (IS_LOCAL(user))
                {
-                       char ts[24];
-                       snprintf(ts,24,"%lu",(unsigned long)channel->age);
-
                        std::deque<std::string> params;
                        params.clear();
                        params.push_back(channel->name);
-
-                       /** XXX: The client protocol will IGNORE this parameter.
-                        * We could make use of it if we wanted to keep the TS
-                        * in step if somehow we lose it.
-                        */
-                       params.push_back(ts);
-
-                       if (channel->GetUserCounter() > 1)
-                       {
-                               // not the first in the channel
-                               DoOneToMany(user->nick,"JOIN",params);
-                       }
-                       else
-                       {
-                               // first in the channel, set up their permissions
-                               // and the channel TS with FJOIN.
-                               params.clear();
-                               params.push_back(channel->name);
-                               params.push_back(ts);
-                               params.push_back("@,"+std::string(user->nick));
-                               DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",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.clear();
+                       params.push_back(channel->name);
+                       params.push_back(ConvToStr(channel->age));
+                       params.push_back(std::string(channel->GetAllPrefixChars(user))+","+std::string(user->nick));
+                       DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params);
                }
        }
 
@@ -4789,17 +4804,26 @@ class ModuleSpanningTree : public Module
 
        virtual void OnEvent(Event* event)
        {
+               std::deque<std::string>* params = (std::deque<std::string>*)event->GetData();
+
                if (event->GetEventID() == "send_metadata")
                {
-                       std::deque<std::string>* params = (std::deque<std::string>*)event->GetData();
                        if (params->size() < 3)
                                return;
                        (*params)[2] = ":" + (*params)[2];
                        DoOneToMany(ServerInstance->Config->ServerName,"METADATA",*params);
                }
+               else if (event->GetEventID() == "send_topic")
+               {
+                       if (params->size() < 2)
+                               return;
+                       (*params)[1] = ":" + (*params)[1];
+                       params->insert(params->begin() + 1,ServerInstance->Config->ServerName);
+                       params->insert(params->begin() + 1,ConvToStr(ServerInstance->Time()));
+                       DoOneToMany(ServerInstance->Config->ServerName,"FTOPIC",*params);
+               }
                else if (event->GetEventID() == "send_mode")
                {
-                       std::deque<std::string>* params = (std::deque<std::string>*)event->GetData();
                        if (params->size() < 2)
                                return;
                        // Insert the TS value of the object, either userrec or chanrec