From fccd44f2ad0a327fb9ddcc55fd7f196f9738c0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 8 Jul 2008 21:29:02 +0200 Subject: [PATCH] option/action/plugin --- src/actions.h | 2 +- src/base.c | 17 ------------- src/options.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------ src/options.h | 24 +++++++++++++++--- src/plugin.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/plugin.h | 33 +++++++++++++++++++------ src/settings.h | 1 + src/wscript | 1 + 8 files changed, 175 insertions(+), 37 deletions(-) create mode 100644 src/plugin.c diff --git a/src/actions.h b/src/actions.h index 407c240..3daada2 100644 --- a/src/actions.h +++ b/src/actions.h @@ -47,7 +47,7 @@ struct action { union { struct { - GArray *options; /** array of option_mark */ + GArray *options; /** array of option_set */ } setting; struct { diff --git a/src/base.c b/src/base.c index fa731c4..dd6de5c 100644 --- a/src/base.c +++ b/src/base.c @@ -1,20 +1,3 @@ #include "base.h" -static server_option* find_option(server *srv, const char *key) { - return (server_option*) g_hash_table_lookup(srv->options, key); -} - -gboolean parse_option(server *srv, const char *key, option *opt, option_mark *mark) { - server_option *sopt; - - if (!srv || !key || !mark) return FALSE; - - sopt = find_option(srv, key); - if (!sopt) return FALSE; - - /* TODO */ - UNUSED(opt); - - return FALSE; -} diff --git a/src/options.c b/src/options.c index 98503bb..130f23d 100644 --- a/src/options.c +++ b/src/options.c @@ -43,28 +43,79 @@ option* option_new_hash() { void option_free(option* opt) { - guint i; - if (!opt) return; + switch (opt->type) { + case OPTION_NONE: + case OPTION_BOOLEAN: + case OPTION_INT: + /* Nothing to free */ + break; + case OPTION_STRING: + g_string_free(opt->value.opt_string, TRUE); + break; + case OPTION_LIST: + option_list_free(opt->value.opt_list); + break; + case OPTION_HASH: + g_hash_table_destroy((GHashTable*) opt->value.opt_hash); + break; + } + opt->type = OPTION_NONE; + g_slice_free(option, opt); +} + +const char* option_type_string(option_type type) { + switch(type) { + case OPTION_NONE: + return "none"; + case OPTION_BOOLEAN: + return "boolean"; + case OPTION_INT: + return "int"; + case OPTION_STRING: + return "string"; + case OPTION_LIST: + return "list"; + case OPTION_HASH: + return "hash"; + } + return ""; +} + +void option_list_free(GArray *optlist) { + if (!optlist) return; + for (gsize i = 0; i < optlist->len; i++) { + option_free(g_array_index(optlist, option*, i)); + } + g_array_free(optlist, TRUE); +} + +/* Extract value from option, destroy option */ +gpointer option_extract_value(option *opt) { + gpointer val = NULL; + if (!opt) return NULL; + switch (opt->type) { case OPTION_NONE: + break; case OPTION_BOOLEAN: + val = GINT_TO_POINTER(opt->value.opt_bool); + break; case OPTION_INT: - /* Nothing to free */ + val = GINT_TO_POINTER(opt->value.opt_int); break; case OPTION_STRING: - g_string_free(opt->value.opt_string, TRUE); + val = opt->value.opt_string; break; case OPTION_LIST: - for (i=0; ivalue.opt_list->len; i++) - option_free(g_array_index(opt->value.opt_list, option *, i)); - g_array_free(opt->value.opt_list, FALSE); + val = opt->value.opt_list; break; case OPTION_HASH: - g_hash_table_destroy(opt->value.opt_hash); + val = opt->value.opt_hash; break; } opt->type = OPTION_NONE; g_slice_free(option, opt); + return val; } diff --git a/src/options.h b/src/options.h index 2640c1b..e195e49 100644 --- a/src/options.h +++ b/src/options.h @@ -1,13 +1,20 @@ #ifndef _LIGHTTPD_OPTIONS_H_ #define _LIGHTTPD_OPTIONS_H_ -typedef enum { OPTION_NONE, OPTION_BOOLEAN, OPTION_INT, OPTION_STRING, OPTION_LIST, OPTION_HASH } option_type; +typedef enum { + OPTION_NONE, + OPTION_BOOLEAN, + OPTION_INT, + OPTION_STRING, + OPTION_LIST, + OPTION_HASH +} option_type; struct option; typedef struct option option; -struct option_mark; -typedef struct option_mark option_mark; +struct option_set; +typedef struct option_set option_set; #include "base.h" @@ -24,9 +31,11 @@ struct option { } value; }; -struct option_mark { +struct server_option; +struct option_set { size_t ndx; gpointer value; + struct server_option *sopt; }; LI_API option* option_new_bool(gboolean val); @@ -36,4 +45,11 @@ LI_API option* option_new_list(); LI_API option* option_new_hash(); LI_API void option_free(option* opt); +LI_API const char* option_type_string(option_type type); + +LI_API void option_list_free(GArray *optlist); + +/* Extract value from option, destroy option */ +LI_API gpointer option_extract_value(option *opt); + #endif diff --git a/src/plugin.c b/src/plugin.c new file mode 100644 index 0000000..446172e --- /dev/null +++ b/src/plugin.c @@ -0,0 +1,67 @@ + +#include "plugin.h" +#include "log.h" + +static server_option* find_option(server *srv, const char *key) { + return (server_option*) g_hash_table_lookup(srv->options, key); +} + +gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark) { + server_option *sopt; + + if (!srv || !key || !mark) return FALSE; + + sopt = find_option(srv, key); + if (!sopt) { + ERROR("Unknown option '%s'", key); + return FALSE; + } + + if (sopt->type != opt->type) { + ERROR("Unexpected option type '%s', expected '%s'", + option_type_string(opt->type), option_type_string(sopt->type)); + return FALSE; + } + + if (!sopt->parse_option) { + mark->value = option_extract_value(opt); + } else { + if (!sopt->parse_option(srv, sopt->p->data, sopt->module_index, opt, &mark->value)) { + /* errors should be logged by parse function */ + return FALSE; + } + } + + mark->ndx = sopt->index; + mark->sopt = sopt; + + return TRUE; +} + +void release_option(server *srv, option_set *mark) { /** Does not free the option_set memory */ + server_option *sopt = mark->sopt; + if (!srv || !mark || !sopt) return; + + mark->sopt = NULL; + if (!sopt->free_option) { + switch (sopt->type) { + case OPTION_NONE: + case OPTION_BOOLEAN: + case OPTION_INT: + /* Nothing to free */ + break; + case OPTION_STRING: + g_string_free((GString*) mark->value, TRUE); + break; + case OPTION_LIST: + option_list_free((GArray*) mark->value); + break; + case OPTION_HASH: + g_hash_table_destroy((GHashTable*) mark->value); + break; + } + } else { + sopt->free_option(srv, sopt->p->data, sopt->module_index, mark->value); + } + mark->value = NULL; +} diff --git a/src/plugin.h b/src/plugin.h index 073c5eb..0931557 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -20,17 +20,26 @@ typedef struct server_option server_option; #include "base.h" #include "options.h" +typedef void (*ModuleInit) (server *srv, plugin *p); +typedef void (*ModuleFree) (server *srv, plugin *p); +typedef gboolean (*ModuleParseOption) (server *srv, gpointer p_d, size_t ndx, option *opt, gpointer *value); +typedef void (*ModuleFreeOption) (server *srv, gpointer p_d, size_t ndx, gpointer value); + +struct module { + GString *name; + + GModule *lib; +}; + + struct plugin { size_t version; GString *name; /* name of the plugin */ - void *(* init) (server *srv, plugin *p); - gpointer data; - /* dlopen handle */ - void *lib; + ModuleFree *free; module_option *options; }; @@ -38,6 +47,9 @@ struct plugin { struct module_option { const char *key; option_type type; + + ModuleParseOption parse_option; + ModuleFreeOption free_option; }; struct server_option { @@ -46,14 +58,21 @@ struct server_option { /* the plugin must free the _content_ of the option * opt is zero to get the global default value if nothing is specified * save result in value + * + * Default behaviour (NULL) is to just use the option as value */ - gboolean (* parse_option) (server *srv, void *p_d, size_t ndx, option *opt, gpointer *value); - void (* free_option) (server *srv, void *p_d, size_t ndx, gpointer value); + ModuleParseOption parse_option; + ModuleFreeOption free_option; size_t index, module_index; option_type type; }; -LI_API gboolean parse_option(server *srv, const char *key, option *opt, option_mark *mark); +LI_API gboolean plugin_register(server *srv, ModuleInit *init); + +LI_API gboolean parse_option(server *srv, const char *key, option *opt, option_set *mark); +LI_API void release_option(server *srv, option_set *mark); /** Does not free the option_set memory */ + +LI_API gboolean plugin_load(server *srv, const char *module); #endif diff --git a/src/settings.h b/src/settings.h index 6f772e0..9155d3b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -11,6 +11,7 @@ #endif #include +#include #include diff --git a/src/wscript b/src/wscript index 5088418..31baf91 100644 --- a/src/wscript +++ b/src/wscript @@ -17,6 +17,7 @@ common_source=''' http_request_parser.rl log.c options.c + plugin.c request.c sys-files.c sys-socket.c