X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree%2Ftreesocket1.cpp;h=5f628a5e8317a505b70d0b9741720338c2144d17;hb=78a1d269f8c5163fdcd88252b77176966e9e882f;hp=31564b017d8488c389532d4e8f3faed404e324ab;hpb=594d923190c5af67533c6ee6a8fd9b2715fbc979;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 31564b017..5f628a5e8 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -35,8 +35,8 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string ho InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); } -TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string host, int port, bool listening, unsigned long maxtime, std::string ServerName, Module* HookMod) - : InspSocket(SI, host, port, listening, maxtime), Utils(Util), Hook(HookMod) +TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string host, int port, bool listening, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Module* HookMod) + : InspSocket(SI, host, port, listening, maxtime, bindto), Utils(Util), Hook(HookMod) { myhost = ServerName; this->LinkState = CONNECTING; @@ -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,122 +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) && (!this->Instance->ULine(source.c_str()))) - { - /* 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 - { - /* The server was ulined, but something iffy is up with the TS. - * Sound the alarm bells! - */ - if ((this->Instance->ULine(sourceserv.c_str())) && (TS > ourTS)) - { - this->Instance->WriteOpers("\2WARNING!\2 U-Lined server '%s' has bad TS for '%s' (accepted change): \2SYNC YOUR CLOCKS\2 to avoid this notice",sourceserv.c_str(),params[0].c_str()); - } - /* 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); @@ -797,7 +539,7 @@ bool TreeSocket::ForceTopic(const std::string &source, std::deque & { std::string oldtopic = c->topic; strlcpy(c->topic,params[3].c_str(),MAXTOPIC); - strlcpy(c->setby,params[2].c_str(),NICKMAX-1); + strlcpy(c->setby,params[2].c_str(),127); c->topicset = ts; /* if the topic text is the same as the current topic, * dont bother to send the TOPIC command out, just silently @@ -981,12 +723,6 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque &p who = this->Instance->FindNick(usr); if (who) { - /* Did they get any modes? How many times? */ - strlcat(modestring, nm, MAXBUF); - for (int k = 0; k < ntimes; k++) - mode_users[modectr++] = strdup(usr); - /* Free temporary buffer used for mode sequence */ - delete[] nm; /* Check that the user's 'direction' is correct * based on the server sending the FJOIN. We must * check each nickname in turn, because the origin of @@ -997,8 +733,23 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque &p if ((!route_back_again) || (route_back_again->GetSocket() != this)) { /* Oh dear oh dear. */ + delete[] nm; continue; } + + /* NOTE: Moved this below the fake direction check, so that modes + * arent put into the mode list for users that were collided, and + * may reconnect from the other side or our side before the split + * is completed! + */ + + /* Did they get any modes? How many times? */ + strlcat(modestring, nm, MAXBUF); + for (int k = 0; k < ntimes; k++) + mode_users[modectr++] = strdup(usr); + /* Free temporary buffer used for mode sequence */ + delete[] nm; + /* Finally, we can actually place the user into the channel. * We're sure its right. Final answer, phone a friend. */ @@ -1054,7 +805,7 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque &p * in case somehow we're desynched, so that other users which might be able to see * the nickname get their fair chance to process it. */ - Instance->Log(SPARSE,"Warning! Invalid user in FJOIN to channel %s IGNORED", channel.c_str()); + Instance->Log(SPARSE,"Warning! Invalid user %s in FJOIN to channel %s IGNORED", usr, channel.c_str()); continue; } } @@ -1247,23 +998,32 @@ void TreeSocket::SendFJoins(TreeServer* Current, chanrec* c) modes.append("+"); } + buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(c->ChanModes(true)).append("\r\n"); + + int linesize = 1; for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++) { - modes.append("b"); - params.append(" ").append(b->data); - if (params.length() >= MAXMODES) + int size = strlen(b->data) + 2; + int currsize = linesize + size; + if (currsize <= 350) + { + modes.append("b"); + params.append(" ").append(b->data); + linesize += size; + } + if ((params.length() >= MAXMODES) || (currsize > 350)) { /* Wrap at MAXMODES */ buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n"); modes = ""; params = ""; + linesize = 1; } } - buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(c->ChanModes(true)); /* Only send these if there are any */ if (!modes.empty()) - buffer.append("\r\n").append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params); + buffer.append(":").append(this->Instance->Config->ServerName).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params); this->WriteLine(buffer); }