Andrew Miller wrote:

>Progs wrote:
>
>  
>
>>Hi,
>>
>>If I have two servers, AA and AB, with AAAAA and ABAAA on #foo, a +D channel.
>>AAAAA is delayed on #foo and ABAAA is +d.
>>There are only AAAAA and ABAAA in #foo.
>>When AAAAA speaks on #foo, ABAAA is +d so AB doesn't receive message, so 
>>ABAAA doesn't see AAAAA's join.
>>
>>Bug or feature ?:)
>>
>This could be used to build a map of the network and determine where the
>hubs are. Anything which breaks HIS that bad is a bug.
>
>There are several fixes:
>Fix A: We need to globally synchronise delayed state, which means that
>we need to transmit it in BURST. We can then apply the "don't propagate
>WASDELAYED" because we can track delayed state in each server. Finally,
>if a message causes RevealDelayed, it should propagate to all servers,
>not just those with non-deaf members on the channel.
>
>Fix B: Deaf users can't join +D or +d channels, and users in +D or + d
>channels can't become deaf.
>
>Fix C: Deaf users joining a +D or +d channel force a full reveal to
>everyone on that server(I think we can rule this one out)
>
>Fix D: Deaf users joining a +D or +d channel can see everyone, and can't
>set -d usermode(to prevent seeing the same join twice, when
>RevealDelayed is called) while in channel.
>
>Fix E: Deaf users joining +D or +d channel get a full reveal, and if
>they set -d, we set WASDEAF on all +D or +d channels they are in. Users
>with Deaf usermode or WASDEAF status in the channel do not see messages
>sent by RevealDelayed as they have already seen them earlier. They do
>see parts for delayed users.
>
>How many users set -d once they are connected anyway? Probably not many,
>so fix D might be reasonable. Fix A requires a server protocol
>change(and costs extra bandwidth on burst). In the light of the
>bandwidth problems with A and C, and the feature restrictions of B and
>D, only E remains(or G, "do nothing" :) ).
>  
>
Patch for option E attached. It needs review, because there are lots of
cases to consider(and it is 4am here :( ). Feel free to commit it if
people agree with the solution. I haven't added a changelog in the patch
so if you commit it don't forget that too.

Andrew

? deaf_delayed.patch
? wasdelayed-bugfix.patch
? ircd/.Rhistory
? ircd/convert-conf
? ircd/test/ircd_match_t
Index: include/channel.h
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/include/channel.h,v
retrieving revision 1.55
diff -b -u -d -r1.55 channel.h
--- include/channel.h	27 Sep 2005 02:41:57 -0000	1.55
+++ include/channel.h	28 Oct 2005 14:58:19 -0000
@@ -81,6 +81,7 @@
 					 * channel 
 					 */
 #define CHFL_DELAYED            0x40000 /**< User's join message is delayed */
+#define CHFL_SEENDELAYED        0x80000 /**< User has been sent delayed list */
 
 #define CHFL_OVERLAP         (CHFL_CHANOP | CHFL_VOICE)
 #define CHFL_BANVALIDMASK    (CHFL_BANVALID | CHFL_BANNED)
@@ -219,6 +220,7 @@
 #define IsChannelManager(x) ((x)->status & CHFL_CHANNEL_MANAGER)
 #define IsUserParting(x)    ((x)->status & CHFL_USER_PARTING)
 #define IsDelayedJoin(x)    ((x)->status & CHFL_DELAYED)
+#define HasSeenDelayed(x)   ((x)->status & CHFL_SEENDELAYED)
 
 #define SetBanned(x)        ((x)->status |= CHFL_BANNED)
 #define SetBanValid(x)      ((x)->status |= CHFL_BANVALID)
@@ -230,6 +232,7 @@
 #define SetOpLevel(x, v)    (void)((x)->oplevel = (v))
 #define SetUserParting(x)   ((x)->status |= CHFL_USER_PARTING)
 #define SetDelayedJoin(x)   ((x)->status |= CHFL_DELAYED)
+#define SetSeenDelayed(x)   ((x)->status |= CHFL_SEENDELAYED)
 
 #define ClearBanned(x)      ((x)->status &= ~CHFL_BANNED)
 #define ClearBanValid(x)    ((x)->status &= ~CHFL_BANVALID)
@@ -454,5 +457,6 @@
 extern struct Ban *find_ban(struct Client *cptr, struct Ban *banlist);
 extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free);
 extern void free_ban(struct Ban *ban);
+extern void ShowClientAllDelayed(struct Client *client);
 
 #endif /* INCLUDED_channel_h */
Index: include/s_user.h
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/include/s_user.h,v
retrieving revision 1.21
diff -b -u -d -r1.21 s_user.h
--- include/s_user.h	18 Oct 2005 03:20:53 -0000	1.21
+++ include/s_user.h	28 Oct 2005 14:58:26 -0000
@@ -113,6 +113,8 @@
 #define NAMES_VIS 2 /**< List only visible users in non-secret channels */
 #define NAMES_EON 4 /**< Add an 'End Of Names' reply to the end */
 #define NAMES_DEL 8 /**< Show delayed joined users only */
+#define NAMES_INCLUDEDEL 16 /**< Show delayed joined users additionally */
+
 
 void do_names(struct Client* sptr, struct Channel* chptr, int filter);
 
Index: include/send.h
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/include/send.h,v
retrieving revision 1.22
diff -b -u -d -r1.22 send.h
--- include/send.h	16 Dec 2004 03:28:51 -0000	1.22
+++ include/send.h	28 Oct 2005 14:58:27 -0000
@@ -91,6 +91,11 @@
 #define SKIP_NONOPS	0x04	/**< skip users that aren't chanops */
 #define SKIP_NONVOICES  0x08    /**< skip users that aren't voiced (includes
                                    chanops) */
+#define SKIP_SEENDELAYED    0x10 /**< skip users that have seen delayed joins.
+                                      */
+#define SKIP_NOTSEENDELAYED 0x20 /**< skip users that have not seen delayed
+                                      joins. */
+
 
 /* Send command to all users having a particular flag set */
 extern void sendwallto_group_butone(struct Client *from, int type, 
Index: ircd/channel.c
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/ircd/channel.c,v
retrieving revision 1.156
diff -b -u -d -r1.156 channel.c
--- ircd/channel.c	6 Oct 2005 23:49:25 -0000	1.156
+++ ircd/channel.c	28 Oct 2005 14:59:18 -0000
@@ -3280,11 +3280,21 @@
     SetUserParting(member);
 
     /* Send notification to channel */
-    if (!(flags & (CHFL_ZOMBIE | CHFL_DELAYED)))
-      sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL, 0,
-				(flags & CHFL_BANNED || !jbuf->jb_comment) ?
-				":%H" : "%H :%s", chan, jbuf->jb_comment);
-    else if (MyUser(jbuf->jb_source))
+    if (!(flags & CHFL_ZOMBIE))
+      sendcmdto_channel_butserv_butone
+      (
+       jbuf->jb_source, CMD_PART, chan, NULL,
+       (flags & CHFL_DELAYED) ? SKIP_NOTSEENDELAYED : 0,
+       (flags & CHFL_BANNED || !jbuf->jb_comment) ? ":%H" : "%H :%s", chan,
+       jbuf->jb_comment
+      );
+
+    /* If the parting user hasn't seen their own part yet, send it now. */
+    if (
+        MyUser(jbuf->jb_source) &&
+        ((flags & CHFL_ZOMBIE) ||
+         ((flags & CHFL_DELAYED) && !HasSeenDelayed(member)))
+       )
       sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source,
 		    (flags & CHFL_BANNED || !jbuf->jb_comment) ?
 		    ":%H" : "%H :%s", chan, jbuf->jb_comment);
@@ -3320,16 +3330,27 @@
                               "%H %Tu", chan, chan->creationtime);
     }
 
-    if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & CHFL_VOICED_OR_OPPED))) {
+    if (!(flags & CHFL_VOICED_OR_OPPED)) {
       /* Send the notification to the channel */
-      sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, 0, "%H", chan);
+      sendcmdto_channel_butserv_butone
+      (jbuf->jb_source, CMD_JOIN, chan, NULL,
+       (chan->mode.mode & MODE_DELJOINS) ? SKIP_NOTSEENDELAYED : 0, "%H",
+       chan);
 
       /* send an op, too, if needed */
       if (flags & CHFL_CHANOP && (oplevel < MAXOPLEVEL || !MyUser(jbuf->jb_source)))
-	sendcmdto_channel_butserv_butone((chan->mode.apass[0] ? &his : jbuf->jb_source),
-                                         CMD_MODE, chan, NULL, 0, "%H +o %C",
-					 chan, jbuf->jb_source);
-    } else if (MyUser(jbuf->jb_source))
+	sendcmdto_channel_butserv_butone
+        ((chan->mode.apass[0] ? &his : jbuf->jb_source),
+         CMD_MODE, chan, NULL,
+         (chan->mode.mode & MODE_DELJOINS) ? SKIP_NOTSEENDELAYED : 0,
+         "%H +o %C", chan, jbuf->jb_source);
+    }
+    /* If the parting user hasn't seen their own part yet, send it now. */
+    if (
+        MyUser(jbuf->jb_source) &&
+        ((flags & CHFL_VOICED_OR_OPPED) ||
+         ((chan->mode.mode & MODE_DELJOINS) && !(flags & CHFL_SEENDELAYED)))
+       )
       sendcmdto_one(jbuf->jb_source, CMD_JOIN, jbuf->jb_source, ":%H", chan);
   }
 
@@ -3414,11 +3435,33 @@
 void RevealDelayedJoin(struct Membership *member)
 {
   ClearDelayedJoin(member);
-  sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel, member->user, 0, ":%H",
+  sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel,
+                                   member->user, SKIP_SEENDELAYED, ":%H",
                                    member->channel);
   CheckDelayedJoins(member->channel);
 }
 
+void ShowClientAllDelayed(struct Client *client)
+{
+  struct Membership *member, *member2;
+
+  for (member = cli_user(client)->channel; member; member=member->next_channel)
+  {
+    if (HasSeenDelayed(member) ||
+        !(member->channel->mode.mode & (MODE_WASDELJOINS | MODE_DELJOINS)))
+      continue;
+
+    SetSeenDelayed(member);
+    for (member2 = member->channel->members; member2;
+         member2=member2->next_member)
+    {
+      if (member2 == member || !IsDelayedJoin(member2))
+        continue;
+      sendcmdto_one(member2->user, CMD_JOIN, client, ":%H", member->channel);
+    }
+  }
+}
+
 /* CheckDelayedJoins: checks and clear +d if necessary */
 
 void CheckDelayedJoins(struct Channel *chan)
Index: ircd/m_join.c
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/ircd/m_join.c,v
retrieving revision 1.35
diff -b -u -d -r1.35 m_join.c
--- ircd/m_join.c	6 Oct 2005 23:49:25 -0000	1.35
+++ ircd/m_join.c	28 Oct 2005 14:59:26 -0000
@@ -112,6 +112,7 @@
   char *chanlist;
   char *name;
   char *keys;
+  int filter = NAMES_ALL|NAMES_EON;
 
   if (parc < 2 || *parv[1] == '\0')
     return need_more_params(sptr, "JOIN");
@@ -123,6 +124,9 @@
 
   keys = parv[2]; /* remember where keys are */
 
+  if (IsDeaf(sptr))
+    filter |= NAMES_INCLUDEDEL;
+
   for (name = ircd_strtok(&p, chanlist, ","); name;
        name = ircd_strtok(&p, 0, ",")) {
     char *key = 0;
@@ -247,7 +251,9 @@
 		 chptr->topic_time);
     }
 
-    do_names(sptr, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
+    do_names(sptr, chptr, filter); /* send /names list */
+    if (IsDeaf(sptr))
+      SetSeenDelayed((cli_user(sptr))->channel);
   }
 
   joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */
Index: ircd/m_names.c
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/ircd/m_names.c,v
retrieving revision 1.23
diff -b -u -d -r1.23 m_names.c
--- ircd/m_names.c	6 Oct 2005 04:00:36 -0000	1.23
+++ ircd/m_names.c	28 Oct 2005 14:59:32 -0000
@@ -156,7 +156,8 @@
     if (IsZombie(member) && member->user != sptr)
       continue;
 
-    if (IsDelayedJoin(member) && (member->user != sptr) && !(filter & NAMES_DEL))
+    if (IsDelayedJoin(member) && (member->user != sptr) &&
+        !(filter & (NAMES_DEL | NAMES_INCLUDEDEL)))
         continue;
 
     if ((!IsDelayedJoin(member) || (member->user == sptr)) && (filter & NAMES_DEL))
Index: ircd/s_user.c
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/ircd/s_user.c,v
retrieving revision 1.100
diff -b -u -d -r1.100 s_user.c
--- ircd/s_user.c	18 Oct 2005 03:20:53 -0000	1.100
+++ ircd/s_user.c	28 Oct 2005 15:00:04 -0000
@@ -1437,6 +1437,9 @@
     hide_hostmask(sptr, FLAG_HIDDENHOST);
   send_umode_out(cptr, sptr, &setflags, prop);
 
+  if (MyUser(sptr) && !FlagHas(&setflags, FLAG_DEAF) && IsDeaf(sptr))
+    ShowClientAllDelayed(sptr);
+
   return 0;
 }
 
Index: ircd/send.c
===================================================================
RCS file: /cvsroot/undernet-ircu/ircu2.10/ircd/send.c,v
retrieving revision 1.55
diff -b -u -d -r1.55 send.c
--- ircd/send.c	16 Dec 2004 03:28:50 -0000	1.55
+++ ircd/send.c	28 Oct 2005 15:00:19 -0000
@@ -544,7 +544,9 @@
         || IsZombie(member)
         || (skip & SKIP_DEAF && IsDeaf(member->user))
         || (skip & SKIP_NONOPS && !IsChanOp(member))
-        || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)))
+        || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member))
+        || (skip & SKIP_SEENDELAYED && HasSeenDelayed(member))
+        || (skip & SKIP_NOTSEENDELAYED && !HasSeenDelayed(member)))
         continue;
       send_buffer(member->user, mb, 0);
   }
_______________________________________________
Coder-com mailing list
Coder-com@undernet.org
http://undernet.sbg.org/mailman/listinfo/coder-com

Reply via email to