X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree%2Ftreesocket1.cpp;h=5809fb6b82c50750738e972ae25eaae63d5b31bc;hb=ed31c3ee4a7b5f59465457ba353642d46d86a8b2;hp=a0eb6ad7fd211dfe08f772d67afb50c68d6758a4;hpb=0ba4b96bbaf1ef385fda088be6e02f93d1b03904;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index a0eb6ad7f..5809fb6b8 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -958,24 +958,83 @@ bool TreeSocket::ParseUID(const std::string &source, std::deque &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);