From 3b2b776a1f3684429c5014b964db54737e662dda Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Tue, 1 Aug 2023 23:52:31 +0100 Subject: Correctly handle too many clients by doing accept() and close() immediately rather than trying to add to clients[] struct. --- TODO | 4 +++- blabouncer.c | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index 6c90f83..6bcc8d3 100644 --- a/TODO +++ b/TODO @@ -44,4 +44,6 @@ KICK not handled. Crash when requesting 30 hour replay. -"too many clients, disconnecting and skipping loop iteration!" has been seen in the real world, e.g. Wed Jul 12 16:44:57 2023 +Users in channel not being populated observed once - 27/07/2023 #pipewire on irc.oftc.net. +(related to?): +11/06/2023 01:00:41 "processrawstring(): combined truncated message '2131365056' is too long (1006 out of a maximum of 512 characters), clearing it." seen during long/truncated/recombined 353 RPL_NAMREPLY #winehq on irc.libera.chat. diff --git a/blabouncer.c b/blabouncer.c index 878dbd1..c56fc9d 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -790,12 +790,6 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { if (i == *clientsockfd) { debugprint(DEBUG_SOME, "...new connection!\n"); // handle new connections - if (numclients(clients) >= MAXCLIENTS) { - fprintf(stderr, "too many clients, disconnecting and skipping loop iteration!\n"); - debugprint(DEBUG_CRIT, "too many clients, disconnecting and skipping loop iteration!\n"); - disconnectclient(i, clients, &ircdstate, settings, clientcodes); - continue; - } addrlen = sizeof remoteaddr; newfd = accept(*clientsockfd, (struct sockaddr *)&remoteaddr, &addrlen); if (newfd == -1) { @@ -814,6 +808,20 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { char remoteip[INET6_ADDRSTRLEN]; strncpy(remoteip, inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), INET6_ADDRSTRLEN); + // accept() and close() immediately if there are too many clients + if (numclients(clients) >= MAXCLIENTS) { + fprintf(stderr, "dochat(): clientsockfd loop: too many clients, disconnecting fd '%d' ('%s') and skipping loop iteration!\n", newfd, remoteip); + debugprint(DEBUG_CRIT, "dochat(): clientsockfd loop: too many clients, disconnecting fd '%d' ('%s') and skipping loop iteration!\n", newfd, remoteip); + char outgoingmsg[MAXDATASIZE]; + if (!snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :too many clients, disconnecting fd '%d' ('%s')!", ircdstate.ircnick, newfd, remoteip)) { + debugprint(DEBUG_CRIT, "dochat(): clientsockfd loop: error while preparing too many clients message!\n"); + outgoingmsg[0] = '\0'; + } + sendtoallclients(clients, outgoingmsg, 0, settings); + close(newfd); + continue; + } + // Find a free element in the clients array and set to new fd value (plus start SSL_accept() if using client TLS) for (int j = 0; j < MAXCLIENTS; j++) { if (clients[j].fd == 0) { -- cgit v1.2.3