diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-06-17 01:46:28 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-06-17 01:46:28 +0100 |
commit | c70cd5cccc966a35f175913f2281ce251fd62425 (patch) | |
tree | cd95e1bbb28ad4df94db87b9e3080cb05d00645b /functions.c | |
parent | fa37193c83f82784e826b8477ee7d4a4cd96d7cf (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.c | 94 |
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; +} |