From 0883de2c491a8c79aec13d25bab429aea4362a10 Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Sun, 22 Dec 2019 20:16:57 +0000 Subject: Significantly reduce memory usage by only initialising channel struct elements when they are used for the first time. --- message.c | 56 ++++++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 30 deletions(-) (limited to 'message.c') diff --git a/message.c b/message.c index 8431c31..e30a247 100644 --- a/message.c +++ b/message.c @@ -116,14 +116,11 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int } // Next re-join channels - // Storing separately so we can skip over blank channels. - int channelcount = getchannelcount(channels); - // Join all the channels and make a note of the channel count - for (int i = 0; i < channelcount; i++) { - // Skip this one and increment channelcount if it's a blank channel + // Join all the channels + for (int i = 0; i < ircdstate->maxchannelcount; i++) { + // Skip this one if it's a blank channel if (!channels[i].name[0]) { - debugprint(DEBUG_FULL, "Reconnection: Skipping channel[%d], incrementing channelcount.\n", i); - channelcount++; + debugprint(DEBUG_FULL, "Reconnection: Skipping blank channel channel[%d].\n", i); continue; } @@ -197,13 +194,13 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int debugprint(DEBUG_FULL, "Server JOIN: nick is ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick); // TODO - Saner way to initialise this since we don't have the variables yet? // TODO - Defaulting to type '=' which is "public" since I don't know what else to guess. - createchannel(channels, tokens[2], "TOPIC", "TOPICWHO", "0"); + createchannel(channels, ircdstate, tokens[2], "TOPIC", "TOPICWHO", "0"); } else { debugprint(DEBUG_FULL, "Server JOIN: nick is NOT ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick); } // Add the JOINing nick to our local channel struct - if (!addnicktochannel(tokens[0], tokens[2], channels)) { + if (!addnicktochannel(tokens[0], tokens[2], channels, ircdstate->maxchannelcount)) { debugprint(DEBUG_CRIT, "Failed to add nick to channel struct.\n"); } @@ -236,13 +233,13 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int extractnickfromprefix(prefixcopy, 1); if (strncmp(prefixcopy, ircdstate->ircnick, strlen(tokens[0])) == 0) { debugprint(DEBUG_FULL, "Server PART: nick is ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick); - removechannel(channels, tokens[2]); + removechannel(channels, ircdstate->maxchannelcount, tokens[2]); } else { debugprint(DEBUG_FULL, "Server PART: nick is NOT ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick); } // Remove the PARTing nick from our local channel struct - if (!removenickfromchannel(tokens[0], tokens[2], channels)) { + if (!removenickfromchannel(tokens[0], tokens[2], channels, ircdstate->maxchannelcount)) { debugprint(DEBUG_CRIT, "Failed to remove nick from channel struct.\n"); } @@ -280,7 +277,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int char quitnick[MAXDATASIZE]; strcpy(quitnick, tokens[0]); extractnickfromprefix(quitnick, 1); - for (int i = 0; i < MAXCHANNELS; i++) { + for (int i = 0; i < ircdstate->maxchannelcount; i++) { if (channels[i].name[0]) { for (int j = 0; j < MAXCHANNICKS; j++) { if (strlen(channels[i].nicks[j]) == strlen(quitnick) && !strcmp(channels[i].nicks[j], quitnick)) { @@ -295,7 +292,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int } // Remove the QUITting nick from our local channel struct - if (!removenickfromallchannels(tokens[0], channels)) { + if (!removenickfromallchannels(tokens[0], channels, ircdstate->maxchannelcount)) { debugprint(DEBUG_CRIT, "Failed to remove nick from channel structs.\n"); } @@ -306,9 +303,9 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int // Server 331 (RPL_NOTOPIC) the topic is blank which we track by having a set timestamp of 0 if (strncmp(tokens[1], "331", strlen(tokens[1])) == 0) { // Might as well blank our current topic value - setchanneltopic(channels, tokens[3], ""); + setchanneltopic(channels, ircdstate->maxchannelcount, tokens[3], ""); // Set the topic timestamp to 0 which we use to determine an "unset" topic when new clients connect - setchanneltopicwhotime(channels, tokens[3], "", "0"); + setchanneltopicwhotime(channels, ircdstate->maxchannelcount, tokens[3], "", "0"); // Server 332 (RPL_TOPIC) set the channel topic } else if (strncmp(tokens[1], "332", strlen(tokens[1])) == 0) { debugprint(DEBUG_FULL, "Server 332 (RPL_TOPIC) found, extracting topic and storing in channel struct.\n"); @@ -316,17 +313,17 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int // Copy to a temporary string so we still have the original in case we need it char *topiccopy = strdup(str); extractfinalparameter(topiccopy); - setchanneltopic(channels, tokens[3], topiccopy); + setchanneltopic(channels, ircdstate->maxchannelcount, tokens[3], topiccopy); free(topiccopy); // Server 333 (RPL_TOPICWHOTIME) set the channel topic setter and the time it was set } else if (strncmp(tokens[1], "333", strlen(tokens[1])) == 0) { debugprint(DEBUG_FULL, "Server 333 (RPL_TOPICWHOTIME) found, extracting who and when, and storing in channel struct.\n"); - setchanneltopicwhotime(channels, tokens[3], tokens[4], tokens[5]); + setchanneltopicwhotime(channels, ircdstate->maxchannelcount, tokens[3], tokens[4], tokens[5]); // Server 353 (RPL_NAMREPLY), relay to all clients if we've just JOINed the channel, or relay to any clients // who were pending RPL_NAMREPLYs if it's an existing channel. } else if (strncmp(tokens[1], "353", strlen(tokens[1])) == 0) { // It must be a new channel and we don't have the NAMES - if (!channelgotnames(channels, tokens[4])) { + if (!channelgotnames(channels, ircdstate->maxchannelcount, tokens[4])) { debugprint(DEBUG_FULL, "Server 353 received for a new channel, sending to all clients.\n"); // Relay to all clients sendtoallclients(clients, str, sourcefd, settings); @@ -344,7 +341,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int } // Update our local channels struct with all nicks from this RPL_NAMREPLY - if (!addnamereplytochannel(str, channels)) { + if (!addnamereplytochannel(str, channels, ircdstate->maxchannelcount)) { debugprint(DEBUG_CRIT, "Failed to add RPL_NAMREPLY to channels.\n"); } @@ -354,10 +351,10 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int } else if (strncmp(tokens[1], "366", strlen(tokens[1])) == 0) { int channelelement; // It must be a new channel and we don't have the NAMES - if (!(channelelement = channelgotnames(channels, tokens[3]))) { + if (!(channelelement = channelgotnames(channels, ircdstate->maxchannelcount, tokens[3]))) { debugprint(DEBUG_FULL, "Server 366 received for a new channel, sending to all clients and set as got names.\n"); // We have the names now! - channels[channelindex(channels, tokens[3])].gotnames = 1; + channels[channelindex(channels, ircdstate->maxchannelcount, tokens[3])].gotnames = 1; // Relay to all clients sendtoallclients(clients, str, sourcefd, settings); } else { @@ -389,7 +386,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int // Copy to a temporary string so we still have the original in case we need it char *topiccopy = strdup(str); extractfinalparameter(topiccopy); - setchanneltopic(channels, tokens[2], topiccopy); + setchanneltopic(channels, ircdstate->maxchannelcount, tokens[2], topiccopy); // Extract the author and get the current timestamp @@ -405,7 +402,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int snprintf(timenowstr, timenowlen + 1, "%ld", timenow); // Actually set the author and timestamp - setchanneltopicwhotime(channels, tokens[2], prefixcopy, timenowstr); + setchanneltopicwhotime(channels, ircdstate->maxchannelcount, tokens[2], prefixcopy, timenowstr); // And then finally relay to all clients sendtoallclients(clients, str, sourcefd, settings); @@ -493,7 +490,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int char oldnick[MAXDATASIZE]; strcpy(oldnick, tokens[0]); extractnickfromprefix(oldnick, 1); - for (int i = 0; i < MAXCHANNELS; i++) { + for (int i = 0; i < ircdstate->maxchannelcount; i++) { if (channels[i].name[0]) { for (int j = 0; j < MAXCHANNICKS; j++) { if (strlen(channels[i].nicks[j]) == strlen(oldnick) && !strcmp(channels[i].nicks[j], oldnick)) { @@ -508,7 +505,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int } // Update old nick to the new nick in our local channel struct - if (!updatenickinallchannels(tokens[0], tokens[2], channels)) { + if (!updatenickinallchannels(tokens[0], tokens[2], channels, ircdstate->maxchannelcount)) { debugprint(DEBUG_CRIT, "Failed to update old nick to new nick in channels.\n"); } @@ -970,19 +967,18 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :\"BLABOUNCER QUIT [quit message]\" (To quit blabouncer, optionally sending [quit message] to the server.)", ircdstate->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); - // Get the channel count so we can enumerate over all channels. - // Storing separately so we can skip over blank channels. - int channelcount = getchannelcount(channels); + // Get the channel count so we can iterate over all channels. + int channelcount = getchannelcount(channels, ircdstate->maxchannelcount); // Set the client as pending RPL_NAMREPLYs for 'channelcount' channels debugprint(DEBUG_FULL, "Setting pendingnames to '%d' for client with fd '%d'.\n", channelcount, sourcefd); clients[arrindex(clients, sourcefd)].pendingnames = channelcount; // Get client to join channels, and tell client about those channels - for (int i = 0; i < channelcount; i++) { + for (int i = 0; i < ircdstate->maxchannelcount; i++) { debugprint(DEBUG_FULL, "JOINing channel[%d] out of %d.\n", i, channelcount); // Skip this one and increment channelcount if it's a blank channel if (!channels[i].name[0]) { - debugprint(DEBUG_FULL, "Skipping channel[%d], incrementing channelcount.\n", i); + debugprint(DEBUG_FULL, "Actually, skipping blank channel channel[%d].\n", i); channelcount++; continue; } -- cgit v1.2.3