summaryrefslogtreecommitdiff
path: root/functions.c
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-06-17 01:46:28 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-06-17 01:46:28 +0100
commitc70cd5cccc966a35f175913f2281ce251fd62425 (patch)
treecd95e1bbb28ad4df94db87b9e3080cb05d00645b /functions.c
parentfa37193c83f82784e826b8477ee7d4a4cd96d7cf (diff)
Implement a per-client identifier so auto replay can replay everything a given client has missed.
Diffstat (limited to 'functions.c')
-rw-r--r--functions.c94
1 files changed, 91 insertions, 3 deletions
diff --git a/functions.c b/functions.c
index 1efb2c1..f8609b1 100644
--- a/functions.c
+++ b/functions.c
@@ -536,7 +536,7 @@ int sendtoserver(SSL *server_ssl, char *strsrc, int str_len, int clientfd, struc
// it from the array of clients.
// Also set its authentication and registration statuses to 0.
// Also set the pending statuses to 0
-int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate, struct settings *settings) {
+int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate, struct settings *settings, struct clientcodes *clientcodes) {
debugprint(DEBUG_SOME, "disconnectclient(): disconnecting client fd '%d'\n", fd);
// Alert other clients about the disconnection (don't send yet, we haven't removed from the clients array yet)
@@ -553,6 +553,10 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
// If the client was registered, record the time of the last client disconnect
if (clients[i].registered) {
ircdstate->clientchangetime = time(NULL);
+ // And set their client code, if any, to last disconnecting at this time.
+ if (clients[i].clientcode[0]) {
+ setclientcodetime(clients[i].clientcode, clientcodes);
+ }
}
clients[i].fd = 0;
clients[i].authed = 0;
@@ -565,6 +569,7 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
clients[i].pendingwhowas = 0;
clients[i].pendingnames = 0;
clients[i].pendingcap = 0;
+ clients[i].clientcode[0] = '\0';
if (settings->clienttls) {
// Finish up with OpenSSL if using client TLS
SSL_free(clients[i].ssl);
@@ -902,6 +907,11 @@ int doautoreplay(int sourcefd, struct client *clients, struct settings *settings
return 1;
}
+ // If replaymode = "lastchange" then don't handle this here, it is done when the client registers its client code
+ if (!strncmp(settings->replaymode, "perclient", strlen("perclient"))) {
+ return 1;
+ }
+
// We shouldn't get here
return 0;
}
@@ -1075,9 +1085,9 @@ int rehash(struct settings *settings, char *failuremsg) {
return 0;
} else {
if (strcmp(settings->replaymode, "none") && strcmp(settings->replaymode, "time") && strcmp(settings->replaymode, "lastspoke") &&
- strcmp(settings->replaymode, "noclients") && strcmp(settings->replaymode, "lastchange")) {
+ strcmp(settings->replaymode, "noclients") && strcmp(settings->replaymode, "lastchange") && strcmp(settings->replaymode, "perclient")) {
strcpy(settings->replaymode, oldreplaymode);
- strcpy(failuremsg, "replaymode in configuration file must be one of \"none\", \"time\", \"lastspoke\", \"noclients\", or \"lastchange\"");
+ strcpy(failuremsg, "replaymode in configuration file must be one of \"none\", \"time\", \"lastspoke\", \"noclients\", \"lastchange\", or \"perclient\"");
return 0;
}
}
@@ -1155,3 +1165,81 @@ int checkpassword(char *password, struct settings *settings) {
// No messing around with password stuff
exit(EXIT_FAILURE);
}
+
+// Adds a client code to the clientcode structure if it doesn't already exist.
+// On success, copy it to the client's clientcode field.
+// Returns 1 on adding a new code, 0 if the code already existed, or -1 on error.
+int addclientcode(int sourcefd, char *code, struct clientcodes *clientcodes, struct client *clients) {
+ debugprint(DEBUG_SOME, "addclientcode(): Adding client code '%s' if it doesn't already exist.\n", code);
+
+ // Make sure there aren't too many client codes already
+ int counter;
+ for (int i = 0; i < MAXCLIENTCODES; i++) {
+ if (clientcodes[i].code[0]) {
+ counter++;
+ }
+ }
+ if (counter >= MAXCLIENTCODES) {
+ debugprint(DEBUG_CRIT, "addclientcode(): too many client codes.\n");
+ return -1;
+ }
+
+ // Copy it to the current client
+ for (int j = 0; j < MAXCLIENTS; j++) {
+ if (clients[j].fd == sourcefd) {
+ strcpy(clients[j].clientcode, code);
+ debugprint(DEBUG_FULL, "addclientcode(): set client code for fd '%d' to '%s'.\n", clients[j].fd, clients[j].clientcode);
+ }
+ }
+
+ // And add it to the clientcode structure if it doesn't already exist
+ for (int i = 0; i < MAXCLIENTCODES; i++) {
+ if (strlen(code) == strlen(clientcodes[i].code) && (strncmp(code, clientcodes[i].code, strlen(code)) == 0)) {
+ debugprint(DEBUG_FULL, "addclientcode(): client code already existed.\n");
+ // It already exists
+ return 0;
+ } else {
+ // It doesn't, add it
+ strcpy(clientcodes[i].code, code);
+ return 1;
+ }
+ }
+
+ // We shouldn't get here
+ debugprint(DEBUG_CRIT, "addclientcode(): we shouldn't get here");
+ return -1;
+}
+
+// Sets a given client code as last disconnecting at the current time.
+// Returns 1 on success or 0 on failure. - TODO have callers do something on failure, or change this to a void.
+int setclientcodetime(char *code, struct clientcodes *clientcodes) {
+ debugprint(DEBUG_FULL, "setclientcodetime(): Setting disconnect time for '%s'.\n", code);
+
+ // Look for this code and set it as the current time if found
+ for (int i = 0; i < MAXCLIENTCODES; i++) {
+ if (strlen(code) == strlen(clientcodes[i].code) && (strncmp(code, clientcodes[i].code, strlen(code)) == 0)) {
+ clientcodes[i].lastdisconnected = time(NULL);
+ debugprint(DEBUG_FULL, "setclientcodetime(): Set time to '%d'.\n", clientcodes[i].lastdisconnected);
+ return 1;
+ }
+ }
+
+ // If we got here, the code was never found
+ return 0;
+}
+
+// Return the timestamp that a given client last disconnected, or 0 on failure.
+int getclientcodetime(char *code, struct clientcodes *clientcodes) {
+ debugprint(DEBUG_FULL, "getclientcodetime(): looking for '%s'.\n", code);
+ // Look for this code and set it as the current time if found
+ for (int i = 0; i < MAXCLIENTCODES; i++) {
+//printf("%s.\n", clientcodes[i].code);
+ if (strlen(code) == strlen(clientcodes[i].code) && (strncmp(code, clientcodes[i].code, strlen(code)) == 0)) {
+ debugprint(DEBUG_FULL, "getclientcodetime(): code '%s' found at index '%d', timestamp '%d'.\n", code, i, clientcodes[i].lastdisconnected);
+ return clientcodes[i].lastdisconnected;
+ }
+ }
+
+ // If we got here, the code was never found
+ return 0;
+}