summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-09-07 17:25:01 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-09-07 17:25:01 +0100
commit3b836818fe3626798924a56f1660ab5423998094 (patch)
tree3fe8a232fb6539ba881962d1e38a9e858fd654af
parent6ae84b9245bfaa832f847a31952b2ae33daf2299 (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--TODO2
-rw-r--r--blabouncer.c2
-rw-r--r--functions.c13
-rw-r--r--message.c3
-rw-r--r--replay.c23
-rw-r--r--replay.h2
-rw-r--r--structures.h1
7 files changed, 36 insertions, 10 deletions
diff --git a/TODO b/TODO
index 5895d8b..0335689 100644
--- a/TODO
+++ b/TODO
@@ -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);
diff --git a/message.c b/message.c
index 9058814..3036eb2 100644
--- a/message.c
+++ b/message.c
@@ -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;
diff --git a/replay.c b/replay.c
index 412ed7c..654e170 100644
--- a/replay.c
+++ b/replay.c
@@ -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';
diff --git a/replay.h b/replay.h
index c3f23f9..039c131 100644
--- a/replay.h
+++ b/replay.h
@@ -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