Commit 3b836818 authored by Luke Bratch's avatar Luke Bratch

Avoid more replay log NICK synchronisation issues by ignoring replay log nick...

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.
parent 6ae84b92
......@@ -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.)
......@@ -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.
......
......@@ -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'.
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment