From b2089e21606aed1a6aaa9644dbe0d2fe998ae1e0 Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Fri, 8 Aug 2025 23:11:31 +0100 Subject: Improve output of LISTCLIENTS blabouncer command, add identical listclients command to STDIN commands, declare STDIN commands ("debug commands") in README. --- README | 8 ++++++++ TODO | 2 +- blabouncer.c | 36 ++++++++++++++++++++++++++++++++++++ message.c | 23 ++++++++++++++++++----- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/README b/README index 3875fc2..dec0475 100644 --- a/README +++ b/README @@ -109,3 +109,11 @@ $HOME/.blabouncer/key.pem, respectively. Server TLS is also enabled by default in the example configuration file, and can be disabled (not recommended) using the "servertls" configuration file option. + +== Debug commands == + +If run in foreground mode, the following commands can be sent to standard input: + +"listchannels" (To list all joined channels and their members.) +"reopenssl" (To reload the client-side TLS certificate/key.) +"listclients" (To list all connected clients and their authentication status.) diff --git a/TODO b/TODO index eabe733..f736661 100644 --- a/TODO +++ b/TODO @@ -33,7 +33,7 @@ What happens with lastspoke when there was no lastspoke time? Potentially opt t Is it possible to periodically reduce fdmax if higher numbered clients are gone? Debug log ("checking client socket out of ") gets busy after fdmax gets relatively high, and might be possible to avoid unnecessary looping. -Combine custom BLABOUNCER commands with stdin commands (or ditch stdin?). +Combine custom BLABOUNCER commands with stdin commands. Crash when requesting 30 hour replay. diff --git a/blabouncer.c b/blabouncer.c index 1c61336..b57fb4a 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -805,6 +805,42 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { continue; } + if (strncmp(outgoingmsg, "listclients", strlen("listclients")) == 0) { + debugprint(DEBUG_SOME, "dochat(): stdin: There are %d blabouncer client(s) connected:\n", numclients(clients)); + printf("There are %d blabouncer client(s) connected:\n", numclients(clients)); + + // Loop through each client in clients struct for connected and authenticated clients... + int clientcount = 0; + debugprint(DEBUG_SOME, "dochat(): stdin: Authenticated clients:\n"); + printf("Authenticated clients:\n"); + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].fd && clients[i].authed) { + // ...then tell the requesting client about them + clientcount++; + debugprint(DEBUG_SOME, "dochat(): stdin: #%d: File descriptor: %d, IP: %s.\n", clientcount, clients[i].fd, clients[i].remoteip); + printf("#%d: File descriptor: %d, IP: %s.\n", clientcount, clients[i].fd, clients[i].remoteip); + } + } + + // And now loop through each client in clients struct for connected but unauthenticated clients... + clientcount = 0; + debugprint(DEBUG_SOME, "dochat(): stdin: Unauthenticated clients:\n"); + printf("Unauthenticated clients:\n"); + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].fd && !clients[i].authed) { + // ...then tell the requesting client about them + clientcount++; + debugprint(DEBUG_SOME, "dochat(): stdin: #%d: File descriptor: %d, IP: %s.\n", clientcount, clients[i].fd, clients[i].remoteip); + printf("#%d: File descriptor: %d, IP: %s.\n", clientcount, clients[i].fd, clients[i].remoteip); + } + } + + debugprint(DEBUG_SOME, "dochat(): stdin: STDIN command complete: listclients\n"); + printf("STDIN command complete: listclients\n"); + + continue; + } + debugprint(DEBUG_FULL, "dochat(): stdin: '%s' not processed as a command, sending to server.\n", outgoingmsg); printf("'%s' not processed as a command, sending to server.\n", outgoingmsg); // sourcefd = 0 as this is a trusted message diff --git a/message.c b/message.c index b574586..36941ec 100644 --- a/message.c +++ b/message.c @@ -1535,15 +1535,28 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :There are %d blabouncer client(s) connected:", ircdstate->ircnick, numclients(clients)); sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); + // Loop through each client in clients struct for connected and authenticated clients... int clientcount = 0; + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Authenticated clients:", ircdstate->ircnick); + sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].fd && clients[i].authed) { + // ...then tell the requesting client about them + clientcount++; + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :#%d: File descriptor: %d, IP: %s.", ircdstate->ircnick, clientcount, clients[i].fd, clients[i].remoteip); + sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); + } + } - // Loop through each client in clients struct... + // And now loop through each client in clients struct for connected but unauthenticated clients... + clientcount = 0; + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Unauthenticated clients:", ircdstate->ircnick); + sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); for (int i = 0; i < MAXCLIENTS; i++) { - // ...and if they have a file descriptor... - if (clients[i].fd) { - // ... then tell the requesting client about them + if (clients[i].fd && !clients[i].authed) { + // ...then tell the requesting client about them clientcount++; - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :#%d: File descriptor: %d, authenticated: %d, IP: %s.", ircdstate->ircnick, clientcount, clients[i].fd, clients[i].authed, clients[i].remoteip); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :#%d: File descriptor: %d, IP: %s.", ircdstate->ircnick, clientcount, clients[i].fd, clients[i].remoteip); sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); } } -- cgit v1.2.3