-
- }
- return true;
-}
-
-/** FJOIN, similar to TS6 SJOIN, but not quite. */
-bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> ¶ms)
-{
- /* 1.1 FJOIN works as follows:
- *
- * Each FJOIN is sent along with a timestamp, and the side with the lowest
- * timestamp 'wins'. From this point on we will refer to this side as the
- * winner. The side with the higher timestamp loses, from this point on we
- * will call this side the loser or losing side. This should be familiar to
- * anyone who's dealt with dreamforge or TS6 before.
- *
- * When two sides of a split heal and this occurs, the following things
- * will happen:
- *
- * If the timestamps are exactly equal, both sides merge their privilages
- * and users, as in InspIRCd 1.0 and ircd2.8. The channels have not been
- * re-created during a split, this is safe to do.
- *
- *
- * If the timestamps are NOT equal, the losing side removes all privilage
- * modes from all of its users that currently exist in the channel, before
- * introducing new users into the channel which are listed in the FJOIN
- * command's parameters. This means, all modes +ohv, and privilages added
- * by modules, such as +qa. The losing side then LOWERS its timestamp value
- * of the channel to match that of the winning side, and the modes of the
- * users of the winning side are merged in with the losing side. The loser
- * then sends out a set of FMODE commands which 'confirm' that it just
- * removed all privilage modes from its existing users, which allows for
- * services packages to still work correctly without needing to know the
- * timestamping rules which InspIRCd follows. In TS6 servers this is always
- * a problem, and services packages must contain code which explicitly
- * behaves as TS6 does, removing ops from the losing side of a split where
- * neccessary within its internal records, as this state information is
- * not explicitly echoed out in that protocol.
- *
- * The winning side on the other hand will ignore all user modes from the
- * losing side, so only its own modes get applied. Life is simple for those
- * who succeed at internets. :-)
- *
- * NOTE: Unlike TS6 and dreamforge and other protocols which have SJOIN,
- * FJOIN does not contain the simple-modes such as +iklmnsp. Why not,
- * you ask? Well, quite simply because we don't need to. They'll be sent
- * after the FJOIN by FMODE, and FMODE is timestamped, so in the event
- * the losing side sends any modes for the channel which shouldnt win,
- * they wont as their timestamp will be too high :-)
- */
-
- if (params.size() < 3)
- return true;
-
- char first[MAXBUF]; /* The first parameter of the mode command */
- char modestring[MAXBUF]; /* The mode sequence (2nd parameter) of the mode command */
- char* mode_users[127]; /* The values used by the mode command */
- memset(&mode_users,0,sizeof(mode_users)); /* Initialize mode parameters */
- mode_users[0] = first; /* Set this up to be our on-stack value */
- mode_users[1] = modestring; /* Same here as above */
- strcpy(modestring,"+"); /* Initialize the mode sequence to just '+' */
- unsigned int modectr = 2; /* Pointer to the third mode parameter (e.g. the one after the +-sequence) */
-
- userrec* who = NULL; /* User we are currently checking */
- std::string channel = params[0]; /* Channel name, as a string */
- time_t TS = atoi(params[1].c_str()); /* Timestamp given to us for remote side */
- std::string nicklist = params[2];
- bool created = false;
-
- /* Try and find the channel */
- chanrec* chan = this->Instance->FindChan(channel);
-
- /* Initialize channel name in the mode parameters */
- strlcpy(mode_users[0],channel.c_str(),MAXBUF);
-
- /* default TS is a high value, which if we dont have this
- * channel will let the other side apply their modes.
- */
- time_t ourTS = Instance->Time(true)+600;
- /* Does this channel exist? if it does, get its REAL timestamp */
- if (chan)
- ourTS = chan->age;
- else
- created = true; /* don't perform deops, and set TS to correct time after processing. */
-
- /* do this first, so our mode reversals are correctly received by other servers
- * if there is a TS collision.
- */
- params[2] = ":" + params[2];
- Utils->DoOneToAllButSender(source,"FJOIN",params,source);
-
- /* In 1.1, if they have the newer channel, we immediately clear
- * all status modes from our users. We then accept their modes.
- * If WE have the newer channel its the other side's job to do this.
- * Note that this causes the losing server to send out confirming
- * FMODE lines.
- */
- if (ourTS > TS)
- {
- std::deque<std::string> param_list;
- /* Lower the TS here */
- if (Utils->AnnounceTSChange && chan)
- chan->WriteChannelWithServ(Instance->Config->ServerName,
- "NOTICE %s :TS for %s changed from %lu to %lu", chan->name, chan->name, ourTS, TS);
- ourTS = TS;
- /* Zap all the privilage modes on our side, if the channel exists here */
- if (!created)