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.
This commit is contained in:
Elizabeth Myers 2016-03-06 16:53:03 -06:00
parent 123231aa3c
commit 8e9c6a7590
2 changed files with 179 additions and 20 deletions

View File

@ -28,7 +28,7 @@
#include "setup.h"
#include "parse.h"
#define MAPI_RATBOX 1
#define MAPI_CHARYBDIS 2
#include <ltdl.h>
@ -42,12 +42,13 @@ struct module
lt_dlhandle address;
int core;
int mapi_version;
void * mapi_header; /* actually struct mapi_mheader_av<mapi_version> */
void *mapi_header; /* actually struct mapi_mheader_av<mapi_version> */
};
#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);

View File

@ -35,6 +35,7 @@
#include "ircd_defs.h"
#include "match.h"
#include "s_serv.h"
#include "capability.h"
#include <ltdl.h>
@ -640,6 +641,7 @@ static void increase_modlist(void);
#define MODS_INCREMENT 10
static char unknown_ver[] = "<unknown>";
static char unknown_description[] = "<none>";
/* 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;