]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/treesocket1.cpp
Remove unneeded headers from spanningtree. This was done to the rest of the source...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treesocket1.cpp
index 9c53a16cdb8ec2de9e0824773d12151de4f277b6..748a44b45d76fd4cb99d6b51cf6b3bf4bf6cd0ea 100644 (file)
  */
 
 #include "inspircd.h"
-#include "configreader.h"
-#include "users.h"
-#include "channels.h"
-#include "modules.h"
 #include "commands/cmd_whois.h"
 #include "commands/cmd_stats.h"
 #include "socket.h"
@@ -640,9 +636,8 @@ bool TreeSocket::ForceMode(const std::string &source, std::deque<std::string> &p
        }
        else
        {
-               /* FMODE from a server, create a fake user to receive mode feedback */
-               who = new userrec(this->Instance);
-               who->SetFd(FD_MAGIC_NUMBER);
+               /* FMODE from a server, use a fake user to receive mode feedback */
+               who = this->Instance->FakeClient;
                smode = true;      /* Setting this flag tells us we should free the userrec later */
                sourceserv = source;    /* Set sourceserv to the actual source string */
        }
@@ -714,10 +709,6 @@ bool TreeSocket::ForceMode(const std::string &source, std::deque<std::string> &p
        }
        /* If the TS is greater than ours, we drop the mode and dont pass it anywhere.
         */
-
-       if (smode)
-               DELETE(who);
-
        return true;
 }
 
@@ -896,8 +887,6 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
        {
                std::deque<std::string> stackresult;
                const char* mode_junk[MAXMODES+2];
-               userrec* n = new userrec(Instance);
-               n->SetFd(FD_MAGIC_NUMBER);
                mode_junk[0] = channel.c_str();
 
                while (modestack.GetStackedLine(stackresult))
@@ -906,15 +895,117 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
                        {
                                mode_junk[j+1] = stackresult[j].c_str();
                        }
-                       Instance->SendMode(mode_junk, stackresult.size() + 1, n);
+                       Instance->SendMode(mode_junk, stackresult.size() + 1, Instance->FakeClient);
                }
-
-               delete n;
        }
 
        return true;
 }
 
+/*
+ * Yes, this function looks a little ugly.
+ * However, in some circumstances we may not have a userrec, so we need to do things this way.
+ * Returns 1 if colliding local client, 2 if colliding remote, 3 if colliding both.
+ * Sends SVSNICKs as appropriate and forces nickchanges too.
+ */
+int TreeSocket::DoCollision(userrec *u, time_t remotets, const char *remoteident, const char *remoteip, const char *remoteuid)
+{
+       /*
+        *  Under old protocol rules, we would have had to kill both clients.
+        *  Really, this sucks.
+        * These days, we have UID. And, so what we do is, force nick change client(s)
+        * involved according to timestamp rules.
+        *
+        * RULES:        
+        *  user@ip equal:       
+        *   Force nick change on OLDER timestamped client       
+        *  user@ip differ:      
+        *   Force nick change on NEWER timestamped client       
+        *  TS EQUAL:    
+        *   FNC both.   
+        *       
+        * This stops abusive use of collisions, simplifies problems with loops, and so on.      
+        *   -- w00t
+        */
+       bool bChangeLocal = true;
+       bool bChangeRemote = true;
+
+       /* for brevity, don't use the userrec */
+       time_t localts = u->age;
+       const char *localident = u->ident;
+       const char *localip = u->GetIPString();
+
+       /* mmk. let's do this again. */
+       if (remotets == localts)
+       {
+               /* equal. fuck them both! do nada, let the handler at the bottom figure this out. */
+       }
+       else
+       {
+               /* fuck. now it gets complex. */
+
+               /* first, let's see if ident@host matches. */
+               bool SamePerson = strcmp(localident, remoteident)
+                               && !strcmp(localip, remoteip);
+
+               /*
+                * if ident@ip is equal, and theirs is newer, or
+                * ident@ip differ, and ours is newer
+                */
+               if((SamePerson && remotets < localts) ||
+                  (!SamePerson && remotets > localts))
+               {
+                       /* remote needs to change */
+                       bChangeLocal = false;
+               }
+               else
+               {
+                       /* ours needs to change */
+                       bChangeRemote = false;
+               }
+       }
+
+
+       if (bChangeLocal)
+       {
+               u->ForceNickChange(u->uuid);
+
+               if (!bChangeRemote)
+                       return 1;
+       }
+       if (bChangeRemote)
+       {
+               /*
+                * Cheat a little here. Instead of a dedicated command to change UID,
+                * use SVSNICK and accept their client with it's UID (as we know the SVSNICK will
+                * not fail under any circumstances -- UIDs are netwide exclusive).
+                *
+                * This means that each side of a collide will generate one extra NICK back to where
+                * they have just linked (and where it got the SVSNICK from), however, it will
+                * be dropped harmlessly as it will come in as :928AAAB NICK 928AAAB, and we already
+                * have 928AAAB's nick set to that.
+                *   -- w00t
+                */
+               userrec *remote = this->Instance->FindUUID(remoteuid);
+
+               if (remote)
+               {
+                       /* buh.. nick change collide. force change their nick. */
+                       remote->ForceNickChange(remote->uuid);
+               }
+               else
+               {
+                       /* user has not been introduced yet, just inform their server */
+                       this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" SVSNICK "+remoteuid+" " + remoteuid);
+               }
+
+               if (!bChangeRemote)
+                       return 2;
+       }
+
+       return 3;
+}
+
 bool TreeSocket::ParseUID(const std::string &source, std::deque<std::string> &params)
 {
        /** Do we have enough parameters:
@@ -965,77 +1056,13 @@ bool TreeSocket::ParseUID(const std::string &source, std::deque<std::string> &pa
        {
                /*
                 * Nick collision.
-                *  Under old protocol rules, we would have had to kill both clients.
-                *  Really, this sucks.
-                * These days, we have UID. And, so what we do is, force nick change client(s)
-                * involved according to timestamp rules.
-                *
-                * RULES:        
-                *  user@ip equal:       
-                *   Force nick change on OLDER timestamped client       
-                *  user@ip differ:      
-                *   Force nick change on NEWER timestamped client       
-                *  TS EQUAL:    
-                *   FNC both.   
-                *       
-                * This stops abusive use of collisions, simplifies problems with loops, and so on.      
-                *   -- w00t
                 */
                Instance->Log(DEBUG,"*** Collision on %s", tempnick);
+               int collide = this->DoCollision(iter->second, age, params[5].c_str(), params[7].c_str(), params[0].c_str());
 
-               bool bChangeLocal = true;
-               bool bChangeRemote = true;
-
-               /* mmk. let's do this again. */
-               if (age == iter->second->age)
-               {
-                       /* equal. fuck them both! do nada, let the handler at the bottom figure this out. */
-               }
-               else
-               {
-                       /* fuck. now it gets complex. */
-
-                       /* first, let's see if ident@host matches. */
-                       bool SamePerson = strcmp(iter->second->ident, params[5].c_str())
-                                       && !strcmp(iter->second->GetIPString(), params[7].c_str());
-
-                       /*
-                        * if ident@ip is equal, and theirs is newer, or
-                        * ident@ip differ, and ours is newer
-                        */
-                       if((SamePerson && age < iter->second->age) ||
-                          (!SamePerson && age > iter->second->age))
-                       {
-                               /* remote needs to change */
-                               bChangeLocal = false;
-                       }
-                       else
-                       {
-                               /* ours needs to change */
-                               bChangeRemote = false;
-                       }
-               }
-
-
-               if (bChangeLocal)
-               {
-                       iter->second->ForceNickChange(iter->second->uuid);
-               }
-               if (bChangeRemote)
+               if (collide == 2)
                {
-                       /*
-                        * Cheat a little here. Instead of a dedicated command to change UID,
-                        * use SVSNICK and accept their client with it's UID (as we know the SVSNICK will
-                        * not fail under any circumstances -- UIDs are netwide exclusive).
-                        *
-                        * This means that each side of a collide will generate one extra NICK back to where
-                        * they have just linked (and where it got the SVSNICK from), however, it will
-                        * be dropped harmlessly as it will come in as :928AAAB NICK 928AAAB, and we already
-                        * have 928AAAB's nick set to that.
-                        *   -- w00t
-                        */
-                       this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" SVSNICK "+params[0]+" " + params[0]);
-                       /* also, don't trample on the hash - use their UID as nick */
+                       /* remote client changed, make sure we change their nick for the hash too */
                        tempnick = params[0].c_str();
                }
        }