From 4e1c220b3982ae0f0b380e997340a0e2a100d1dd Mon Sep 17 00:00:00 2001 From: DanyLE Date: Mon, 9 Jan 2023 16:31:59 +0100 Subject: [PATCH] Allow specific configuration for plugins --- antd-config.ini | 21 ++++++----- http_server.c | 92 ++++++++++++++++++++++++++++++++++-------------- lib/handle.c | 6 ++-- lib/handle.h | 14 ++++---- lib/plugin.h | 9 ++--- plugin_manager.c | 31 +++++++++++----- plugin_manager.h | 8 ++--- 7 files changed, 122 insertions(+), 59 deletions(-) diff --git a/antd-config.ini b/antd-config.ini index ffb043e..49333e0 100644 --- a/antd-config.ini +++ b/antd-config.ini @@ -30,6 +30,8 @@ ssl.cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA ; enable compression gzip_enable = 1 gzip_types = text\/.*,.*\/css,.*\/json,.*\/javascript +debug_enable = 1 +; 0 to disable ; a configuration each port @@ -106,11 +108,14 @@ lua = lua ; handled by the cgi plugin ; php = cgi - -; This enable some plugins to be initialised at server startup -; this section shall always at the end of the -; configuration file -[AUTOSTART] -; to start a plugin at server statup use: -;plugin = plugin_name_1 -;plugin = plugin_name_2, etc \ No newline at end of file +; Example of plugin configurations +[PLUGIN:php] +; theses configurations is understandable by the server +; the name of the plugin in plugin dir +name = fastcgi +; run this plugin at startup +autoload = true +; pluggin specific configurations here, for example +socket = /var/php.sock +bin = /usr/bin/phpfcgi +; etc \ No newline at end of file diff --git a/http_server.c b/http_server.c index e39c336..642235b 100644 --- a/http_server.c +++ b/http_server.c @@ -58,6 +58,7 @@ config_t *config() } void destroy_config() { + chain_t it; freedict(server_config.handlers); if (server_config.plugins_dir) free(server_config.plugins_dir); @@ -75,9 +76,16 @@ void destroy_config() freedict(server_config.mimes); if (server_config.stat_fifo_path) free(server_config.stat_fifo_path); + if(server_config.plugins) + { + for_each_assoc(it, server_config.plugins) + { + freedict((dictionary_t) it->value); + } + freedict(server_config.plugins); + } if (server_config.ports) { - chain_t it; port_config_t *cnf; for_each_assoc(it, server_config.ports) { @@ -102,7 +110,8 @@ static int config_handler(void *conf, const char *section, const char *name, const char *value) { config_t *pconfig = (config_t *)conf; - regmatch_t port_matches[2]; + regmatch_t regex_matches[2]; + char buf[255]; char * tmp; struct stat st; // trim(section, ' '); @@ -237,21 +246,14 @@ static int config_handler(void *conf, const char *section, const char *name, { dput(pconfig->handlers, name, strdup(value)); } - else if (strcmp(section, "AUTOSTART") == 0 || strcmp(section, "AUTOLOAD") == 0) - { - // The server section must be added before the autostart section - // auto start plugin - plugin_load((char *)value); - } else if (strcmp(section, "MIMES") == 0) { dput(pconfig->mimes, name, strdup(value)); } - else if (regex_match("PORT:\\s*([0-9]+)", section, 2, port_matches)) + else if (regex_match("PORT:\\s*([0-9]+)", section, 2, regex_matches)) { - char buf[20]; memset(buf, '\0', sizeof(buf)); - memcpy(buf, section + port_matches[1].rm_so, port_matches[1].rm_eo - port_matches[1].rm_so); + memcpy(buf, section + regex_matches[1].rm_so, regex_matches[1].rm_eo - regex_matches[1].rm_so); port_config_t *p = dvalue(pconfig->ports, buf); if (!p) { @@ -291,6 +293,19 @@ static int config_handler(void *conf, const char *section, const char *name, dput(p->rules, name, strdup(value)); } } + // plugin configuration + else if (regex_match("PLUGIN:\\s*(.*)", section, 2, regex_matches)) + { + memset(buf, '\0', sizeof(buf)); + memcpy(buf, section + regex_matches[1].rm_so, regex_matches[1].rm_eo - regex_matches[1].rm_so); + dictionary_t p = dvalue(pconfig->plugins, buf); + if (!p) + { + p = dict(); + dput(pconfig->plugins, buf, p); + } + dput(p, name, strdup(value)); + } else { return 0; /* unknown section/name, error */ @@ -298,9 +313,35 @@ static int config_handler(void *conf, const char *section, const char *name, return 1; } +static void init_plugins() +{ + chain_t it, it2; + dictionary_t config; + const char* value; + for_each_assoc(it, server_config.plugins) + { + config = (dictionary_t) it -> value; + if(config) + { + for_each_assoc(it2, config) + { + LOG("Plugin %s: [%s] -> [%s]", it->key, it2->key, (char*) it2->value); + } + value = (char*)dvalue(config,"autoload"); + if( value && (strncmp(value,"1", 1) == 0 || strncmp(value, "true", 3) == 0 ) ) + { + // load the plugin + LOG("Plugin %s: autoloading...", it->key); + plugin_load(it->key, config); + } + } + } +} + void load_config(const char *file) { server_config.ports = dict(); + server_config.plugins = dict(); server_config.plugins_dir = strdup("plugins/"); server_config.plugins_ext = strdup(".so"); server_config.db_path = strdup("databases/"); @@ -345,6 +386,8 @@ void load_config(const char *file) #endif } LOG("%d mimes entries found", server_config.mimes->size); + // Init plugins if necessary + init_plugins(); } void *accept_request(void *data) @@ -1632,16 +1675,13 @@ void *execute_plugin(void *data, const char *pname) // LOG("Plugin name '%s'", pname); rq->client->state = ANTD_CLIENT_PLUGIN_EXEC; // load the plugin - if ((plugin = plugin_lookup((char *)pname)) == NULL) + pthread_mutex_lock(&server_mux); + plugin = plugin_load((char *)pname, dvalue(server_config.plugins, pname)); + pthread_mutex_unlock(&server_mux); + if (plugin == NULL) { - pthread_mutex_lock(&server_mux); - plugin = plugin_load((char *)pname); - pthread_mutex_unlock(&server_mux); - if (plugin == NULL) - { - antd_error(rq->client, 503, "Requested service not found"); - return task; - } + antd_error(rq->client, 503, "Requested service not found"); + return task; } // check if the plugin want rawbody or decoded body metafn = (plugin_header_t * (*)()) dlsym(plugin->handle, "meta"); @@ -1675,17 +1715,17 @@ dictionary_t mimes_list() return server_config.mimes; } -void dbdir(char *dest) +void dbdir(char **dest) { - strncpy(dest, server_config.db_path, 512); + *dest = server_config.db_path; } -void tmpdir(char *dest) +void tmpdir(char **dest) { - strncpy(dest, server_config.tmpdir, 512); + *dest = server_config.tmpdir; } -void plugindir(char *dest) +void plugindir(char **dest) { - strncpy(dest, server_config.plugins_dir, 512); + *dest =server_config.plugins_dir; } #ifdef USE_ZLIB diff --git a/lib/handle.c b/lib/handle.c index a886639..539f250 100644 --- a/lib/handle.c +++ b/lib/handle.c @@ -115,15 +115,15 @@ void htdocs(antd_request_t *rq, char *dest) strcpy(dest, www); } } -void dbdir(char *dest) +void dbdir(char **dest) { UNUSED(dest); } -void tmpdir(char *dest) +void tmpdir(char **dest) { UNUSED(dest); } -void plugindir(char *dest) +void plugindir(char **dest) { UNUSED(dest); } diff --git a/lib/handle.h b/lib/handle.h index 789b398..1eaaf24 100644 --- a/lib/handle.h +++ b/lib/handle.h @@ -98,23 +98,25 @@ typedef struct list_t gzip_types; dictionary_t mimes; dictionary_t ports; + dictionary_t plugins; // #endif } config_t; typedef struct { char name[128]; - char dbpath[512]; - char tmpdir[512]; - char pdir[512]; + char* dbpath; + char* tmpdir; + char* pdir; + dictionary_t config; int raw_body; } plugin_header_t; int __attribute__((weak)) require_plugin(const char *); void __attribute__((weak)) htdocs(antd_request_t *rq, char *dest); -void __attribute__((weak)) dbdir(char *dest); -void __attribute__((weak)) tmpdir(char *dest); -void __attribute__((weak)) plugindir(char *dest); +void __attribute__((weak)) dbdir(char **dest); +void __attribute__((weak)) tmpdir(char **dest); +void __attribute__((weak)) plugindir(char **dest); int __attribute__((weak)) compressable(char *ctype); diff --git a/lib/plugin.h b/lib/plugin.h index 4047614..f8f5bd3 100644 --- a/lib/plugin.h +++ b/lib/plugin.h @@ -35,11 +35,12 @@ STATIC PART, should be included in any plugin #ifdef PLUGIN_IMPLEMENT static plugin_header_t __plugin__; // private function -void __init_plugin__(const char* pl){ +void __init_plugin__(const char* pl, dictionary_t* conf){ strcpy(__plugin__.name,pl); - dbdir(__plugin__.dbpath); - plugindir(__plugin__.pdir); - tmpdir(__plugin__.tmpdir); + dbdir(&__plugin__.dbpath); + plugindir(&__plugin__.pdir); + tmpdir(&__plugin__.tmpdir); + __plugin__.config = conf; __plugin__.raw_body = 0; init(); }; diff --git a/plugin_manager.c b/plugin_manager.c index ebdb44c..e993071 100644 --- a/plugin_manager.c +++ b/plugin_manager.c @@ -4,6 +4,10 @@ #include "lib/utils.h" #include "lib/handle.h" #include "http_server.h" + +static void unload_plugin_by_name(const char*); +static void * plugin_from_file(char* name, dictionary_t conf); + /** * Plugin table to store the loaded plugin */ @@ -25,7 +29,7 @@ struct plugin_entry *plugin_lookup(char *s) int require_plugin(const char* name) { - struct plugin_entry* ptr = plugin_load((char*)name); + struct plugin_entry* ptr = plugin_load((char*)name, NULL); return ptr != NULL; } @@ -33,13 +37,24 @@ int require_plugin(const char* name) * Load a plugin to the plugin table * Only load when not available in the plugin table * @param name plugin name + * @param config: plugin configuration * @return pointer to the loaded plugin */ -struct plugin_entry *plugin_load(char *name) +struct plugin_entry *plugin_load(char *name, dictionary_t config) { + char* pname = NULL; struct plugin_entry *np; unsigned hashval; + if(config) + { + pname = dvalue(config, "name"); + } + if(!pname) + { + pname = name; + } if ((np = plugin_lookup(name)) == NULL) { /* not found */ + LOG("Loading plugin: %s -> %s", name, pname); np = (struct plugin_entry *) malloc(sizeof(*np)); if (np == NULL || name == NULL) { @@ -47,7 +62,7 @@ struct plugin_entry *plugin_load(char *name) return NULL; } np->pname = strdup(name); - if ((np->handle = plugin_from_file(name)) == NULL) + if ((np->handle = plugin_from_file(pname,config)) == NULL) { if(np->pname) free(np->pname); if(np) free(np); @@ -68,12 +83,12 @@ struct plugin_entry *plugin_load(char *name) * @param name Name of the plugin * @return */ -void * plugin_from_file(char* name) +static void * plugin_from_file(char* name, dictionary_t conf) { - void *lib_handle; + void *lib_handle; char* error; char* path = __s("%s/%s%s",config()->plugins_dir,name,config()->plugins_ext); - void (*fn)(const char*); + void (*fn)(const char*, dictionary_t); lib_handle = dlopen(path, RTLD_LAZY); if (!lib_handle) { @@ -83,11 +98,11 @@ void * plugin_from_file(char* name) return NULL; } // set database path - fn = (void (*)(const char *))dlsym(lib_handle, "__init_plugin__"); + fn = (void (*)(const char*, dictionary_t))dlsym(lib_handle, "__init_plugin__"); if ((error = dlerror()) != NULL) ERROR("Problem when finding plugin init function for %s : %s", name,error); else - (*fn)(name); + (*fn)(name, conf); if(path) free(path); return lib_handle; diff --git a/plugin_manager.h b/plugin_manager.h index eab6176..72447c1 100644 --- a/plugin_manager.h +++ b/plugin_manager.h @@ -1,5 +1,8 @@ #ifndef PLUGIN_MANAGER_H #define PLUGIN_MANAGER_H + +#include "lib/dictionary.h" + struct plugin_entry { struct plugin_entry *next; char *pname; @@ -8,10 +11,7 @@ struct plugin_entry { /* lookup: look for s in hashtab */ struct plugin_entry *plugin_lookup(char *s); /* install: put (name, defn) in hashtab */ -struct plugin_entry *plugin_load(char *name); +struct plugin_entry *plugin_load(char *name, dictionary_t config); void unload_all_plugin(); void unload_plugin(struct plugin_entry*); -void unload_plugin_by_name(const char*); -void * plugin_from_file(char* name); - #endif \ No newline at end of file