summary refs log tree commit diff
path: root/bounce.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-05-11 18:05:41 -0400
committerJune McEnroe <june@causal.agency>2020-05-11 18:16:19 -0400
commit548c4a3a86a37cf74aac5ef91f84b9a762dc1023 (patch)
tree810cdf6ea4d26421f4b2a36f3a35bda745fec628 /bounce.c
parentPass -1 as backlog to listen(2) (diff)
downloadpounce-548c4a3a86a37cf74aac5ef91f84b9a762dc1023.tar.gz
pounce-548c4a3a86a37cf74aac5ef91f84b9a762dc1023.zip
Add server send queueing with time interval
This addresses pounce getting killed with "Excess flood" when it sends
NAMES commands for too many channels when a client connects. These
commands, as well as automatic AWAY commands, are by default throttled
to 5 per second.

Tested on freenode with 36 channels and 200ms interval.
Diffstat (limited to 'bounce.c')
-rw-r--r--bounce.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/bounce.c b/bounce.c
index dd5d723..6ddc023 100644
--- a/bounce.c
+++ b/bounce.c
@@ -31,6 +31,7 @@
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <sysexits.h>
 #include <tls.h>
 #include <unistd.h>
@@ -111,6 +112,16 @@ static size_t parseSize(const char *str) {
 	return size;
 }
 
+static struct timeval parseInterval(const char *str) {
+	char *rest;
+	long ms = strtol(str, &rest, 0);
+	if (*rest) errx(EX_USAGE, "invalid interval: %s", str);
+	return (struct timeval) {
+		.tv_sec = ms / 1000,
+		.tv_usec = 1000 * (ms % 1000),
+	};
+}
+
 static FILE *saveFile;
 
 static void saveSave(void) {
@@ -280,6 +291,7 @@ int main(int argc, char *argv[]) {
 		{ .val = 'K', .name = "local-priv", required_argument },
 		{ .val = 'N', .name = "no-names", no_argument },
 		{ .val = 'P', .name = "local-port", required_argument },
+		{ .val = 'Q', .name = "queue-interval", required_argument },
 		{ .val = 'S', .name = "bind", required_argument },
 		{ .val = 'T', .name = "no-sts", no_argument },
 		{ .val = 'U', .name = "local-path", required_argument },
@@ -329,6 +341,7 @@ int main(int argc, char *argv[]) {
 			break; case 'K': strlcpy(privPath, optarg, sizeof(privPath));
 			break; case 'N': stateNoNames = true;
 			break; case 'P': bindPort = optarg;
+			break; case 'Q': serverQueueInterval = parseInterval(optarg);
 			break; case 'S': serverBindHost = optarg;
 			break; case 'T': clientSTS = false;
 			break; case 'U': strlcpy(bindPath, optarg, sizeof(bindPath));
@@ -447,6 +460,7 @@ int main(int argc, char *argv[]) {
 	signal(SIGINT, signalHandler);
 	signal(SIGTERM, signalHandler);
 	signal(SIGPIPE, SIG_IGN);
+	signal(SIGALRM, signalHandler);
 	signal(SIGINFO, signalHandler);
 	signal(SIGUSR1, signalHandler);
 
@@ -509,18 +523,23 @@ int main(int argc, char *argv[]) {
 
 		if (signals[SIGINT] || signals[SIGTERM]) break;
 
+		if (signals[SIGALRM]) {
+			signals[SIGALRM] = 0;
+			serverDequeue();
+		}
+
 		if (signals[SIGINFO]) {
-			ringInfo();
 			signals[SIGINFO] = 0;
+			ringInfo();
 		}
 
 		if (signals[SIGUSR1]) {
+			signals[SIGUSR1] = 0;
 			cert = splitOpen(certSplit);
 			priv = splitOpen(privSplit);
 			localConfig(cert, priv, localCA, !clientPass);
 			fclose(cert);
 			fclose(priv);
-			signals[SIGUSR1] = 0;
 		}
 	}