From 8e9c6a75905ad9feb5d374e67b4c9ab5f6e8a514 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 6 Mar 2016 16:53:03 -0600 Subject: [PATCH] modules: add new MAPI V2 MAPI V1 is still supported for legacy modules, but it is highly recommended to update to MAPI V2. It includes support for capability tables, module descriptions, and implicit versions. --- include/modules.h | 58 ++++++++++++++----- ircd/modules.c | 141 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 179 insertions(+), 20 deletions(-) diff --git a/include/modules.h b/include/modules.h index 9c8da718..6c0f7ccf 100644 --- a/include/modules.h +++ b/include/modules.h @@ -28,7 +28,7 @@ #include "setup.h" #include "parse.h" -#define MAPI_RATBOX 1 +#define MAPI_CHARYBDIS 2 #include @@ -42,12 +42,13 @@ struct module lt_dlhandle address; int core; int mapi_version; - void * mapi_header; /* actually struct mapi_mheader_av */ + void *mapi_header; /* actually struct mapi_mheader_av */ }; #define MAPI_MAGIC_HDR 0x4D410000 #define MAPI_V1 (MAPI_MAGIC_HDR | 0x1) +#define MAPI_V2 (MAPI_MAGIC_HDR | 0x2) #define MAPI_MAGIC(x) ((x) & 0xffff0000) #define MAPI_VERSION(x) ((x) & 0x0000ffff) @@ -56,31 +57,58 @@ typedef struct Message* mapi_clist_av1; typedef struct { - const char * hapi_name; - int * hapi_id; + const char *hapi_name; + int *hapi_id; } mapi_hlist_av1; typedef struct { - const char * hapi_name; - hookfn fn; + const char *hapi_name; + hookfn fn; } mapi_hfn_list_av1; + +#define MAPI_CAP_CLIENT 1 +#define MAPI_CAP_SERVER 2 + +typedef struct +{ + int cap_index; /* Which cap index does this belong to? */ + const char *cap_name; /* Capability name */ + void *cap_ownerdata; /* Not used much but why not... */ + int *cap_id; /* May be set to non-NULL to store cap id */ +} mapi_cap_list_av2; + struct mapi_mheader_av1 { - int mapi_version; /* Module API version */ - int (*mapi_register) (void); /* Register function; - ret -1 = failure (unload) */ - void (*mapi_unregister) (void); /* Unregister function. */ - mapi_clist_av1 * mapi_command_list; /* List of commands to add. */ - mapi_hlist_av1 * mapi_hook_list; /* List of hooks to add. */ - mapi_hfn_list_av1 *mapi_hfn_list; /* List of hook_add_hook's to do */ - const char * mapi_module_version; /* Module's version (freeform) */ + int mapi_version; /* Module API version */ + int (*mapi_register)(void); /* Register function; ret -1 = failure (unload) */ + void (*mapi_unregister)(void); /* Unregister function. */ + mapi_clist_av1 *mapi_command_list; /* List of commands to add. */ + mapi_hlist_av1 *mapi_hook_list; /* List of hooks to add. */ + mapi_hfn_list_av1 *mapi_hfn_list; /* List of hook_add_hook's to do */ + const char *mapi_module_version; /* Module's version (freeform) */ }; -#define DECLARE_MODULE_AV1(name,reg,unreg,cl,hl,hfnlist, v) \ +struct mapi_mheader_av2 +{ + int mapi_version; /* Module API version */ + int (*mapi_register)(void); /* Register function; ret -1 = failure (unload) */ + void (*mapi_unregister)(void); /* Unregister function. */ + mapi_clist_av1 *mapi_command_list; /* List of commands to add. */ + mapi_hlist_av1 *mapi_hook_list; /* List of hooks to add. */ + mapi_hfn_list_av1 *mapi_hfn_list; /* List of hook_add_hook's to do */ + mapi_cap_list_av2 *mapi_cap_list; /* List of CAPs to add */ + const char *mapi_module_version; /* Module's version (freeform), replaced with ircd version if NULL */ + const char *mapi_module_description; /* Module's description (freeform) */ +}; + +#define DECLARE_MODULE_AV1(name, reg, unreg, cl, hl, hfnlist, v) \ struct mapi_mheader_av1 _mheader = { MAPI_V1, reg, unreg, cl, hl, hfnlist, v} +#define DECLARE_MODULE_AV2(name, reg, unreg, cl, hl, hfnlist, caplist, v, desc) \ + struct mapi_mheader_av2 _mheader = { MAPI_V1, reg, unreg, cl, hl, hfnlist, caplist, v, desc} + /* add a path */ void mod_add_path(const char *path); void mod_clear_paths(void); diff --git a/ircd/modules.c b/ircd/modules.c index c13f4f1a..2985f1c2 100644 --- a/ircd/modules.c +++ b/ircd/modules.c @@ -35,6 +35,7 @@ #include "ircd_defs.h" #include "match.h" #include "s_serv.h" +#include "capability.h" #include @@ -640,6 +641,7 @@ static void increase_modlist(void); #define MODS_INCREMENT 10 static char unknown_ver[] = ""; +static char unknown_description[] = ""; /* unload_one_module() * @@ -693,6 +695,60 @@ unload_one_module(const char *name, int warn) mheader->mapi_unregister(); break; } + case 2: + { + struct mapi_mheader_av2 *mheader = modlist[modindex]->mapi_header; + + /* XXX duplicate code :( */ + if(mheader->mapi_command_list) + { + struct Message **m; + for (m = mheader->mapi_command_list; *m; ++m) + mod_del_cmd(*m); + } + + /* hook events are never removed, we simply lose the + * ability to call them --fl + */ + if(mheader->mapi_hfn_list) + { + mapi_hfn_list_av1 *m; + for (m = mheader->mapi_hfn_list; m->hapi_name; ++m) + remove_hook(m->hapi_name, m->fn); + } + + if(mheader->mapi_unregister) + mheader->mapi_unregister(); + + if(mheader->mapi_cap_list) + { + mapi_cap_list_av2 *m; + for (m = mheader->mapi_cap_list; m->cap_name; ++m) + { + struct CapabilityIndex *idx; + + switch(m->cap_index) + { + case MAPI_CAP_CLIENT: + idx = cli_capindex; + break; + case MAPI_CAP_SERVER: + idx = serv_capindex; + break; + default: + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s", + m->cap_index, m->cap_name, modlist[modindex]->name); + ilog(L_MAIN, + "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s", + m->cap_index, m->cap_name, modlist[modindex]->name); + continue; + } + + capability_orphan(idx, m->cap_name); + } + } + } default: sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unknown/unsupported MAPI version %d when unloading %s!", @@ -734,7 +790,7 @@ load_a_module(const char *path, int warn, int core) { lt_dlhandle tmpptr; char *mod_basename; - const char *ver; + const char *ver, *description = NULL; int *mapi_version; @@ -814,7 +870,79 @@ load_a_module(const char *path, int warn, int core) ver = mheader->mapi_module_version; break; } + case 2: + { + struct mapi_mheader_av2 *mheader = (struct mapi_mheader_av2 *)(void *)mapi_version; /* see above */ + /* XXX duplicated code :( */ + if(mheader->mapi_register && (mheader->mapi_register() == -1)) + { + ilog(L_MAIN, "Module %s indicated failure during load.", + mod_basename); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Module %s indicated failure during load.", + mod_basename); + lt_dlclose(tmpptr); + rb_free(mod_basename); + return -1; + } + if(mheader->mapi_command_list) + { + struct Message **m; + for (m = mheader->mapi_command_list; *m; ++m) + mod_add_cmd(*m); + } + + if(mheader->mapi_hook_list) + { + mapi_hlist_av1 *m; + for (m = mheader->mapi_hook_list; m->hapi_name; ++m) + *m->hapi_id = register_hook(m->hapi_name); + } + + if(mheader->mapi_hfn_list) + { + mapi_hfn_list_av1 *m; + for (m = mheader->mapi_hfn_list; m->hapi_name; ++m) + add_hook(m->hapi_name, m->fn); + } + + /* New in MAPI v2 - version replacement */ + ver = mheader->mapi_module_version ? mheader->mapi_module_version : ircd_version; + description = mheader->mapi_module_description; + + if(mheader->mapi_cap_list) + { + mapi_cap_list_av2 *m; + for (m = mheader->mapi_cap_list; m->cap_name; ++m) + { + struct CapabilityIndex *idx; + int result; + + switch(m->cap_index) + { + case MAPI_CAP_CLIENT: + idx = cli_capindex; + break; + case MAPI_CAP_SERVER: + idx = serv_capindex; + break; + default: + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Unknown/unsupported CAP index found of type %d on capability %s when loading %s", + m->cap_index, m->cap_name, mod_basename); + ilog(L_MAIN, + "Unknown/unsupported CAP index found of type %d on capability %s when loading %s", + m->cap_index, m->cap_name, mod_basename); + continue; + } + + result = capability_put(idx, m->cap_name, m->cap_ownerdata); + if (m->cap_id != NULL) + *(m->cap_id) = result; + } + } + } default: ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.", mod_basename, MAPI_VERSION(*mapi_version)); @@ -829,6 +957,9 @@ load_a_module(const char *path, int warn, int core) if(ver == NULL) ver = unknown_ver; + if(description == NULL) + description = unknown_description; + increase_modlist(); modlist[num_mods] = rb_malloc(sizeof(struct module)); @@ -843,11 +974,11 @@ load_a_module(const char *path, int warn, int core) if(warn == 1) { sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx", - mod_basename, ver, MAPI_VERSION(*mapi_version), + "Module %s [version: %s; MAPI version: %d; description: \"%s\"] loaded at 0x%lx", + mod_basename, ver, MAPI_VERSION(*mapi_version), description, (unsigned long) tmpptr); - ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx", - mod_basename, ver, MAPI_VERSION(*mapi_version), (unsigned long) tmpptr); + ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d; description: \"%s\"] loaded at 0x%lx", + mod_basename, ver, MAPI_VERSION(*mapi_version), description, (unsigned long) tmpptr); } rb_free(mod_basename); return 0;