From e8a8d7a440cc7c4af35d808b03df1d8cefe9942a Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sun, 18 Oct 2020 13:20:15 +0100 Subject: [PATCH] Refactor common channel iteration --- extensions/hide_uncommon_channels.c | 2 +- include/channel.h | 9 +++++ include/hook.h | 3 +- ircd/channel.c | 41 +++++++++++++++++++++ ircd/tgchange.c | 27 ++++---------- modules/m_whois.c | 55 +++++++---------------------- 6 files changed, 72 insertions(+), 65 deletions(-) diff --git a/extensions/hide_uncommon_channels.c b/extensions/hide_uncommon_channels.c index 586dc360..f9587b64 100644 --- a/extensions/hide_uncommon_channels.c +++ b/extensions/hide_uncommon_channels.c @@ -27,5 +27,5 @@ static void h_huc_doing_whois_channel_visibility(void *data_) { hook_data_channel_visibility *data = data_; - data->approved = data->approved && (!IsInvisible(data->targms->client_p) || data->clientms != NULL); + data->approved = data->approved && (!IsInvisible(data->target) || data->clientms != NULL); } diff --git a/include/channel.h b/include/channel.h index a9c07529..fe8c566c 100644 --- a/include/channel.h +++ b/include/channel.h @@ -200,6 +200,15 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p, #define EXTBAN_NOMATCH 0 /* valid mask, no match */ #define EXTBAN_MATCH 1 /* matches */ +int iter_comm_channels_step(rb_dlink_node *pos1, rb_dlink_node *pos2, + struct membership **ms1, struct membership **ms2, + struct Channel **chptr); + +#define ITER_COMM_CHANNELS(pos1, pos2, head1, head2, ms1, ms2, chptr) for ((pos1) = (head1), (pos2) = (head2); \ + iter_comm_channels_step((pos1), (pos2), &(ms1), &(ms2), &(chptr)); \ + (ms1) && ((pos1) = (pos1)->next), (ms2) && ((pos2) = (pos2)->next)) + + extern rb_dlink_list global_channel_list; void init_channels(void); diff --git a/include/hook.h b/include/hook.h index f3a2b88f..8bf8d9fc 100644 --- a/include/hook.h +++ b/include/hook.h @@ -110,9 +110,10 @@ typedef struct typedef struct { struct Client *client; + struct Client *target; struct Channel *chptr; struct membership *clientms; - struct membership *targms; + struct membership *targetms; int approved; } hook_data_channel_visibility; diff --git a/ircd/channel.c b/ircd/channel.c index 70eb5c2b..c09a717d 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -434,6 +434,47 @@ channel_pub_or_secret(struct Channel *chptr) return ("*"); } +int +iter_comm_channels_step(rb_dlink_node *pos1, rb_dlink_node *pos2, + struct membership **ms1, struct membership **ms2, + struct Channel **chptr) +{ + *ms1 = pos1 ? pos1->data : NULL; + *ms2 = pos2 ? pos2->data : NULL; + + /* we're at the end */ + if (*ms1 == NULL && *ms2 == NULL) + return 0; + + /* one side is at the end, keep stepping the other one */ + if (*ms1 == NULL || *ms2 == NULL) + { + *chptr = *ms1 != NULL ? (*ms1)->chptr : (*ms2)->chptr; + return 1; + } + + /* common channel */ + if ((*ms1)->chptr == (*ms2)->chptr) + { + *chptr = (*ms1)->chptr; + return 1; + } + + /* null out the channel that's further ahead; we'll get to it later */ + if (irccmp((*ms1)->chptr->chname, (*ms2)->chptr->chname) > 0) + { + *ms1 = NULL; + *chptr = (*ms2)->chptr; + return 1; + } + else + { + *ms2 = NULL; + *chptr = (*ms1)->chptr; + return 1; + } +} + /* channel_member_names() * * input - channel to list, client to list to, show endofnames diff --git a/ircd/tgchange.c b/ircd/tgchange.c index c8e595aa..1f4ebdc0 100644 --- a/ircd/tgchange.c +++ b/ircd/tgchange.c @@ -38,29 +38,14 @@ static int add_hashed_target(struct Client *source_p, uint32_t hashv); struct Channel * find_allowing_channel(struct Client *source_p, struct Client *target_p) { - rb_dlink_node *ps = source_p->user->channel.head; - rb_dlink_node *pt = target_p->user->channel.head; + rb_dlink_node *ps, *pt; + struct membership *ms, *mt; + struct Channel *chptr; - while (ps && pt) + ITER_COMM_CHANNELS(ps, pt, source_p->user->channel.head, target_p->user->channel.head, ms, mt, chptr) { - struct membership *ms = ps->data; - struct membership *mt = pt->data; - int d; - if (ms->chptr == mt->chptr) - { - if (is_chanop_voiced(ms)) - return ms->chptr; - ps = ps->next; - pt = pt->next; - continue; - } - d = irccmp(ms->chptr->chname, mt->chptr->chname); - if (d < 0) - ps = ps->next; - else if (d > 0) - pt = pt->next; - else - assert("different channels can't have equal names" && false); + if (ms != NULL && mt != NULL && is_chanop_voiced(ms)) + return chptr; } return NULL; } diff --git a/modules/m_whois.c b/modules/m_whois.c index d07f0fc6..281c6d85 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -224,7 +224,6 @@ static void single_whois(struct Client *source_p, struct Client *target_p, int operspy) { char buf[BUFSIZE]; - rb_dlink_node *ptr; int cur_len = 0; int mlen; char *t; @@ -268,56 +267,28 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) if (!IsService(target_p)) { hook_data_channel_visibility hdata_vis; - rb_dlink_node *ps = source_p->user->channel.head; - rb_dlink_node *pt = target_p->user->channel.head; + rb_dlink_node *ps, *pt; + struct Channel *chptr; + struct membership *ms, *mt; hdata_vis.client = source_p; + hdata_vis.target = target_p; - while (pt) + ITER_COMM_CHANNELS(ps, pt, source_p->user->channel.head, target_p->user->channel.head, ms, mt, chptr) { - struct membership *mt = pt->data; - int dir = 0; - if (ps != NULL) - { - struct membership *ms = ps->data; - if (ms->chptr == mt->chptr) - { - ps = ps->next; - pt = pt->next; - hdata_vis.chptr = mt->chptr; - hdata_vis.clientms = ms; - hdata_vis.targms = mt; - hdata_vis.approved = 1; - dir = 0; - } - else - { - dir = irccmp(ms->chptr->chname, mt->chptr->chname); - } - } - else - { - dir = 1; - } - if (dir < 0) - { - ps = ps->next; + if (mt == NULL) continue; - } - else if (dir > 0) - { - pt = pt->next; - hdata_vis.chptr = mt->chptr; - hdata_vis.clientms = NULL; - hdata_vis.targms = mt; - hdata_vis.approved = PubChannel(mt->chptr); - } + + hdata_vis.chptr = chptr; + hdata_vis.clientms = ms; + hdata_vis.targetms = mt; + hdata_vis.approved = ms != NULL || PubChannel(chptr); call_hook(doing_whois_channel_visibility_hook, &hdata_vis); if(hdata_vis.approved || operspy) { - if((cur_len + strlen(mt->chptr->chname) + 3) > (BUFSIZE - 5)) + if((cur_len + strlen(chptr->chname) + strlen("!@+ ")) > (BUFSIZE - strlen("\r\n"))) { sendto_one(source_p, "%s", buf); cur_len = mlen + extra_space; @@ -327,7 +298,7 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) tlen = sprintf(t, "%s%s%s ", hdata_vis.approved ? "" : "!", find_channel_status(mt, 1), - mt->chptr->chname); + chptr->chname); t += tlen; cur_len += tlen; }