]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/treesocket1.cpp
Nick collision handling with TS rules. This probably doesn't work yet.
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treesocket1.cpp
index a0eb6ad7fd211dfe08f772d67afb50c68d6758a4..5809fb6b82c50750738e972ae25eaae63d5b31bc 100644 (file)
@@ -958,24 +958,83 @@ bool TreeSocket::ParseUID(const std::string &source, std::deque<std::string> &pa
                }
        }
 
-       /** Our client looks ok, lets introduce it now
-        */
-       Instance->Log(DEBUG,"New remote client %s", tempnick);
+
+       /* check for collision */
        user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
 
        if (iter != this->Instance->clientlist->end())
        {
                /*
-                * Uh oh, nick collision. Under old rules, we'd kill both. These days now we have UUID,
-                * we force both clients to change nick to their UUID. Just change ours, and the other
-                * server will change theirs when they see the collide. Problem solved! -- w00t
+                * 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.
+                *
+                * Note that remote clients MUST be dealt with also to remove desyncs.
+                *  XXX we don't do this yet.
+                *
+                * This stops abusive use of collisions, simplifies problems with loops, and so on.
+                *   -- w00t
                 */
-               iter->second->ForceNickChange(iter->second->uuid);
+               Instance->Log(DEBUG,"*** Collision on %s", tempnick);
+
+               if (age == iter->second->signon)
+               {
+                       /* TS equal, do both */
+                       Instance->Log(DEBUG,"*** TS EQUAL, colliding both");
+                       iter->second->ForceNickChange(iter->second->uuid);
+                       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 */
+                       tempnick = params[0].c_str();
+               }
+               else
+               {
+                       /* default to FNC newer (more likely that ident@ip will differ) */
+                       bool bFNCNewer = true;
 
-               /* also reassign tempnick so we don't trample the hash - important! */
-               tempnick = params[0].c_str();
+                       if (
+                               strcmp(iter->second->ident, params[5].c_str()) == 0 &&
+                               strcmp(iter->second->GetIPString(), params[7].c_str()) == 0
+                          )
+                       {
+                               /* ident@ip same, FNC older client */
+                               bFNCNewer = false;
+                       }
+
+                       if (age > iter->second->signon) /* It will never be equal here */
+                       {
+                               if (bFNCNewer)
+                               {
+                                       /* incoming client "lost" - for now, send SVSNICK to them .. XXX use SAVE*/
+                                       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 */
+                                       tempnick = params[0].c_str();
+                                       Instance->Log(DEBUG,"*** INCOMING client lost, changed theirs");
+                               }
+                               else
+                               {
+                                       /* we "lost", change us */
+                                       iter->second->ForceNickChange(iter->second->uuid);
+                                       Instance->Log(DEBUG,"*** OUR client lost, changing ours");
+                               }
+                       }
+               }
        }
 
+       /* IMPORTANT NOTE: For remote users, we pass the UUID in the constructor. This automatically
+        * sets it up in the UUID hash for us.
+        * TODO: Make this throw an exception maybe, on UUID collision?
+        */
        userrec* _new = new userrec(this->Instance, params[0]);
        (*(this->Instance->clientlist))[tempnick] = _new;
        _new->SetFd(FD_MAGIC_NUMBER);