X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmodules%2Fm_spanningtree%2Ftreesocket1.cpp;h=748a44b45d76fd4cb99d6b51cf6b3bf4bf6cd0ea;hb=e6d000042ea75d4e0485bec9564b47163a3ca414;hp=9c53a16cdb8ec2de9e0824773d12151de4f277b6;hpb=66d187fa55b4fdcb38ec987c269c4c1573a441b5;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 9c53a16cd..748a44b45 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -12,10 +12,6 @@ */ #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 &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 &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 &p { std::deque 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 &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 ¶ms) { /** Do we have enough parameters: @@ -965,77 +1056,13 @@ bool TreeSocket::ParseUID(const std::string &source, std::deque &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(); } }