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:
+3
-1
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user