summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-06-12 21:29:28 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-06-12 21:29:28 +0100
commit0bea530df3f718b34a1022a871f4f78a41c2bee6 (patch)
tree74ec32052bfc81a9218896eb7675be7e87193a2f
parent0ea06b9c632af2fe09cdea8be0baa9ae6e538aeb (diff)
Handle failing to reconnect to the server upon timeout or disconnection by looping the reconnection and keeping clients informed.
-rw-r--r--TODO6
-rw-r--r--blabouncer.c75
2 files changed, 53 insertions, 28 deletions
diff --git a/TODO b/TODO
index 4c106d8..cfd260b 100644
--- a/TODO
+++ b/TODO
@@ -7,6 +7,8 @@ Add various auto replay options:
Might need to #include <limits.h> in blabouncer.c to make some operating systems and/or compilers happy.
-Handle re-connecting to the server failing.
-
Allow reloading the configuration file while running (at least for things like replayseconds, replaymode) - BLABOUNCER command and SIGHUP?
+
+Don't pass server PONGs to clients.
+
+"error: createchannel(): channel name already exists.\n: Success" printed to terminal upon server reconnection.
diff --git a/blabouncer.c b/blabouncer.c
index c416c3e..bbb22cd 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -492,6 +492,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
snprintf(outgoingmsg, MAXDATASIZE, "PING timeouttest");
}
sendtoserver(server_ssl, outgoingmsg, strlen(outgoingmsg), 0, clients, settings);
+ // Back to top of loop
+ continue;
} else {
// ...and we've already PINGed the server and haven't heard back yet, so let's assume we've timed out
// TODO - Code duplication, make a function and share with socket error code below
@@ -502,23 +504,34 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
sendtoallclients(clients, alertmsg, 0, settings);
if (settings->servertls) {
// Finish up with OpenSSL if using server TLS
- SSL_free(server_ssl);
+ if (server_ssl != NULL) SSL_free(server_ssl);
+ // Set to NULL so we can check if we already free()d this on a previous attempt
+ server_ssl = NULL;
}
// Close the socket
close(*serversockfd);
- // Make a new one
- *serversockfd = createserversocket(settings->ircserver, settings->ircserverport);
-
- // Set reconnection marker for other functions to know we're reconnecting
- ircdstate.reconnecting = 1;
- // Set oldnick in case we change nick when reconnecting so we can inform existing clients
- strcpy(ircdstate.oldnick, ircdstate.ircnick);
- connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients);
+ // Make a new one and reconnect
+ if ((*serversockfd = createserversocket(settings->ircserver, settings->ircserverport)) == -1) {
+ // We failed
+ debugprint(DEBUG_CRIT, "dochat(): Couldn't reconnect to server, will try again.\n");
+ // Tell clients
+ char alertmsg[MAXDATASIZE];
+ snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Couldn't reconnect to server, will try again.", ircdstate.ircnick);
+ sendtoallclients(clients, alertmsg, 0, settings);
+ // Don't go back to the top of the loop yet, perhaps some clients are waiting to tell us something - TODO - Could this ever happen in this state?
+ } else {
+ // We succeeded
+ // Set reconnection marker for other functions to know we're reconnecting
+ ircdstate.reconnecting = 1;
+ // Set oldnick in case we change nick when reconnecting so we can inform existing clients
+ strcpy(ircdstate.oldnick, ircdstate.ircnick);
+ connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients);
+ // Back to top of loop
+ continue;
+ }
}
- // Back to top of loop
- continue;
} else {
- // No timeout is occuring, back to the top of the loop
+ // No timeout is occuring, the pselect() just timed out (which is fine and expected), back to the top of the loop
continue;
}
}
@@ -543,28 +556,38 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
// If there was a socket error (receive error or socket closed)
// TODO - Code duplication, make a function and share with timeout code above
if (servernumbytes < 1) {
- printf("Server socket had an error (sockread return code %d), reconnecting!\n", servernumbytes);
- // Tell all clients if we timed out
+ debugprint(DEBUG_CRIT, "Server socket had an error (sockread return code %d), reconnecting!\n", servernumbytes);
+ // Tell all clients if we had an error
char alertmsg[MAXDATASIZE];
snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Server socket had an error (sockread return code %d), reconnecting!", ircdstate.ircnick, servernumbytes);
sendtoallclients(clients, alertmsg, 0, settings);
if (settings->servertls) {
// Finish up with OpenSSL if using server TLS
- SSL_free(server_ssl);
+ if (server_ssl != NULL) SSL_free(server_ssl);
+ // Set to NULL so we can check if we already free()d this on a previous attempt
+ server_ssl = NULL;
}
// Close the socket
close(*serversockfd);
- // Make a new one
- *serversockfd = createserversocket(settings->ircserver, settings->ircserverport);
-
- // Set reconnection marker for other functions to know we're reconnecting
- ircdstate.reconnecting = 1;
- // Set oldnick in case we change nick when reconnecting so we can inform existing clients
- strcpy(ircdstate.oldnick, ircdstate.ircnick);
- connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients);
-
- // Back to top of loop
- continue;
+ // Make a new one and reconnect
+ if ((*serversockfd = createserversocket(settings->ircserver, settings->ircserverport)) == -1) {
+ // We failed
+ debugprint(DEBUG_CRIT, "dochat(): Couldn't reconnect to server, will try again.\n");
+ // Tell clients
+ char alertmsg[MAXDATASIZE];
+ snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Couldn't reconnect to server, will try again.", ircdstate.ircnick);
+ sendtoallclients(clients, alertmsg, 0, settings);
+ // Don't go back to the top of the loop yet, perhaps some clients are waiting to tell us something - TODO - Could this ever happen in this state?
+ } else {
+ // We succeeded
+ // Set reconnection marker for other functions to know we're reconnecting
+ ircdstate.reconnecting = 1;
+ // Set oldnick in case we change nick when reconnecting so we can inform existing clients
+ strcpy(ircdstate.oldnick, ircdstate.ircnick);
+ connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients);
+ // Back to top of loop
+ continue;
+ }
}
serverbuf[servernumbytes] = '\0';