Commits

Anonymous committed 15b59ec

[svn] Port over ratbox 2.2 r23507, r23624, r23626 (jilles/anfl):
Change TS6 JOIN processing
- don't send out simple modes in TS6 JOIN and TS5 SJOIN when
a local user joins an existing channel
- don't send out simple modes in TS6 JOIN and TS5 SJOIN when
propagating a TS6 JOIN
- don't interpret simple modes in an incoming TS6 JOIN

This is to avoid desyncs when certain mode changes (e.g. -im)
cross with joins. A downside is that simple modes will be
more desynched when a JOIN creates a channel or lowers TS,
but that's less important.

Update the TS6 specification to include this, and clarify
that TMODE can come from a server and that MODE must be
translated into TMODE from other servers too.

  • Participants
  • Parent commits 9607785

Comments (0)

Files changed (4)

+jilles      2007/02/11 16:54:43 UTC	(20070211-3209)
+  Log:
+  Make -logfile work again.
+  
+
+  Changes:	Modified:
+  +2 -2		trunk/src/s_log.c (File Modified) 
+
+
 nenolod     2007/02/09 22:18:23 UTC	(20070209-3205)
   Log:
   - fix off-by-one memory overflow error.

File doc/technical/ts6.txt

-$Id: ts6.txt 6 2005-09-10 01:02:21Z nenolod $
+$Id: ts6.txt 3211 2007-02-20 00:34:28Z jilles $
 
-TS6 Proposal (v7)
+TS6 Proposal (v8)
 Written by Lee H <lee@leeh.co.uk>
 Ideas borrowed heavily from ircnet (Beeth, jv, Q)
 
-Introduction
-------------
+- Changes between v7 and v8 -
+-----------------------------
+
+In the v7 specification, the JOIN command included the channel modes of a
+channel, and acted on them following TS rules.  In the v8 specification,
+JOIN will never send modes.
+
+Desyncs can occur both when they are sent and when they are not.  If they
+are sent, then you can have a situation where a user on one side of the
+network issues "MODE #channel -l", and a user on another side of the network
+issues "JOIN #channel" whilst the +l still exists.  As the JOIN string sent 
+server<->server includes the full modes at the time of the user joining, 
+this will propagate the +l, but there is a -l crossing in the other
+direction.  Desync will occur beyond where they intersect.
+
+If the modes are not sent, then a lower TS JOIN command, or a JOIN command
+that creates a channel will cause a desync.
+
+It is judged that the desync with sending the modes is worse than the desync
+by not sending them, as such the v8 specification dictates modes are not
+sent with a JOIN command server<->server.
+
+The v8 specification also clarifies that servers may issue TMODE.
+
+- Introduction -
+----------------
 
 This document aims to fix some of the flaws that are still present in the
 current TS system.
 we are bursting to.
 
 
-Definitions
------------
+- Definitions -
+---------------
 
 Throughout this document, the following terms are used:
 
 TS6     - The TS version 6.
 
 
-Support
--------
+- Support -
+-----------
 
 Support for this document is given by the TS version 6.
 
 The TS6 protocol does not supports masked entities.
 
 
-Nick TS rules
--------------
+- Nick TS rules -
+-----------------
 
 A server receiving a command that requires nick TS rules must check for a
 collision between an existing user, and the nick in the received message.
 message.
 
 
-Nick TS collisions
-------------------
+- Nick TS collisions -
+----------------------
 
 If both users are to be collided, we must issue a KILL for the existing 
 user to all servers.  If the new user has a UID then we must also issue a 
 back to the server sending us data if the new user has a UID.
 
 
-Channel TS rules
-----------------
+- Channel TS rules -
+--------------------
 
 A server receiving a command that requires normal channel TS rules must 
 apply the following rules to the command.
 ignore any "MODE" commands from a user marked as 'deopped'.
 
 
-Simple channel TS rules
------------------------
+- Simple channel TS rules -
+---------------------------
 
 A server receiving a command that requires simple channel TS rules must
 apply the following rules to the command.
 for the modes we are accepting.
 
 
-The following commands are defined here as the TS6 protocol
------------------------------------------------------------
+- The following commands are defined here as the TS6 protocol -
+---------------------------------------------------------------
 
-PASS:
-PASS <PASSWORD> TS <TS_CURRENT> :<SID>
+- PASS -
+	PASS <PASSWORD> TS <TS_CURRENT> :<SID>
 
 This command is used for password verification with the server we are
 connecting to.
 <TS_CURRENT> is our current TS version.  If this field is not present then
 the server does not support TS6.  <SID> is the SID of the server.
 
-UID:
-:<SID> UID <NICK> <HOPS> <TS> +<UMODE> <USERNAME> <HOSTNAME> <IP> <UID> :<GECOS>
+- UID -
+	:<SID> UID <NICK> <HOPS> <TS> +<UMODE> <USERNAME> <HOSTNAME> <IP> <UID> :<GECOS>
 
 This command is used for introducing clients to the network.
 
 
 A server receiving a UID command must apply nick TS rules to the nick.
 
-SID:
-:<SID> SID <SERVERNAME> <HOPS> <SID> :<GECOS>
+- SID -
+	:<SID> SID <SERVERNAME> <HOPS> <SID> :<GECOS>
 
 This command is used for introducing servers to the network.
 
 Client and servers which do not have a UID/SID must be introduced by old
 methods.
 
-SJOIN:
-:<SID> SJOIN <TS> <CHANNAME> +<CHANMODES> :<UIDS>
+- SJOIN -
+	:<SID> SJOIN <TS> <CHANNAME> +<CHANMODES> :<UIDS>
 
 This command is used for introducing users to channels.
 
 use the "JOIN" command defined in this specification.  A TS6 server must
 still use SJOIN for creating channels.
 
-JOIN:
-:<UID> JOIN <TS> <CHANNAME> +<CHANMODES>
+- JOIN -
+	:<UID> JOIN <TS> <CHANNAME> +
 
 This command is used for introducing one user unopped to an existing channel.
 
 The <UID> field is the UID of the client joining the channel.  The
 <TS> field is the channels current TS, <CHANNAME> is the channels
-current name, <CHANMODES> are the channels current modes.
+current name.
 
 A server receiving a JOIN must apply normal channel TS rules to the JOIN.
 
+No channel modes are sent with the JOIN command.  In previous versions of
+this specification, the "+" parameter contained the channels current modes.
+A server following this version of the specification must not interpret this
+argument and must not propagate any value other than "+" for this parameter.
+
 It should be noted that whilst JOIN would not normally create a 
-channel, during specific race conditions it can.  This can create
-a ban desync that this specification does not rectify.
+channel or lower the timestamp, during specific conditions it can.  This 
+can create a desync that this specification does not rectify.
 
-BMASK:
-:<SID> BMASK <TS> <CHANNAME> <TYPE> :<MASKS>
+- BMASK -
+	:<SID> BMASK <TS> <CHANNAME> <TYPE> :<MASKS>
 
 This command is used for bursting channel bans to a network.
 
 not be possible without a desync, due to it being sent after
 SJOIN.
 
-TMODE:
-:<UID> TMODE <TS> <CHANNAME> <MODESTRING>
+- TMODE -
+	:<SID|UID> TMODE <TS> <CHANNAME> <MODESTRING>
 
 This command is used for clients issuing modes on a channel.
 
-<UID> is the UID of the client setting the mode.  <TS> is the
-current TS of the channel, <CHANNAME> is the channels name.
-<MODESTRING> is the raw mode the client is setting.
+<SID|UID> is either the UID of the client setting the mode, or the SID of
+the server setting the mode.  <TS> is the current TS of the channel, 
+<CHANNAME> is the channels name. <MODESTRING> is the raw mode the client is 
+setting.
 
 A server receiving a TMODE must apply simple channel TS rules to the TMODE.
 
-A TS6 server must translate MODEs issued by a local client into TMODE 
-to send to other TS6 capable servers.
+A TS6 server must translate MODEs issued by a local client, or received from
+a server into TMODE to send to other TS6 capable servers.
 

File include/serno.h

-#define SERNO "20070209-3205"
+#define SERNO "20070211-3209"

File modules/core/m_join.c

  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  *  USA
  *
- *  $Id: m_join.c 3173 2007-01-31 23:57:18Z jilles $
+ *  $Id: m_join.c 3211 2007-02-20 00:34:28Z jilles $
  */
 
 #include "stdinc.h"
 	{ NULL, NULL },
 };
 
-DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3173 $");
+DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3211 $");
 
 static void do_join_0(struct Client *client_p, struct Client *source_p);
 static int check_channel_name_loc(struct Client *source_p, const char *name);
 		}
 		else
 		{
-			const char *modes = channel_modes(chptr, &me);
-
 			sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
-				      ":%s JOIN %ld %s %s",
+				      ":%s JOIN %ld %s +",
 				      use_id(source_p), (long) chptr->channelts,
-				      chptr->chname, modes);
+				      chptr->chname);
 
 			sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
-				      ":%s SJOIN %ld %s %s :%s",
+				      ":%s SJOIN %ld %s + :%s",
 				      me.name, (long) chptr->channelts,
-				      chptr->chname, modes, source_p->name);
+				      chptr->chname, source_p->name);
 		}
 
 		del_invite(chptr, source_p);
 ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
 	struct Channel *chptr;
-	static struct Mode mode, *oldmode;
-	const char *s;
-	const char *modes;
+	static struct Mode mode;
 	time_t oldts;
 	time_t newts;
 	int isnew;
-	int args = 0;
 	int keep_our_modes = YES;
 	int keep_new_modes = YES;
 	dlink_node *ptr, *next_ptr;
 	mode.key[0] = mode.forward[0] = '\0';
 	mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
 
-	s = parv[3];
-	while(*s)
-	{
-		switch (*(s++))
-		{
-		case 'i':
-			mode.mode |= MODE_INVITEONLY;
-			break;
-		case 'n':
-			mode.mode |= MODE_NOPRIVMSGS;
-			break;
-		case 'p':
-			mode.mode |= MODE_PRIVATE;
-			break;
-		case 's':
-			mode.mode |= MODE_SECRET;
-			break;
-		case 'm':
-			mode.mode |= MODE_MODERATED;
-			break;
-		case 't':
-			mode.mode |= MODE_TOPICLIMIT;
-			break;
-		case 'r':
-			mode.mode |= MODE_REGONLY;
-			break;
-		case 'L':
-			mode.mode |= MODE_EXLIMIT;
-			break;
-		case 'P':
-			mode.mode |= MODE_PERMANENT;
-			break;
-		case 'c':
-			mode.mode |= MODE_NOCOLOR;
-			break;
-		case 'g':
-			mode.mode |= MODE_FREEINVITE;
-			break;
-		case 'z':
-			mode.mode |= MODE_OPMODERATE;
-			break;
-		case 'F':
-			mode.mode |= MODE_FREETARGET;
-			break;
-		case 'Q':
-			mode.mode |= MODE_DISFORWARD;
-			break;
-		case 'f':
-			if(parc < 5 + args)
-				return 0;
-			strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
-			args++;
-			break;
-		case 'j':
-			/* sent a +j without an arg. */
-			if(parc < 5 + args)
-				return 0;
-			sscanf(parv[4 + args], "%d:%d", &mode.join_num, &mode.join_time);
-			args++;
-			break;
-		case 'k':
-			/* sent a +k without a key, eek. */
-			if(parc < 5 + args)
-				return 0;
-			strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
-			args++;
-			break;
-		case 'l':
-			/* sent a +l without a limit. */
-			if(parc < 5 + args)
-				return 0;
-			mode.limit = atoi(parv[4 + args]);
-			args++;
-			break;
-		}
-	}
-
 	if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
 		return 0;
 
 	newts = atol(parv[1]);
 	oldts = chptr->channelts;
-	oldmode = &chptr->mode;
 
 #ifdef IGNORE_BOGUS_TS
 	if(newts < 800000000)
 	else
 		keep_new_modes = NO;
 
-	if(!keep_new_modes)
-		mode = *oldmode;
-	else if(keep_our_modes)
-	{
-		mode.mode |= oldmode->mode;
-		if(oldmode->limit > mode.limit)
-			mode.limit = oldmode->limit;
-		if(strcmp(mode.key, oldmode->key) < 0)
-			strcpy(mode.key, oldmode->key);
-		if(oldmode->join_num > mode.join_num ||
-				(oldmode->join_num == mode.join_num &&
-				 oldmode->join_time > mode.join_time))
-		{
-			mode.join_num = oldmode->join_num;
-			mode.join_time = oldmode->join_time;
-		}
-		if(irccmp(mode.forward, oldmode->forward) < 0)
-			strcpy(mode.forward, oldmode->forward);
-	}
-	else
-	{
-		/* If setting -j, clear join throttle state -- jilles */
-		if (!mode.join_num)
-			chptr->join_count = chptr->join_delta = 0;
-	}
-
-	set_final_mode(&mode, oldmode);
-	chptr->mode = mode;
-
 	/* Lost the TS, other side wins, so remove modes on this side */
 	if(!keep_our_modes)
 	{
+		set_final_mode(&mode, &chptr->mode);
+		chptr->mode = mode;
 		remove_our_modes(chptr, source_p);
 		DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
 		{
 			del_invite(chptr, ptr->data);
 		}
+		/* If setting -j, clear join throttle state -- jilles */
+		chptr->join_count = chptr->join_delta = 0;
 		sendto_channel_local(ALL_MEMBERS, chptr,
 				     ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
 				     me.name, chptr->chname, chptr->chname,
 				     (long) oldts, (long) newts);
+		if(*modebuf != '\0')
+			sendto_channel_local(ALL_MEMBERS, chptr,
+					     ":%s MODE %s %s %s",
+					     source_p->servptr->name,
+					     chptr->chname, modebuf, parabuf);
+		*modebuf = *parabuf = '\0';
 	}
 
-	if(*modebuf != '\0')
-		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
-				     source_p->user->server, chptr->chname, modebuf, parabuf);
-
-	*modebuf = *parabuf = '\0';
-
 	if(!IsMember(source_p, chptr))
 	{
 		add_user_to_channel(chptr, source_p, CHFL_PEON);
 				     source_p->host, chptr->chname);
 	}
 
-	modes = channel_modes(chptr, client_p);
 	sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
-		      ":%s JOIN %ld %s %s",
-		      source_p->id, (long) chptr->channelts, chptr->chname, modes);
+		      ":%s JOIN %ld %s +",
+		      source_p->id, (long) chptr->channelts, chptr->chname);
 	sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
 		      ":%s SJOIN %ld %s %s :%s",
 		      source_p->user->server, (long) chptr->channelts,
-		      chptr->chname, modes, source_p->name);
+		      chptr->chname, keep_new_modes ? "+" : "0",
+		      source_p->name);
 	return 0;
 }