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 */