diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-09-07 17:25:01 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-09-07 17:25:01 +0100 |
commit | 3b836818fe3626798924a56f1660ab5423998094 (patch) | |
tree | 3fe8a232fb6539ba881962d1e38a9e858fd654af | |
parent | 6ae84b9245bfaa832f847a31952b2ae33daf2299 (diff) |
Avoid more replay log NICK synchronisation issues by ignoring replay log nick changes from us if not our current nick, and by completely ignoring replaying any type of replay log line from before blabouncer was launched.
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | blabouncer.c | 2 | ||||
-rw-r--r-- | functions.c | 13 | ||||
-rw-r--r-- | message.c | 3 | ||||
-rw-r--r-- | replay.c | 23 | ||||
-rw-r--r-- | replay.h | 2 | ||||
-rw-r--r-- | structures.h | 1 |
7 files changed, 36 insertions, 10 deletions
@@ -10,4 +10,4 @@ Ensure replayed lines don't exceed IRC message maximum length due to inserted ti Log server messages to file. -Is there a way to log nick changes to the normal log despite not tracking channels or nicks in each channel? +Is there a way to log nick changes to the normal log despite not tracking nicks in each channel? (We do track channel names themselves.) diff --git a/blabouncer.c b/blabouncer.c index 7d8dc06..cfc1f2d 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -413,6 +413,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { ircdstate.reconnecting = 0; ircdstate.clientchangetime = time(NULL); ircdstate.clientsnonetime = time(NULL); + // Record the time we launched (for comparisons later) + ircdstate.launchtime = time(NULL); // Struct of client codes // Used to track the last time a client identifying as a given client connected to handle auto replay for a known client. diff --git a/functions.c b/functions.c index bbbd9dd..0a03ca9 100644 --- a/functions.c +++ b/functions.c @@ -811,7 +811,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set // Replay those lines! for (int i = 0; i < numlines; i++) { - if (!readreplayline(replayseconds, i, outgoingmsg, settings->basedir, settings->replaydates)) { + if (!readreplayline(replayseconds, i, outgoingmsg, settings, ircdstate)) { debugprint(DEBUG_CRIT, "Error requesting replay line.\n"); return 0; } @@ -860,6 +860,17 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set } } + // Separate special check for if a NICK change is from us but it isn't our current nick + if (strncmp(tokens[1], "NICK", strlen("NICK")) == 0) { + extractnickfromprefix(tokens[0]); + + if (strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0) { + debugprint(DEBUG_FULL, "Not sending '%s' replay line '%s'.\n", tokens[1], outgoingmsg); + free(strcopyPtr); + continue; + } + } + free(strcopyPtr); debugprint(DEBUG_FULL, "Sending replay line: '%s'.\n", outgoingmsg); @@ -416,7 +416,8 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int writereplayline(str, settings->basedir); } - // TODO - Is there a way to log nick changes to the normal log despite not tracking channels or nicks in each channel? + // TODO - Is there a way to log nick changes to the normal log despite not tracking nicks in each channel? + // (We do track channel names themselves.) free(svrprefixcopy); return 1; @@ -219,19 +219,21 @@ int replaylines(int seconds, char *basedir) { } // Set 'str' to the line in the log with a timestamp of greater than 'seconds' -// seconds ago, plus however many lines 'linenum' is set to. 'basedir' is the -// directory in which to find 'replay.log'. +// seconds ago, plus however many lines 'linenum' is set to. // Also modify the line to include a timestamp in the form "[HH:MM:SS]", or [DD/MM/YY HH:MM:SS] -// if replaydates == 1. +// if settings.replaydates == 1. // Returns 1 on success, or 0 on failure. // TODO - This is horribly inefficient since it re-reads the entire file each call, rewrite this! -int readreplayline(int seconds, int linenum, char *str, char *basedir, int replaydates) { +int readreplayline(int seconds, int linenum, char *str, struct settings *settings, struct ircdstate *ircdstate) { FILE *fp; char line[MAXCHAR]; char filename[PATH_MAX]; // Build path - snprintf(filename, PATH_MAX, "%s/replay.log", basedir); + if (!snprintf(filename, PATH_MAX, "%s/replay.log", settings->basedir)) { + debugprint(DEBUG_CRIT, "debuglog(): Error while preparing replay path, exiting!\n"); + exit(1); + } int count = 0; @@ -257,10 +259,19 @@ int readreplayline(int seconds, int linenum, char *str, char *basedir, int repla // If the line is within range of the requested time... if (timestamp >= timenow - seconds) { + // ...and it wasn't before blabouncer launched... + if (timestamp <= ircdstate->launchtime) { + // Don't replay if this replay line happened before blabouncer launched, + // to avoid weird synchronisation issues with uncertain events from before + // we launched. + debugprint(DEBUG_FULL, "readreplayline(): Ignoring line '%s' from before we launched.\n", line); + continue; + } + // ...and it is the current requested line then return it if (count == linenum) { // Insert our formatted [HH:MM:SS] timestamp into the message - formattime(line, replaydates); + formattime(line, settings->replaydates); strncpy(str, line, strlen(line)); str[strlen(line)] = '\0'; @@ -40,7 +40,7 @@ int replaylines(int seconds, char *basedir); -int readreplayline(int seconds, int linenum, char *str, char *basedir, int replaydates); +int readreplayline(int seconds, int linenum, char *str, struct settings *settings, struct ircdstate *ircdstate); // Returns the number of seconds ago that 'nick' last spoke, or -1 if there is a problem. // 'basedir' is the directory in which to find 'replay.log'. diff --git a/structures.h b/structures.h index 66c34d0..e58c1b1 100644 --- a/structures.h +++ b/structures.h @@ -52,6 +52,7 @@ struct ircdstate { char oldnick[MAXNICKLENGTH]; // Set temporarily if we end up reconnecting in case we need to tell existing clients about a nick change int clientchangetime; // The last time a client registered or disconnected int clientsnonetime; // The last time there were no clients registered + int launchtime; // The time blabouncer was launched }; // Structure of settings either to be read from the configuration file or set/changed at runtime |