From 91b1278224692433c4ec42ee04e06cf64373dde3 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Mon, 27 Apr 2020 00:14:56 +0100 Subject: [PATCH 1/3] Implement hook priorities --- include/hook.h | 11 +++++++++++ include/modules.h | 2 +- ircd/hook.c | 48 ++++++++++++++++++++++++++++++++++++++++++----- ircd/modules.c | 5 +++++ 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/hook.h b/include/hook.h index 099eeec7..e185d46b 100644 --- a/include/hook.h +++ b/include/hook.h @@ -11,6 +11,16 @@ typedef struct rb_dlink_list hooks; } hook; +enum hook_priority +{ + HOOK_LOWEST = 10, + HOOK_LOW = 20, + HOOK_NORMAL = 30, + HOOK_HIGH = 40, + HOOK_HIGHEST = 50, + HOOK_MONITOR = 100 +}; + typedef void (*hookfn) (void *data); extern int h_iosend_id; @@ -39,6 +49,7 @@ extern int h_rehash; void init_hook(void); int register_hook(const char *name); void add_hook(const char *name, hookfn fn); +void add_hook_prio(const char *name, hookfn fn, enum hook_priority priority); void remove_hook(const char *name, hookfn fn); void call_hook(int id, void *arg); diff --git a/include/modules.h b/include/modules.h index 49539865..9a362c11 100644 --- a/include/modules.h +++ b/include/modules.h @@ -70,9 +70,9 @@ typedef struct { const char *hapi_name; hookfn fn; + enum hook_priority priority; } mapi_hfn_list_av1; - #define MAPI_CAP_CLIENT 1 #define MAPI_CAP_SERVER 2 diff --git a/ircd/hook.c b/ircd/hook.c index 70defd1c..bda9fc0c 100644 --- a/ircd/hook.c +++ b/ircd/hook.c @@ -42,6 +42,13 @@ hook *hooks; #define HOOK_INCREMENT 1000 +struct hook_entry +{ + rb_dlink_node node; + hookfn fn; + enum hook_priority priority; +}; + int num_hooks = 0; int last_hook = 0; int max_hooks = HOOK_INCREMENT; @@ -174,11 +181,34 @@ register_hook(const char *name) void add_hook(const char *name, hookfn fn) { + add_hook_prio(name, fn, HOOK_NORMAL); +} + +/* add_hook_prio() + * Adds a hook with the specified priority + */ +void +add_hook_prio(const char *name, hookfn fn, enum hook_priority priority) +{ + rb_dlink_node *ptr; + struct hook_entry *entry = rb_malloc(sizeof *entry); int i; i = register_hook(name); + entry->fn = fn; + entry->priority = priority; - rb_dlinkAddAlloc(fn, &hooks[i].hooks); + RB_DLINK_FOREACH(ptr, &hooks[i].hooks.head) + { + struct hook_entry *o = ptr->data; + if (entry->priority < o->priority) + { + rb_dlinkAddBefore(ptr, entry, &entry->node, &hooks[i].hooks); + return; + } + } + + rb_dlinkAddTail(entry, &entry->node, &hooks[i].hooks); } /* remove_hook() @@ -187,12 +217,21 @@ add_hook(const char *name, hookfn fn) void remove_hook(const char *name, hookfn fn) { + rb_dlink_node *ptr, *scratch; int i; if((i = find_hook(name)) < 0) return; - rb_dlinkFindDestroy(fn, &hooks[i].hooks); + RB_DLINK_FOREACH_SAFE(ptr, scratch, &hooks[i].hooks.head) + { + struct hook_entry *entry = ptr->data; + if (entry->fn == fn) + { + rb_dlinkDelete(ptr, &hooks[i].hooks); + return; + } + } } /* call_hook() @@ -201,7 +240,6 @@ remove_hook(const char *name, hookfn fn) void call_hook(int id, void *arg) { - hookfn fn; rb_dlink_node *ptr; /* The ID we were passed is the position in the hook table of this @@ -209,8 +247,8 @@ call_hook(int id, void *arg) */ RB_DLINK_FOREACH(ptr, hooks[id].hooks.head) { - fn = ptr->data; - fn(arg); + struct hook_entry *entry = ptr->data; + entry->fn(arg); } } diff --git a/ircd/modules.c b/ircd/modules.c index 7a246cbe..6602a21d 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -586,7 +586,12 @@ load_a_module(const char *path, bool warn, int origin, bool core) { mapi_hfn_list_av1 *m; for (m = mheader->mapi_hfn_list; m->hapi_name; ++m) + { + int priority = m->priority; + if (priority == 0) + priority = HOOK_NORMAL; add_hook(m->hapi_name, m->fn); + } } /* New in MAPI v2 - version replacement */ From c500b0bdb56a311859461b7b6ac68bdaaf6330e3 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Mon, 27 Apr 2020 00:42:53 +0100 Subject: [PATCH 2/3] Add priorities to some hooks --- extensions/invite_notify.c | 2 +- extensions/m_webirc.c | 3 ++- extensions/override.c | 8 ++++---- extensions/override_kick_immunity.c | 2 +- ircd/hook.c | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/extensions/invite_notify.c b/extensions/invite_notify.c index bc7c84f7..19708f90 100644 --- a/extensions/invite_notify.c +++ b/extensions/invite_notify.c @@ -13,7 +13,7 @@ static void m_invited(struct MsgBuf *, struct Client *, struct Client *, int, co static unsigned int CAP_INVITE_NOTIFY; mapi_hfn_list_av1 inv_notify_hfnlist[] = { - { "invite", hook_invite }, + { "invite", hook_invite, HOOK_MONITOR }, { NULL, NULL } }; diff --git a/extensions/m_webirc.c b/extensions/m_webirc.c index 04f59c96..2937189e 100644 --- a/extensions/m_webirc.c +++ b/extensions/m_webirc.c @@ -66,7 +66,8 @@ mapi_clist_av1 webirc_clist[] = { &webirc_msgtab, NULL }; static void new_local_user(void *data); mapi_hfn_list_av1 webirc_hfnlist[] = { - { "new_local_user", (hookfn) new_local_user }, + /* unintuitive but correct--we want to be called first */ + { "new_local_user", (hookfn) new_local_user, HOOK_LOWEST }, { NULL, NULL } }; diff --git a/extensions/override.c b/extensions/override.c index 20110a65..91b3d6eb 100644 --- a/extensions/override.c +++ b/extensions/override.c @@ -34,10 +34,10 @@ static void handle_client_exit(void *data); mapi_hfn_list_av1 override_hfnlist[] = { { "umode_changed", (hookfn) check_umode_change }, - { "get_channel_access", (hookfn) hack_channel_access }, - { "can_join", (hookfn) hack_can_join }, - { "can_kick", (hookfn) hack_can_kick }, - { "can_send", (hookfn) hack_can_send }, + { "get_channel_access", (hookfn) hack_channel_access, HOOK_HIGHEST }, + { "can_join", (hookfn) hack_can_join, HOOK_HIGHEST }, + { "can_kick", (hookfn) hack_can_kick, HOOK_HIGHEST }, + { "can_send", (hookfn) hack_can_send, HOOK_HIGHEST }, { "client_exit", (hookfn) handle_client_exit }, { NULL, NULL } }; diff --git a/extensions/override_kick_immunity.c b/extensions/override_kick_immunity.c index b6f7e518..df10ae8b 100644 --- a/extensions/override_kick_immunity.c +++ b/extensions/override_kick_immunity.c @@ -14,7 +14,7 @@ static const char override_kick_immunity_desc[] = static void can_kick(void *data); mapi_hfn_list_av1 override_kick_immunity_hfnlist[] = { - { "can_kick", (hookfn) can_kick }, + { "can_kick", (hookfn) can_kick, HOOK_HIGHEST }, { NULL, NULL } }; diff --git a/ircd/hook.c b/ircd/hook.c index bda9fc0c..bd6f39eb 100644 --- a/ircd/hook.c +++ b/ircd/hook.c @@ -198,7 +198,7 @@ add_hook_prio(const char *name, hookfn fn, enum hook_priority priority) entry->fn = fn; entry->priority = priority; - RB_DLINK_FOREACH(ptr, &hooks[i].hooks.head) + RB_DLINK_FOREACH(ptr, hooks[i].hooks.head) { struct hook_entry *o = ptr->data; if (entry->priority < o->priority) @@ -223,7 +223,7 @@ remove_hook(const char *name, hookfn fn) if((i = find_hook(name)) < 0) return; - RB_DLINK_FOREACH_SAFE(ptr, scratch, &hooks[i].hooks.head) + RB_DLINK_FOREACH_SAFE(ptr, scratch, hooks[i].hooks.head) { struct hook_entry *entry = ptr->data; if (entry->fn == fn) From c6b2dacad4614246fe0860b361c3e9b8c7414a2a Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Mon, 27 Apr 2020 16:36:40 +0100 Subject: [PATCH 3/3] hook: Use old insertion order for equal priority --- ircd/hook.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ircd/hook.c b/ircd/hook.c index bd6f39eb..2721a35c 100644 --- a/ircd/hook.c +++ b/ircd/hook.c @@ -201,7 +201,7 @@ add_hook_prio(const char *name, hookfn fn, enum hook_priority priority) RB_DLINK_FOREACH(ptr, hooks[i].hooks.head) { struct hook_entry *o = ptr->data; - if (entry->priority < o->priority) + if (entry->priority <= o->priority) { rb_dlinkAddBefore(ptr, entry, &entry->node, &hooks[i].hooks); return;