From 57701f997d6ca2887de98560c26d70aab8731055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Wed, 23 Jul 2008 21:34:19 +0200 Subject: [PATCH] Added "actions" and "setups" to the plugin api --- src/actions.c | 24 ++++++++++- src/actions.h | 23 ++++++---- src/base.h | 2 +- src/plugin.c | 117 +++++++++++++++++++++++++++++++++++++++++--------- src/plugin.h | 50 ++++++++++++++++++--- src/server.c | 19 +++++++- src/server.h | 4 +- 7 files changed, 198 insertions(+), 41 deletions(-) diff --git a/src/actions.c b/src/actions.c index 97f1cfa..c26242c 100644 --- a/src/actions.c +++ b/src/actions.c @@ -12,7 +12,6 @@ struct action_stack_element { }; - action *action_new_setting(server *srv, GString *name, option *value) { option_set setting; if (!parse_option(srv, name->str, value, &setting)) { @@ -28,6 +27,29 @@ action *action_new_setting(server *srv, GString *name, option *value) { return a; } +action *action_new_function(server *srv, const char *name, option *value) { + action *a; + action_func af; + server_action *sa; + + if (NULL == (sa = g_hash_table_lookup(srv->actions, name))) { + ERROR(srv, "Action '%s' doesn't exist", name); + return NULL; + } + + if (!sa->create_action(srv, sa->p ? sa->p->data : NULL, value, &af)) { + ERROR(srv, "Action '%s' creation failed", name); + return NULL; + } + + a = g_slice_new(action); + a->refcount = 1; + a->type = ACTION_TFUNCTION; + a->value.function = af; + + return a; +} + void action_release(action *a) { assert(a->refcount > 0); if (!(--a->refcount)) { diff --git a/src/actions.h b/src/actions.h index aa4d656..5a85d0c 100644 --- a/src/actions.h +++ b/src/actions.h @@ -31,7 +31,15 @@ struct action_stack { }; struct server; struct connection; -typedef action_result (*action_func)(struct server *srv, struct connection *con, void* param); +typedef action_result (*ActionFunc)(struct server *srv, struct connection *con, gpointer param); +typedef void (*ActionFree)(struct server *srv, gpointer param); + +struct action_func { + ActionFunc func; + ActionFree free; + gpointer param; +}; +typedef struct action_func action_func; #include "condition.h" #include "plugin.h" @@ -55,10 +63,7 @@ struct action { action_list* target; /** action target to jump to if condition is fulfilled */ } condition; - struct { - action_func func; - gpointer param; - } function; + action_func function; } value; }; @@ -76,8 +81,8 @@ LI_API action_result action_execute(server *srv, connection *con); /* create new action */ -action *action_new_setting(server *srv, GString *name, option *value); -action *action_new_function(); -action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str); -action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i); +LI_API action *action_new_setting(server *srv, GString *name, option *value); +LI_API action *action_new_function(server *srv, const char *name, option *value); +LI_API action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str); +LI_API action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i); #endif diff --git a/src/base.h b/src/base.h index 1846839..0eb907e 100644 --- a/src/base.h +++ b/src/base.h @@ -13,8 +13,8 @@ typedef struct connection connection; #include "server.h" -#include "plugin.h" #include "actions.h" +#include "plugin.h" #include "request.h" #include "log.h" diff --git a/src/plugin.c b/src/plugin.c index 351dfe3..a03ab47 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -8,25 +8,69 @@ static plugin* plugin_new(const gchar *name) { return p; } -void plugin_free(plugin *p) { +static void plugin_free_options(server *srv, plugin *p) { + size_t i; + const plugin_option *po; + server_option *so; + + if (!p->options) return; + for (i = 0; (po = &p->options[i])->name; i++) { + if (NULL == (so = g_hash_table_lookup(srv->options, po->name))) break; + if (so->p != p) break; + g_hash_table_remove(srv->options, po->name); + } +} + +static void plugin_free_actions(server *srv, plugin *p) { + size_t i; + const plugin_action *pa; + server_action *sa; + + if (!p->actions) return; + for (i = 0; (pa = &p->actions[i])->name; i++) { + if (NULL == (sa = g_hash_table_lookup(srv->actions, pa->name))) break; + if (sa->p != p) break; + g_hash_table_remove(srv->actions, pa->name); + } +} + +static void plugin_free_setups(server *srv, plugin *p) { + size_t i; + const plugin_setup *ps; + server_setup *ss; + + if (!p->setups) return; + for (i = 0; (ps = &p->setups[i])->name; i++) { + if (NULL == (ss = g_hash_table_lookup(srv->setups, ps->name))) break; + if (ss->p != p) break; + g_hash_table_remove(srv->setups, ps->name); + } +} + +void plugin_free(server *srv, plugin *p) { if (!p) return; + g_hash_table_remove(srv->plugins, p->name); + plugin_free_options(srv, p); + plugin_free_actions(srv, p); + plugin_free_setups(srv, p); + g_slice_free(plugin, p); } -static server_option* find_option(server *srv, const char *key) { - return (server_option*) g_hash_table_lookup(srv->options, key); +static server_option* find_option(server *srv, const char *name) { + return (server_option*) g_hash_table_lookup(srv->options, name); } -gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark) { +gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark) { server_option *sopt; - if (!srv || !key || !mark) return FALSE; + if (!srv || !name || !mark) return FALSE; - sopt = find_option(srv, key); + sopt = find_option(srv, name); if (!sopt) { - ERROR(srv, "Unknown option '%s'", key); + ERROR(srv, "Unknown option '%s'", name); return FALSE; } @@ -102,13 +146,14 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) { server_option *so; const plugin_option *po; - for (i = 0; (po = &p->options[i])->key; i++) { - if (NULL != (so = (server_option*)g_hash_table_lookup(srv->options, po->key))) { + for (i = 0; (po = &p->options[i])->name; i++) { + if (NULL != (so = (server_option*)g_hash_table_lookup(srv->options, po->name))) { ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'", - po->key, + po->name, so->p ? so->p->name : "", p->name); - break; + plugin_free(srv, p); + return FALSE; } so = g_slice_new0(server_option); so->type = po->type; @@ -117,19 +162,49 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) { so->index = g_hash_table_size(srv->options); so->module_index = i; so->p = p; - g_hash_table_insert(srv->options, (gchar*) po->key, so); + g_hash_table_insert(srv->options, (gchar*) po->name, so); } + } - if (po->key) { - while (i-- > 0) { - po = &p->options[i]; - g_slice_free(server_option, g_hash_table_lookup(srv->options, po->key)); - g_hash_table_remove(srv->options, po->key); + if (p->actions) { + size_t i; + server_action *sa; + const plugin_action *pa; + + for (i = 0; (pa = &p->actions[i])->name; i++) { + if (NULL != (sa = (server_action*)g_hash_table_lookup(srv->actions, pa->name))) { + ERROR(srv, "Action '%s' already registered by plugin '%s', unloading '%s'", + pa->name, + sa->p ? sa->p->name : "", + p->name); + plugin_free(srv, p); + return FALSE; } - g_hash_table_remove(srv->plugins, p->name); - if (p->free) p->free(srv, p); - plugin_free(p); - return FALSE; + sa = g_slice_new0(server_action); + sa->create_action = pa->create_action; + sa->p = p; + g_hash_table_insert(srv->actions, (gchar*) pa->name, sa); + } + } + + if (p->setups) { + size_t i; + server_setup *ss; + const plugin_setup *ps; + + for (i = 0; (ps = &p->setups[i])->name; i++) { + if (NULL != (ss = (server_setup*)g_hash_table_lookup(srv->setups, ps->name))) { + ERROR(srv, "Setup '%s' already registered by plugin '%s', unloading '%s'", + ps->name, + ss->p ? ss->p->name : "", + p->name); + plugin_free(srv, p); + return FALSE; + } + ss = g_slice_new0(server_setup); + ss->setup = ps->setup; + ss->p = p; + g_hash_table_insert(srv->setups, (gchar*) ps->name, ss); } } diff --git a/src/plugin.h b/src/plugin.h index a92ab65..d40452c 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -10,6 +10,18 @@ typedef struct plugin_option plugin_option; struct server_option; typedef struct server_option server_option; +struct plugin_action; +typedef struct plugin_action plugin_action; + +struct server_action; +typedef struct server_action server_action; + +struct plugin_setup; +typedef struct plugin_setup plugin_setup; + +struct server_setup; +typedef struct server_setup server_setup; + #define INIT_FUNC(x) \ LI_EXPORT void * x(server *srv, plugin *) @@ -19,12 +31,15 @@ typedef struct server_option server_option; #include "base.h" #include "options.h" +#include "actions.h" #include "module.h" -typedef void (*PluginInit) (server *srv, plugin *p); -typedef void (*PluginFree) (server *srv, plugin *p); -typedef gboolean (*PluginParseOption) (server *srv, gpointer p_d, size_t ndx, option *opt, gpointer *value); -typedef void (*PluginFreeOption) (server *srv, gpointer p_d, size_t ndx, gpointer value); +typedef void (*PluginInit) (server *srv, plugin *p); +typedef void (*PluginFree) (server *srv, plugin *p); +typedef gboolean (*PluginParseOption) (server *srv, gpointer p_d, size_t ndx, option *opt, gpointer *value); +typedef void (*PluginFreeOption) (server *srv, gpointer p_d, size_t ndx, gpointer value); +typedef gboolean (*PluginCreateAction) (server *srv, gpointer p_d, option *opt, action_func *func); +typedef gboolean (*PluginSetup) (server *srv, gpointer p_d, option *opt); struct plugin { size_t version; @@ -35,16 +50,29 @@ struct plugin { PluginFree free; /**< called before plugin is unloaded */ const plugin_option *options; + const plugin_action *actions; + const plugin_setup *setups; }; struct plugin_option { - const gchar *key; + const gchar *name; option_type type; PluginParseOption parse_option; PluginFreeOption free_option; }; +struct plugin_action { + const gchar *name; + PluginCreateAction create_action; +}; + +struct plugin_setup { + const gchar *name; + PluginSetup setup; +}; + +/* Internal structures */ struct server_option { plugin *p; @@ -61,7 +89,17 @@ struct server_option { option_type type; }; -LI_API void plugin_free(plugin *p); +struct server_action { + plugin *p; + PluginCreateAction create_action; +}; + +struct server_setup { + plugin *p; + PluginSetup setup; +}; + +LI_API void plugin_free(server *srv, plugin *p); LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit init); LI_API gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark); diff --git a/src/server.c b/src/server.c index d380150..a8318be 100644 --- a/src/server.c +++ b/src/server.c @@ -2,11 +2,24 @@ #include "base.h" #include "log.h" +static void server_option_free(gpointer _so) { + g_slice_free(server_option, _so); +} + +static void server_action_free(gpointer _sa) { + g_slice_free(server_action, _sa); +} + +static void server_setup_free(gpointer _ss) { + g_slice_free(server_setup, _ss); +} server* server_new() { server* srv = g_slice_new0(server); srv->plugins = g_hash_table_new(g_str_hash, g_str_equal); - srv->options = g_hash_table_new(g_str_hash, g_str_equal); + srv->options = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_option_free); + srv->actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_action_free); + srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free); srv->mutex = g_mutex_new(); return srv; @@ -16,8 +29,10 @@ void server_free(server* srv) { if (!srv) return; /* TODO */ - g_hash_table_destroy(srv->plugins); g_hash_table_destroy(srv->options); + g_hash_table_destroy(srv->actions); + g_hash_table_destroy(srv->setups); + g_hash_table_destroy(srv->plugins); g_mutex_free(srv->mutex); /* free logs */ diff --git a/src/server.h b/src/server.h index d1de9b4..8f4dcef 100644 --- a/src/server.h +++ b/src/server.h @@ -6,8 +6,10 @@ struct server { GHashTable *plugins; - size_t option_count; GHashTable *options; + GHashTable *actions; + GHashTable *setups; + gpointer *option_def_values; gboolean exiting;