summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Clarke <jrtc27@jrtc27.com>2020-01-01 20:37:39 +0000
committerPatrick <tingping@tingping.se>2020-01-01 16:39:11 -0800
commit9c44d7baf400e2addebfb5343c99cf753cebf7eb (patch)
tree0fac6ea329278fe83016e120e77b6e53537c1590
parentc361bdca6afdc933eeac35732334464990295cd4 (diff)
Avoid prioritising MODE queries for channels with hyphens in their name
If a user has a large number of channels containing hyphens in their
names, the initial MODE queries will have the same high priority as any
PINGs, and so will block the PINGs from being sent, causing the
connection to time out due to a lack of PONGs received.
-rw-r--r--src/common/server.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/common/server.c b/src/common/server.c
index 3db0a963..f7fa8b96 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -200,13 +200,35 @@ tcp_send_len (server *serv, char *buf, int len)
 	}
 	else
 	{
-		/* WHO/MODE get the lowest priority */
-		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0 ||
-		/* but only MODE queries, not changes */
-			(g_ascii_strncasecmp (dbuf + 1, "MODE", 4) == 0 &&
-			 strchr (dbuf, '-') == NULL &&
-			 strchr (dbuf, '+') == NULL))
+		/* WHO gets the lowest priority */
+		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0)
 			dbuf[0] = 0;
+		/* as do MODE queries (but not changes) */
+		else if (g_ascii_strncasecmp (dbuf + 1, "MODE ", 5) == 0)
+		{
+			char *mode_str, *mode_str_end, *loc;
+			/* skip spaces before channel/nickname */
+			for (mode_str = dbuf + 5; *mode_str == ' '; ++mode_str);
+			/* skip over channel/nickname */
+			mode_str = strchr (mode_str, ' ');
+			if (mode_str)
+			{
+				/* skip spaces before mode string */
+				for (; *mode_str == ' '; ++mode_str);
+				/* find spaces after end of mode string */
+				mode_str_end = strchr (mode_str, ' ');
+				/* look for +/- within the mode string */
+				loc = strchr (mode_str, '-');
+				if (loc && (!mode_str_end || loc < mode_str_end))
+					goto keep_priority;
+				loc = strchr (mode_str, '+');
+				if (loc && (!mode_str_end || loc < mode_str_end))
+					goto keep_priority;
+			}
+			dbuf[0] = 0;
+keep_priority:
+			;
+		}
 	}
 
 	serv->outbound_queue = g_slist_append (serv->outbound_queue, dbuf);