From 78a1d269f8c5163fdcd88252b77176966e9e882f Mon Sep 17 00:00:00 2001 From: brain Date: Sat, 10 Mar 2007 17:45:02 +0000 Subject: [PATCH] HIGHLY EXPERIMENTAL: This needs heavy testing -- new FMODE behaviour: (1) IF THEIRTS <= OURTS, ACCEPT MODE AND PASS ON (2) If THEIRTS > OURTS, drop the mode and DONT pass on. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6644 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/modules/m_spanningtree/treesocket1.cpp | 259 +-------------------- 1 file changed, 4 insertions(+), 255 deletions(-) diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index ae972a37e..5f628a5e8 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -500,155 +500,10 @@ bool TreeSocket::ForceMode(const std::string &source, std::deque &p return true; } - /* TS is equal: Merge the mode changes, use voooodoooooo on modes - * with parameters. + /* TS is equal or less: Merge the mode changes into ours and pass on. */ - if (TS == ourTS) + if (TS <= ourTS) { - ModeHandler* mh = NULL; - unsigned long paramptr = 3; - std::string to_bounce = ""; - std::string to_keep = ""; - std::vector params_to_keep; - std::string params_to_bounce = ""; - bool adding = true; - char cur_change = 1; - char old_change = 0; - char old_bounce_change = 0; - /* Merge modes, basically do special stuff to mode with params */ - for (std::string::iterator x = params[2].begin(); x != params[2].end(); x++) - { - switch (*x) - { - case '-': - adding = false; - break; - case '+': - adding = true; - break; - default: - if (adding) - { - /* We only care about whats being set, - * not whats being unset - */ - mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER); - if ((mh) && (mh->GetNumParams(adding) > 0) && (!mh->IsListMode())) - { - /* We only want to do special things to - * modes with parameters, we are going to rewrite - * those parameters - */ - ModePair ret; - adding ? cur_change = '+' : cur_change = '-'; - ret = mh->ModeSet(smode ? NULL : who, dst, chan, params[paramptr]); - /* The mode is set here, check which we should keep */ - if (ret.first) - { - bool which_to_keep = mh->CheckTimeStamp(TS, ourTS, params[paramptr], ret.second, chan); - if (which_to_keep == true) - { - /* Keep ours, bounce theirs: - * Send back ours to them and - * drop their mode changs - */ - adding ? cur_change = '+' : cur_change = '-'; - if (cur_change != old_bounce_change) - to_bounce += cur_change; - to_bounce += *x; - old_bounce_change = cur_change; - if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size())) - params_to_bounce.append(" ").append(ret.second); - } - else - { - /* Keep theirs: Accept their mode change, - * do nothing else - */ - adding ? cur_change = '+' : cur_change = '-'; - if (cur_change != old_change) - to_keep += cur_change; - to_keep += *x; - old_change = cur_change; - if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size())) - params_to_keep.push_back(params[paramptr]); - } - } - else - { - /* Mode isnt set here, we want it */ - adding ? cur_change = '+' : cur_change = '-'; - if (cur_change != old_change) - to_keep += cur_change; - to_keep += *x; - old_change = cur_change; - if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size())) - params_to_keep.push_back(params[paramptr]); - } - paramptr++; - } - else - { - mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER); - if (mh) - { - adding ? cur_change = '+' : cur_change = '-'; - - /* Just keep this, safe to merge with no checks - * it has no parameters - */ - - if (cur_change != old_change) - to_keep += cur_change; - to_keep += *x; - old_change = cur_change; - - if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size())) - { - params_to_keep.push_back(params[paramptr++]); - } - } - } - } - else - { - mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER); - if (mh) - { - /* Taking a mode away */ - adding ? cur_change = '+' : cur_change = '-'; - if (cur_change != old_change) - to_keep += cur_change; - to_keep += *x; - old_change = cur_change; - if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size())) - params_to_keep.push_back(params[paramptr++]); - } - } - break; - } - } - if (to_bounce.length()) - { - std::deque newparams; - newparams.push_back(params[0]); - newparams.push_back(ConvToStr(ourTS)); - newparams.push_back(to_bounce+params_to_bounce); - Utils->DoOneToOne(this->Instance->Config->ServerName,"FMODE",newparams,sourceserv); - } - if (to_keep.length()) - { - unsigned int n = 2; - unsigned int q = 0; - modelist[0] = params[0].c_str(); - modelist[1] = to_keep.c_str(); - if (params_to_keep.size() > 0) - { - for (q = 0; (q < params_to_keep.size()) && (q < 64); q++) - { - modelist[n++] = params_to_keep[q].c_str(); - } - } if (smode) { this->Instance->SendMode(modelist, n, who); @@ -661,115 +516,9 @@ bool TreeSocket::ForceMode(const std::string &source, std::deque &p Utils->DoOneToAllButSender(source,"FMODE",params,sourceserv); } } - else - /* U-lined servers always win regardless of their TS */ - if (TS > ourTS) - { - /* Bounce the mode back to its sender.* We use our lower TS, so the other end - * SHOULD accept it, if its clock is right. - * - * NOTE: We should check that we arent bouncing anything thats already set at this end. - * If we are, bounce +ourmode to 'reinforce' it. This prevents desyncs. - * e.g. They send +l 50, we have +l 10 set. rather than bounce -l 50, we bounce +l 10. - * - * Thanks to jilles for pointing out this one-hell-of-an-issue before i even finished - * writing the code. It took me a while to come up with this solution. - * - * XXX: BE SURE YOU UNDERSTAND THIS CODE FULLY BEFORE YOU MESS WITH IT. - */ - std::deque newparams; /* New parameter list we send back */ - newparams.push_back(params[0]); /* Target, user or channel */ - newparams.push_back(ConvToStr(ourTS)); /* Timestamp value of the target */ - newparams.push_back(""); /* This contains the mode string. For now - * it's empty, we fill it below. - */ - /* Intelligent mode bouncing. Don't just invert, reinforce any modes which are already - * set to avoid a desync here. - */ - std::string modebounce = ""; - bool adding = true; - unsigned int t = 3; - ModeHandler* mh = NULL; - char cur_change = 1; - char old_change = 0; - for (std::string::iterator x = params[2].begin(); x != params[2].end(); x++) - { - /* Iterate over all mode chars in the sent set */ - switch (*x) - { - /* Adding or subtracting modes? */ - case '-': - adding = false; - break; - case '+': - adding = true; - break; - default: - /* Find the mode handler for this mode */ - mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER); - /* Got a mode handler? - * This also prevents us bouncing modes we have no handler for. - */ - if (mh) - { - ModePair ret; - std::string p = ""; - /* Does the mode require a parameter right now? - * If it does, fetch it if we can - */ - if ((mh->GetNumParams(adding) > 0) && (t < params.size())) - p = params[t++]; - /* Call the ModeSet method to determine if its set with the - * given parameter here or not. - */ - ret = mh->ModeSet(smode ? NULL : who, dst, chan, p); - /* XXX: Really. Dont ask. - * Determine from if its set combined with what the current - * 'state' is (adding or not) as to wether we should 'invert' - * or 'reinforce' the mode change - */ - (!ret.first ? (adding ? cur_change = '-' : cur_change = '+') : (!adding ? cur_change = '-' : cur_change = '+')); - /* Quickly determine if we have 'flipped' from + to -, - * or - to +, to prevent unneccessary +/- chars in the - * output string that waste bandwidth - */ - if (cur_change != old_change) - modebounce += cur_change; - old_change = cur_change; - /* Add the mode character to the output string */ - modebounce += mh->GetModeChar(); - /* We got a parameter back from ModeHandler::ModeSet, - * are we supposed to be sending one out right now? - */ - if (ret.second.length()) - { - if (mh->GetNumParams(cur_change == '+') > 0) - /* Yes we're supposed to be sending out - * the parameter. Make sure it goes - */ - newparams.push_back(ret.second); - } - } - break; - } - } + /* If the TS is greater than ours, we drop the mode and dont pass it anywhere. + */ - /* Update the parameters for FMODE with the new 'bounced' string */ - newparams[2] = modebounce; - /* Only send it back the way it came, no need to send it anywhere else */ - Utils->DoOneToOne(this->Instance->Config->ServerName,"FMODE",newparams,sourceserv); - } - else - { - /* Allow the mode, route it to either server or user command handling */ - if (smode) - this->Instance->SendMode(modelist,n,who); - else - this->Instance->CallCommandHandler("MODE", modelist, n, who); - /* HOT POTATO! PASS IT ON! */ - Utils->DoOneToAllButSender(source,"FMODE",params,sourceserv); - } - /* Are we supposed to free the userrec? */ if (smode) DELETE(who); -- 2.39.2