Commit a16d9bde authored by Luke Bratch's avatar Luke Bratch
Browse files

Make the "channels" configuration file entry an array.

parent 323e273b
......@@ -4,8 +4,6 @@ Configurable rotation of replay and debug logs.
Configurable timestamp format in logs.
Add a make install/uninstall/etc., add an "INSTALL" file, include a dependency listing.
macOS compiler may need limits.h included in structures.h.
"Starting log replay...." followed by "Unable to read replay log file!" even though replay seemed to work?
......@@ -16,6 +14,6 @@ Can memory usage be reduced further? (e.g. better channel struct management)
Ability to load new certificate whilst running.
Make the "channels" configuration file entry an array.
JOINing a channel that is a substring of another channel breaks all sorts (e.g. both #blabouncer and #blabounce).
Crash when requesting 30 hour replay.
......@@ -1052,12 +1052,27 @@ int main(int argc, char *argv[]) {
}
// What, if anything, are the configured auto channels?
if (!getconfstr("channels", settings.conffile, settings.autochannels)) {
settings.autochannels[0] = '\0';
} else {
// If something was set, make sure it's not too long
if (strlen(settings.autochannels) >= MAXAUTOCHANLEN) {
printf("main(): 'channels' option in configuration file is too long.\n");
ret = getconfarr("channels", settings.conffile, settings.autochannels);
if (!ret) {
for (int i = 0; i < MAXCONFARR; i++) {
settings.autochannels[i][0] = '\0';
}
} else if (ret == -1) {
// Remove any newlines from the middle of the string so error printing works nicely
for (size_t i = 0; i < strlen(settings.autochannels[0]) - 1; i++) {
if (settings.autochannels[0][i] == '\n') {
settings.autochannels[0][i] = ' ';
}
}
printf("main(): error getting 'autochannels' from configuration file: %s", settings.autochannels[0]);
exit(1);
}
// Make sure channel/key pairs aren't too long (since getconfarr() has to use MAXDATASIZE for all string lengths)
for (int i = 0; i < MAXCONFARR; i++) {
// +1 for the space between channel name and keys
if (settings.autochannels[i][0] && strlen(settings.autochannels[i]) > MAXCHANLENGTH + 1 + MAXCHANKEYLEN) {
printf("main(): error: specified channel name/key pair '%s' is too long, maximum lengths are %d (name) and %d (key).\n", settings.autochannels[i], MAXCHANLENGTH, MAXCHANKEYLEN);
exit(1);
}
}
......
......@@ -32,9 +32,12 @@ nicks = {
username = "bounceusr"
realname = "Mr Bla Bouncer"
# Channels to automatically join (comma-separated list, defaults to none)
# Put channel keywords/passwords after channel names following a space.
#channels = "#blabouncer keyword,#test"
# Channels to automatically join (defaults to none)
# Put channel keys/passwords after channel names (separated with a space)
channels = {
"#blabouncer keyword"
"#test"
}
# Auto replay mode upon a bouncer client connecting
# "none" = Don't auto replay
......
......@@ -344,9 +344,12 @@ int createconfigfile(char *filename) {
"username = \"bounceusr\"\n"
"realname = \"Mr Bla Bouncer\"\n"
"\n"
"# Channels to automatically join (comma-separated list, defaults to none)\n"
"# Put channel keywords/passwords after channel names following a space.\n"
"#channels = \"#blabouncer keyword,#test\"\n"
"# Channels to automatically join (defaults to none)\n"
"# Put channel keys/passwords after channel names (separated with a space)\n"
"channels = {\n"
" \"#blabouncer keyword\"\n"
" \"#test\"\n"
"}\n"
"\n"
"# Auto replay mode upon a bouncer client connecting\n"
"# \"none\" = Don't auto replay\n"
......
......@@ -1027,47 +1027,31 @@ int numclients(struct client *clients) {
// joined in the configuration file.
// Returns 1 on success or 0 on failure.
int joinautochannels(SSL *server_ssl, struct client *clients, struct settings *settings) {
if (strlen(settings->autochannels) == 0) {
if (settings->autochannels[0][0] == '\0') {
// None configured
debugprint(DEBUG_FULL, "joinautochannels(): none configured.\n");
return 1;
}
// Split string up into each channel
char tokens[MAXAUTOCHANLEN][MAXCHANLENGTH];
int counter = 0;
// Copy to a temporary string
char *strcopy = strdup(settings->autochannels);
// Keep track of initial pointer for free()ing later
char *strcopyPtr = strcopy;
char *token;
// Split on commas
while ((token = strsep(&strcopy, ",")) != NULL) {
if (*token == '\0') continue; // Skip consecutive matches
if (counter >= MAXAUTOCHANLEN) break; // Too many tokens
debugprint(DEBUG_FULL, " >> Auto channel: '%s', length '%ld'.\n", token, strlen(token));
// Copy into the token array (strlen + 1 to get the NULL terminator)
strncpy(tokens[counter], token, strlen(token) + 1);
if (strlen(tokens[counter]) > MAXCHANLENGTH) {
printf("error: channel name '%s' from configuration file too long, max length is '%d'.\n", tokens[counter], MAXCHANLENGTH);
debugprint(DEBUG_CRIT, "error: channel name '%s' from configuration file too long, max length is '%d'.\n", tokens[counter], MAXCHANLENGTH);
exit(1);
// Join all the channels
for (int i = 0; i < MAXCONFARR; i++) {
// Unless there are none left in the array
if (settings->autochannels[i][0] == '\0') {
debugprint(DEBUG_FULL, "joinautochannels(): Finishing joining %d channels.\n", i);
return 1;
}
counter++;
}
// Join all the channels
for (int i = 0; i < counter; i++) {
debugprint(DEBUG_FULL, "joinautochannels(): Joining '%s'.\n", tokens[i]);
debugprint(DEBUG_FULL, "joinautochannels(): Joining '%s'.\n", settings->autochannels[i]);
char joinmsg[MAXDATASIZE];
snprintf(joinmsg, MAXDATASIZE, "JOIN %s", tokens[i]);
sendtoserver(server_ssl, joinmsg, strlen(joinmsg), 0, clients, settings);
if (!snprintf(joinmsg, MAXDATASIZE, "JOIN %s", settings->autochannels[i])) {
fprintf(stderr, "joinautochannels(): Error while preparing JOIN message!\n");
debugprint(DEBUG_CRIT, "joinautochannels(): Error while preparing JOIN message\n");
joinmsg[0] = '\0';
} else {
sendtoserver(server_ssl, joinmsg, strlen(joinmsg), 0, clients, settings);
}
}
free(strcopyPtr);
// TODO - Can we fail here? Return 0 if so and make callers handle this if so.
return 1;
}
......
......@@ -22,11 +22,11 @@
#define MAXDATASIZE 513 // max number of bytes we can get at once (RFC2812 says 512, plus one for null terminator)
#define MAXCHANLENGTH 50 // 50 according to RFC 2811 and RFC 2822
#define MAXCHANKEYLEN 24 // Maxium channel key length, 23 determined by testing various clients/servers (plus one for null terminator)
#define MAXNICKLENGTH 64 // Randomly picked (TODO - is there an actual maximum number (ignoring the RFC preference of 9)?)
#define MAXUSERNAMELEN 64 // Randomly picked (TODO - is there an actual maximum username length?)
#define MAXREALNAMELEN 128 // Randomly picked (TODO - is there an actual maximum real name length?)
#define MAXPORTLEN 6 // Up to 65535, so 5 characters + 1 for null
#define MAXAUTOCHANLEN 1024 // Randomly picked maximum length of the auto channel list
#define CLIENTCODELEN 17 // Max length of a client code + 1 for null
#define MAXCLIENTCODES 64 // Max number of client codes to track
#define MAXCONFARR 10 // Max number of entries that a configuration array can have
......@@ -67,7 +67,7 @@ struct settings {
char ircusername[MAXUSERNAMELEN]; // (Is this also true for the username? Can the server change that?)
char ircrealname[MAXREALNAMELEN];
char password[MAXDATASIZE];
char autochannels[MAXAUTOCHANLEN];
char autochannels[MAXCONFARR][MAXDATASIZE]; // MAXDATASIZE instead of MAXCHANLENGTH + 1 + MAXCHANKEYLEN so getconfarr() only has one string size to deal with
char ircserver[HOST_NAME_MAX];
char ircserverport[MAXPORTLEN];
char ircserverpassword[MAXDATASIZE - 5]; // -5 for "PASS "
......
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