summaryrefslogtreecommitdiff
path: root/functions.c
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-12-22 20:16:57 +0000
committerLuke Bratch <luke@bratch.co.uk>2019-12-22 20:16:57 +0000
commit0883de2c491a8c79aec13d25bab429aea4362a10 (patch)
tree1c1e1063697f8b5e19d706ef3813f76aad21b70e /functions.c
parent85dd88a180043e991c19a4c93a6ce5c7fe0a6e88 (diff)
Significantly reduce memory usage by only initialising channel struct elements when they are used for the first time.
Diffstat (limited to 'functions.c')
-rw-r--r--functions.c126
1 files changed, 74 insertions, 52 deletions
diff --git a/functions.c b/functions.c
index 28c6691..54e7390 100644
--- a/functions.c
+++ b/functions.c
@@ -632,12 +632,12 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
return 0;
}
-int createchannel(struct channel *channels, char *name, char *topic, char *topicwho, char *topicwhen) {
+int createchannel(struct channel *channels, struct ircdstate *ircdstate, char *name, char *topic, char *topicwho, char *topicwhen) {
debugprint(DEBUG_FULL, "createchannel(): given '%s', '%s', '%s', and '%s'.\n", name, topic, topicwho, topicwhen);
// Make sure the channel doesn't already exist
- for (int i = 0; i < MAXCHANNELS; i++) {
- if (strncmp(channels[i].name, name, strlen(name)) == 0) {
+ for (int i = 0; i < ircdstate->maxchannelcount; i++) {
+ if (strlen(channels[i].name) == strlen(name) && strncmp(channels[i].name, name, strlen(name)) == 0) {
// Note that this may be happening because we just reconnected
debugprint(DEBUG_CRIT, "error: createchannel(): channel name already exists.\n");
return 0;
@@ -645,44 +645,66 @@ int createchannel(struct channel *channels, char *name, char *topic, char *topic
}
}
- // Find a free slot in the array (when the channel name is not set (0th character is '\0'))...
- for (int i = 0; i < MAXCHANNELS; i++) {
+ // Make sure we aren't in too many channels already
+ if (getchannelcount(channels, ircdstate->maxchannelcount) >= MAXCHANNELS - 1) {
+ debugprint(DEBUG_CRIT, "error: createchannel(): already in too many channels (MAXCHANNELS = %d!\n", MAXCHANNELS);
+ return 0;
+ }
+
+ int arrslot = -1;
+
+ // See if there's a free slot in the already used section of the channels array
+ for (int i = 0; i < ircdstate->maxchannelcount; i++) {
if (!channels[i].name[0]) {
- // ...and set the name and topic
- strncpy(channels[i].name, name, strlen(name));
- channels[i].name[strlen(name)] = '\0';
- debugprint(DEBUG_FULL, "createchannel(): name given was '%s', length '%ld'.\n", name, strlen(name));
- debugprint(DEBUG_FULL, "createchannel(): name set to '%s', length '%ld'.\n", channels[i].name, strlen(channels[i].name));
- strncpy(channels[i].topic, topic, strlen(topic));
- channels[i].topic[strlen(topic)] = '\0';
- debugprint(DEBUG_FULL, "createchannel(): topic given was '%s', length '%ld'.\n", topic, strlen(topic));
- debugprint(DEBUG_FULL, "createchannel(): topic set to '%s', length '%ld'.\n", channels[i].topic, strlen(channels[i].topic));
- strncpy(channels[i].topicwho, topicwho, strlen(topicwho));
- channels[i].topicwho[strlen(topicwho)] = '\0';
- strncpy(channels[i].topicwhen, topicwhen, strlen(topicwhen));
- channels[i].topicwhen[strlen(topicwhen)] = '\0';
- channels[i].gotnames = 0;
- // Set nicks to blank
- for (int j = 0; j < MAXCHANNICKS; j++) {
- channels[i].nicks[j][0] = '\0';
- }
- return 1;
+ // We found one, use this slot
+ arrslot = i;
+ debugprint(DEBUG_FULL, "createchannel(): re-using existing slot %d.\n", arrslot);
+ break;
}
}
+ // If we didn't find one, increment the total count and use the next unused slot
+ if (arrslot < 0) {
+ arrslot = ircdstate->maxchannelcount;
+ ircdstate->maxchannelcount++;
+ debugprint(DEBUG_FULL, "createchannel(): using new slot slot %d.\n", arrslot);
+ }
+
+ // If we got a valid slot...
+ if (arrslot >= 0) {
+ // ...set the name and topic
+ strncpy(channels[arrslot].name, name, strlen(name));
+ channels[arrslot].name[strlen(name)] = '\0';
+ debugprint(DEBUG_FULL, "createchannel(): name given was '%s', length '%ld'.\n", name, strlen(name));
+ debugprint(DEBUG_FULL, "createchannel(): name set to '%s', length '%ld'.\n", channels[arrslot].name, strlen(channels[arrslot].name));
+ strncpy(channels[arrslot].topic, topic, strlen(topic));
+ channels[arrslot].topic[strlen(topic)] = '\0';
+ debugprint(DEBUG_FULL, "createchannel(): topic given was '%s', length '%ld'.\n", topic, strlen(topic));
+ debugprint(DEBUG_FULL, "createchannel(): topic set to '%s', length '%ld'.\n", channels[arrslot].topic, strlen(channels[arrslot].topic));
+ strncpy(channels[arrslot].topicwho, topicwho, strlen(topicwho));
+ channels[arrslot].topicwho[strlen(topicwho)] = '\0';
+ strncpy(channels[arrslot].topicwhen, topicwhen, strlen(topicwhen));
+ channels[arrslot].topicwhen[strlen(topicwhen)] = '\0';
+ channels[arrslot].gotnames = 0;
+ // Set nicks to blank
+ for (int i = 0; i < MAXCHANNICKS; i++) {
+ channels[arrslot].nicks[i][0] = '\0';
+ }
+ return 1;
+ }
+
debugprint(DEBUG_CRIT, "error: createchannel() didn't create a channel\n");
// TODO - Make a failed return do something to callers
return 0;
}
-int setchanneltopicwhotime(struct channel *channels, char *channelname, char *who, char *when) {
+int setchanneltopicwhotime(struct channel *channels, int maxchannelcount, char *channelname, char *who, char *when) {
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): given '%s', '%s', and '%s'.\n", channelname, who, when);
-
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): who: '%s' with length '%ld'.\n", who, strlen(who));
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): when: '%s' with length '%ld'.\n", when, strlen(when));
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, channelname, strlen(channelname)) == 0) {
strncpy(channels[i].topicwho, who, strlen(who));
channels[i].topicwho[strlen(who)] = '\0';
@@ -696,10 +718,10 @@ int setchanneltopicwhotime(struct channel *channels, char *channelname, char *wh
return 0;
}
-int setchanneltopic(struct channel *channels, char *channelname, char *topic) {
+int setchanneltopic(struct channel *channels, int maxchannelcount, char *channelname, char *topic) {
debugprint(DEBUG_FULL, "setchanneltopic(): given '%s' and '%s'.\n", channelname, topic);
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, channelname, strlen(channelname)) == 0) {
strncpy(channels[i].topic, topic, strlen(topic));
channels[i].topic[strlen(topic)] = '\0';
@@ -711,10 +733,10 @@ int setchanneltopic(struct channel *channels, char *channelname, char *topic) {
return 0;
}
-int getchannelcount(struct channel *channels) {
+int getchannelcount(struct channel *channels, int maxchannelcount) {
int count = 0;
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (channels[i].name[0]) {
count++;
}
@@ -725,14 +747,14 @@ int getchannelcount(struct channel *channels) {
return count;
}
-int removechannel(struct channel *channels, char *name) {
+int removechannel(struct channel *channels, int maxchannelcount, char *name) {
debugprint(DEBUG_FULL, "removechannel(): given '%s'.\n", name);
// Clear its topic setter and timestamp...
- setchanneltopicwhotime(channels, name, "", "0");
+ setchanneltopicwhotime(channels, maxchannelcount, name, "", "0");
// Find the channel in the channel array...
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
// ..and NULL its name (0th character = '\0')
channels[i].name[0] = '\0';
@@ -753,9 +775,9 @@ int removechannel(struct channel *channels, char *name) {
// Check if we have the NAMES for the channel 'name' already.
// Return the 1 if we do, 0 if we don't, or -1 if there's an error.
-int channelgotnames(struct channel *channels, char *name) {
+int channelgotnames(struct channel *channels, int maxchannelcount, char *name) {
debugprint(DEBUG_FULL, "channelgotnames(): given '%s'.\n", name);
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if (channels[i].gotnames) {
debugprint(DEBUG_FULL, "channelgotnames(): channel '%s' gotnames was set, returning '%d'.\n", channels[i].name, channels[i].gotnames);
@@ -774,7 +796,7 @@ int channelgotnames(struct channel *channels, char *name) {
// Check if we are in a channel named "name" or not.
// Return 1 if we are, or 0 if not.
-int inchannel(struct channel *channels, char *name) {
+int inchannel(struct channel *channels, int maxchannelcount, char *name) {
// Make sure the name doesn't have any trailing CR or LF
// (But only if name is at least two characters long already)
if (strlen(name) >= 2) {
@@ -783,7 +805,7 @@ int inchannel(struct channel *channels, char *name) {
}
}
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
debugprint(DEBUG_FULL, "inchannel(): in channel '%s'.\n", name);
return 1;
@@ -798,9 +820,9 @@ int inchannel(struct channel *channels, char *name) {
// Returns the array index in the 'channels' array of the channel
// named 'channel'.
// Returns -1 if there was an error.
-int channelindex(struct channel *channels, char *name) {
+int channelindex(struct channel *channels, int maxchannelcount, char *name) {
debugprint(DEBUG_FULL, "channelindex(): given '%s'.\n", name);
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
return i;
}
@@ -883,7 +905,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set
extractnickfromprefix(tokens[0], 1);
// Check if we're currently in this channel or if the log line is from us
- if (!inchannel(channels, tokens[2] + offset) || strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0) {
+ if (!inchannel(channels, ircdstate->maxchannelcount, tokens[2] + offset) || 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;
@@ -1348,7 +1370,7 @@ void replacechar(char *str, char find, char replace) {
// Add nick (passed as a :nick!user@host) to channel 'channel'
// Returns 1 on success or 0 on failure
-int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels) {
+int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels, int maxchannelcount) {
debugprint(DEBUG_FULL, "addnicktochannel(): given '%s' and '%s'.\n", nickuserhost, channel);
// Get the nick from the prefix
@@ -1357,7 +1379,7 @@ int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels
// Make sure the channel exists
int chanfound = 0;
int chanindex;
- for (chanindex = 0; chanindex < MAXCHANNELS; chanindex++) {
+ for (chanindex = 0; chanindex < maxchannelcount; chanindex++) {
if (strlen(channels[chanindex].name) == strlen(channel) && !strcmp(channels[chanindex].name, channel)) {
chanfound = 1;
break;
@@ -1393,7 +1415,7 @@ int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels
// Remove nick (passed as a :nick!user@host) from channel 'channel'
// Returns 1 on success or 0 on failure
-int removenickfromchannel(char *nickuserhost, char *channel, struct channel *channels) {
+int removenickfromchannel(char *nickuserhost, char *channel, struct channel *channels, int maxchannelcount) {
debugprint(DEBUG_FULL, "removenickfromchannel(): given '%s' and '%s'.\n", nickuserhost, channel);
// Get the username from the prefix
@@ -1402,7 +1424,7 @@ int removenickfromchannel(char *nickuserhost, char *channel, struct channel *cha
// Make sure the channel exists
int chanfound = 0;
int chanindex;
- for (chanindex = 0; chanindex < MAXCHANNELS; chanindex++) {
+ for (chanindex = 0; chanindex < maxchannelcount; chanindex++) {
if (strlen(channels[chanindex].name) == strlen(channel) && !strcmp(channels[chanindex].name, channel)) {
chanfound = 1;
break;
@@ -1432,7 +1454,7 @@ int removenickfromchannel(char *nickuserhost, char *channel, struct channel *cha
// Remove nick (passed as a :nick!user@host) from all channels
// Returns 1 on success or 0 on failure
-int removenickfromallchannels(char *nickuserhost, struct channel *channels) {
+int removenickfromallchannels(char *nickuserhost, struct channel *channels, int maxchannelcount) {
debugprint(DEBUG_FULL, "removenickfromallchannels(): given '%s'.\n", nickuserhost);
// Get the nick from the prefix
@@ -1440,12 +1462,12 @@ int removenickfromallchannels(char *nickuserhost, struct channel *channels) {
// Make sure the nick has a length of at least one
if (strlen(nickuserhost) < 1) {
- debugprint(DEBUG_CRIT, "updatenickinallchannels(): nick has no length, returning 0!\n");
+ debugprint(DEBUG_CRIT, "removenickfromallchannels(): nick has no length, returning 0!\n");
return 0;
}
// Go through all channels and remove nick if present
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
// Don't bother checking this channel index if it isn't used
if (!channels[i].name[0]) {
continue;
@@ -1466,7 +1488,7 @@ int removenickfromallchannels(char *nickuserhost, struct channel *channels) {
// Update old nick (passed as a :nick!user@host) to 'newnick' in all channels
// Returns 1 on success or 0 on failure
-int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *channels) {
+int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *channels, int maxchannelcount) {
debugprint(DEBUG_FULL, "updatenickinallchannels(): given '%s' and '%s'.\n", nickuserhost, newnick);
// Get the nick from the prefix
@@ -1482,7 +1504,7 @@ int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *c
}
// Go through all channels and update nick if present
- for (int i = 0; i < MAXCHANNELS; i++) {
+ for (int i = 0; i < maxchannelcount; i++) {
// Go through all nicks in channel
for (int j = 0; j < MAXCHANNICKS; j++) {
// Update the nick in the channel if present
@@ -1498,7 +1520,7 @@ int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *c
// Populate our channels struct with all nicks in a RPL_NAMREPLY
// Returns 1 on success or 0 on failure
-int addnamereplytochannel(char *namereply, struct channel *channels) {
+int addnamereplytochannel(char *namereply, struct channel *channels, int maxchannelcount) {
//:irc.tghost.co.uk 353 blabounce = #blabouncer :blabounce bbnick ~@l_bratch @l_blabnc Hughbla Bratchbot ars
debugprint(DEBUG_FULL, "addnamereplytochannel(): given '%s'.\n", namereply);
@@ -1572,7 +1594,7 @@ int addnamereplytochannel(char *namereply, struct channel *channels) {
for (int i = 0; i < nickcount; i++) {
stripprefixesfromnick(nicks[i]);
// And add to the channel
- addnicktochannel(nicks[i], channelname, channels);
+ addnicktochannel(nicks[i], channelname, channels, maxchannelcount);
}
return 1;