1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-10 16:43:12 +02:00

Move isupport_check_for_changes() to the 'isupport' module.

This function was added a short while ago, and well it seems to be
able to be possible in a module. Since the 'isupport' module is mandatory
and this is ISUPPORT related, it is the right place.
Can't move isupport_snapshot() because modules might not be loaded yet
or things are currently unloading, i think. Not important anyway.

Also, make things work if there are more changes than would fit
on one isupport line. Although I didn't really test this..
Ended up splitting things in 3 helper functions to avoid some
goto and/or duplicate code and stuff. The alternative was, surprisingly,
even more ugly.
This commit is contained in:
Bram Matthys
2025-09-20 15:02:42 +02:00
parent 595f56007b
commit dbb2d1a5c8
6 changed files with 129 additions and 81 deletions
+3 -1
View File
@@ -944,6 +944,7 @@ extern MODVAR char *(*utf8_convert_confusables)(const char *i, char *obuf, int o
extern MODVAR const char *(*utf8_get_block_name)(int i);
extern MODVAR int (*utf8_get_block_number)(const char *name);
extern MODVAR void (*send_isupport)(Client *client);
extern MODVAR void (*isupport_check_for_changes)(void);
/* /Efuncs */
/* TLS functions */
@@ -1061,8 +1062,9 @@ extern PendingNet *find_pending_net_by_sid_butone(const char *sid, Client *exemp
extern Client *find_pending_net_duplicates(Client *cptr, Client **srv, char **sid);
extern MODVAR char serveropts[];
extern MODVAR char *ISupportStrings[];
extern MODVAR ISupport *ISupports;
extern MODVAR ISupport *ISupports_old;
extern void isupport_snapshot(void);
extern void isupport_check_for_changes(void);
extern void read_packet(int fd, int revents, void *data);
extern int process_packet(Client *cptr, char *readbuf, int length, int killsafely);
extern int parse_chanmode(ParseMode *pm, const char *modebuf_in, const char *parabuf_in);
+1
View File
@@ -2781,6 +2781,7 @@ enum EfunctionType {
EFUNC_UTF8_GET_BLOCK_NAME,
EFUNC_UTF8_GET_BLOCK_NUMBER,
EFUNC_SEND_ISUPPORT,
EFUNC_ISUPPORT_CHECK_FOR_CHANGES,
};
/* Module flags */
+2
View File
@@ -209,6 +209,8 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia
#define USERHOST_REPLYLEN (NICKLEN+HOSTLEN+USERLEN+5)
#define ISUPPORTLEN BUFSIZE-HOSTLEN-NICKLEN-39
/* NOTE: this must be down here so the stuff from struct.h IT uses works */
#include "whowas.h"
+2
View File
@@ -189,6 +189,7 @@ char *(*utf8_convert_confusables)(const char *i, char *obuf, int olen);
const char *(*utf8_get_block_name)(int i);
int (*utf8_get_block_number)(const char *name);
void (*send_isupport)(Client *client);
void (*isupport_check_for_changes)(void);
Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
{
@@ -520,4 +521,5 @@ void efunctions_init(void)
efunc_init_function(EFUNC_UTF8_GET_BLOCK_NAME, utf8_get_block_name, utf8_get_block_name_default_handler, 0);
efunc_init_function(EFUNC_UTF8_GET_BLOCK_NUMBER, utf8_get_block_number, utf8_get_block_number_default_handler, 0);
efunc_init_function(EFUNC_SEND_ISUPPORT, send_isupport, NULL, 0);
efunc_init_function(EFUNC_ISUPPORT_CHECK_FOR_CHANGES, isupport_check_for_changes, NULL, 0);
}
-80
View File
@@ -256,7 +256,6 @@ void ISupportDel(ISupport *isupport)
void make_isupportstrings(void)
{
int i;
#define ISUPPORTLEN BUFSIZE-HOSTLEN-NICKLEN-39
int bufsize = ISUPPORTLEN;
int tokcnt = 0;
ISupport *isupport;
@@ -352,82 +351,3 @@ void isupport_snapshot(void)
AppendListItem(f, ISupports_old);
}
}
ISupport *isupport_find(ISupport *list, const char *name)
{
for (; list; list = list->next)
if (!strcmp(list->token, name))
return list;
return NULL;
}
void isupport_check_for_changes(void)
{
Client *acptr;
ISupport *n; // iterator for "new isupports"
ISupport *o; // iterator for "old isupports"
char buf[512], addstr[512];
if (!iConf.send_isupport_updates)
return;
buf[0] = '\0';
/* New tokens and changed values */
for (n = ISupports; n; n = n->next)
{
o = isupport_find(ISupports_old, n->token);
if (!o ||
(!o->value && n->value) ||
(n->value && !o->value) ||
(n->value && o->value && strcmp(n->value, o->value)))
{
/* New or changed */
if (n->value)
{
snprintf(addstr, sizeof(addstr), "%s=%s",
n->token, n->value);
} else {
strlcpy(addstr, n->token, sizeof(addstr));
}
if (strlen(buf) + strlen(addstr) < 400)
{
if (*buf)
strlcat(buf, " ", sizeof(buf));
strlcat(buf, addstr, sizeof(buf));
} else {
abort();
}
}
}
/* Removed tokens */
for (o = ISupports_old; o; o = o->next)
{
n = isupport_find(ISupports, o->token);
if (!n)
{
/* Removed */
strlcpy(addstr, "-", sizeof(addstr));
strlcpy(addstr, o->token, sizeof(addstr));
if (strlen(buf) + strlen(addstr) < 400)
{
if (*buf)
strlcat(buf, " ", sizeof(buf));
strlcat(buf, addstr, sizeof(buf));
} else {
abort();
}
}
}
if (*buf)
{
// batch! well, for some :D
list_for_each_entry(acptr, &lclient_list, lclient_node)
{
sendto_one(acptr, NULL, ":%s 005 %s %s",
me.name, acptr->name, buf);
}
}
}
+121
View File
@@ -27,6 +27,7 @@
/* Forward declarations */
void _send_isupport(Client *client);
void _isupport_check_for_changes(void);
ModuleHeader MOD_HEADER
={
@@ -42,6 +43,7 @@ MOD_TEST()
MARK_AS_OFFICIAL_MODULE(modinfo);
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_ISUPPORT, _send_isupport);
EfunctionAddVoid(modinfo->handle, EFUNC_ISUPPORT_CHECK_FOR_CHANGES, _isupport_check_for_changes);
return MOD_SUCCESS;
}
@@ -107,3 +109,122 @@ void _send_isupport(Client *client)
safe_free_message_tags(mtags);
}
}
ISupport *isupport_find_ex(ISupport *list, const char *name)
{
for (; list; list = list->next)
if (!strcmp(list->token, name))
return list;
return NULL;
}
void isupport_check_for_changes_send(const char *addstr, char *buf, size_t buflen, char *batch, MessageTag *mtags, int *changes, int *buffered_changes)
{
Client *acptr;
if (!*buf)
return;
list_for_each_entry(acptr, &lclient_list, lclient_node)
{
if (HasCapability(acptr, "draft/extended-isupport") && HasCapability(acptr, "batch"))
{
sendtaggednumericfmt(acptr, mtags, RPL_ISUPPORT, "%s :are supported by this server", buf);
} else {
sendnumeric(acptr, RPL_ISUPPORT, buf);
}
}
*buf = '\0';
*buffered_changes = 0;
}
void isupport_check_for_changes_one(const char *addstr, char *buf, size_t buflen, char *batch, MessageTag *mtags, int *changes, int *buffered_changes)
{
Client *acptr;
if (*changes == 0)
{
/* First change, need to start the batch */
list_for_each_entry(acptr, &lclient_list, lclient_node)
if (HasCapability(acptr, "draft/extended-isupport") && HasCapability(acptr, "batch"))
sendto_one(acptr, NULL, ":%s BATCH +%s draft/isupport", me.name, batch);
}
*changes = *changes + 1;
*buffered_changes = *buffered_changes + 1;
if ((strlen(buf) + strlen(addstr) >= ISUPPORTLEN) || (*buffered_changes == 13))
isupport_check_for_changes_send(addstr, buf, buflen, batch, mtags, changes, buffered_changes);
/* Append */
if (*buf)
strlcat(buf, " ", buflen);
strlcat(buf, addstr, buflen);
}
void _isupport_check_for_changes(void)
{
Client *acptr;
MessageTag *mtags = NULL;
char batch[BATCHLEN+1];
ISupport *n; // iterator for "new isupports"
ISupport *o; // iterator for "old isupports"
char buf[512], addstr[512];
int changes = 0, bc = 0;
if (!iConf.send_isupport_updates)
return;
buf[0] = '\0';
generate_batch_id(batch);
mtags = safe_alloc(sizeof(MessageTag));
safe_strdup(mtags->name, "batch");
safe_strdup(mtags->value, batch);
/* New tokens and changed values */
for (n = ISupports; n; n = n->next)
{
o = isupport_find_ex(ISupports_old, n->token);
if (!o ||
(!o->value && n->value) ||
(n->value && !o->value) ||
(n->value && o->value && strcmp(n->value, o->value)))
{
/* New or changed */
if (n->value)
{
snprintf(addstr, sizeof(addstr), "%s=%s",
n->token, n->value);
} else {
strlcpy(addstr, n->token, sizeof(addstr));
}
isupport_check_for_changes_one(addstr, buf, sizeof(buf), batch, mtags, &changes, &bc);
}
}
/* Removed tokens */
for (o = ISupports_old; o; o = o->next)
{
n = isupport_find_ex(ISupports, o->token);
if (!n)
{
/* Removed */
strlcpy(addstr, "-", sizeof(addstr));
strlcpy(addstr, o->token, sizeof(addstr));
isupport_check_for_changes_one(addstr, buf, sizeof(buf), batch, mtags, &changes, &bc);
}
}
isupport_check_for_changes_send(NULL, buf, sizeof(buf), batch, mtags, &changes, &bc);
if (changes)
{
/* End the batch (for those clients who received a batch, that is) */
list_for_each_entry(acptr, &lclient_list, lclient_node)
if (HasCapability(acptr, "draft/extended-isupport") && HasCapability(acptr, "batch"))
sendto_one(acptr, NULL, ":%s BATCH -%s", me.name, batch);
}
safe_free_message_tags(mtags);
}