Allow specific configuration for plugins

This commit is contained in:
DanyLE 2023-01-09 16:31:59 +01:00
parent 5d7a0f8b49
commit 4e1c220b39
7 changed files with 122 additions and 59 deletions

View File

@ -30,6 +30,8 @@ ssl.cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA
; enable compression ; enable compression
gzip_enable = 1 gzip_enable = 1
gzip_types = text\/.*,.*\/css,.*\/json,.*\/javascript gzip_types = text\/.*,.*\/css,.*\/json,.*\/javascript
debug_enable = 1
; 0 to disable
; a configuration each port ; a configuration each port
@ -106,11 +108,14 @@ lua = lua
; handled by the cgi plugin ; handled by the cgi plugin
; php = cgi ; php = cgi
; Example of plugin configurations
; This enable some plugins to be initialised at server startup [PLUGIN:php]
; this section shall always at the end of the ; theses configurations is understandable by the server
; configuration file ; the name of the plugin in plugin dir
[AUTOSTART] name = fastcgi
; to start a plugin at server statup use: ; run this plugin at startup
;plugin = plugin_name_1 autoload = true
;plugin = plugin_name_2, etc ; pluggin specific configurations here, for example
socket = /var/php.sock
bin = /usr/bin/phpfcgi
; etc

View File

@ -58,6 +58,7 @@ config_t *config()
} }
void destroy_config() void destroy_config()
{ {
chain_t it;
freedict(server_config.handlers); freedict(server_config.handlers);
if (server_config.plugins_dir) if (server_config.plugins_dir)
free(server_config.plugins_dir); free(server_config.plugins_dir);
@ -75,9 +76,16 @@ void destroy_config()
freedict(server_config.mimes); freedict(server_config.mimes);
if (server_config.stat_fifo_path) if (server_config.stat_fifo_path)
free(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) if (server_config.ports)
{ {
chain_t it;
port_config_t *cnf; port_config_t *cnf;
for_each_assoc(it, server_config.ports) 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) const char *value)
{ {
config_t *pconfig = (config_t *)conf; config_t *pconfig = (config_t *)conf;
regmatch_t port_matches[2]; regmatch_t regex_matches[2];
char buf[255];
char * tmp; char * tmp;
struct stat st; struct stat st;
// trim(section, ' '); // trim(section, ' ');
@ -237,21 +246,14 @@ static int config_handler(void *conf, const char *section, const char *name,
{ {
dput(pconfig->handlers, name, strdup(value)); 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) else if (strcmp(section, "MIMES") == 0)
{ {
dput(pconfig->mimes, name, strdup(value)); 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)); 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); port_config_t *p = dvalue(pconfig->ports, buf);
if (!p) if (!p)
{ {
@ -291,6 +293,19 @@ static int config_handler(void *conf, const char *section, const char *name,
dput(p->rules, name, strdup(value)); 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 else
{ {
return 0; /* unknown section/name, error */ return 0; /* unknown section/name, error */
@ -298,9 +313,35 @@ static int config_handler(void *conf, const char *section, const char *name,
return 1; 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) void load_config(const char *file)
{ {
server_config.ports = dict(); server_config.ports = dict();
server_config.plugins = dict();
server_config.plugins_dir = strdup("plugins/"); server_config.plugins_dir = strdup("plugins/");
server_config.plugins_ext = strdup(".so"); server_config.plugins_ext = strdup(".so");
server_config.db_path = strdup("databases/"); server_config.db_path = strdup("databases/");
@ -345,6 +386,8 @@ void load_config(const char *file)
#endif #endif
} }
LOG("%d mimes entries found", server_config.mimes->size); LOG("%d mimes entries found", server_config.mimes->size);
// Init plugins if necessary
init_plugins();
} }
void *accept_request(void *data) void *accept_request(void *data)
@ -1632,17 +1675,14 @@ void *execute_plugin(void *data, const char *pname)
// LOG("Plugin name '%s'", pname); // LOG("Plugin name '%s'", pname);
rq->client->state = ANTD_CLIENT_PLUGIN_EXEC; rq->client->state = ANTD_CLIENT_PLUGIN_EXEC;
// load the plugin // load the plugin
if ((plugin = plugin_lookup((char *)pname)) == NULL)
{
pthread_mutex_lock(&server_mux); pthread_mutex_lock(&server_mux);
plugin = plugin_load((char *)pname); plugin = plugin_load((char *)pname, dvalue(server_config.plugins, pname));
pthread_mutex_unlock(&server_mux); pthread_mutex_unlock(&server_mux);
if (plugin == NULL) if (plugin == NULL)
{ {
antd_error(rq->client, 503, "Requested service not found"); antd_error(rq->client, 503, "Requested service not found");
return task; return task;
} }
}
// check if the plugin want rawbody or decoded body // check if the plugin want rawbody or decoded body
metafn = (plugin_header_t * (*)()) dlsym(plugin->handle, "meta"); metafn = (plugin_header_t * (*)()) dlsym(plugin->handle, "meta");
if ((error = dlerror()) == NULL) if ((error = dlerror()) == NULL)
@ -1675,17 +1715,17 @@ dictionary_t mimes_list()
return server_config.mimes; 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 #ifdef USE_ZLIB

View File

@ -115,15 +115,15 @@ void htdocs(antd_request_t *rq, char *dest)
strcpy(dest, www); strcpy(dest, www);
} }
} }
void dbdir(char *dest) void dbdir(char **dest)
{ {
UNUSED(dest); UNUSED(dest);
} }
void tmpdir(char *dest) void tmpdir(char **dest)
{ {
UNUSED(dest); UNUSED(dest);
} }
void plugindir(char *dest) void plugindir(char **dest)
{ {
UNUSED(dest); UNUSED(dest);
} }

View File

@ -98,23 +98,25 @@ typedef struct
list_t gzip_types; list_t gzip_types;
dictionary_t mimes; dictionary_t mimes;
dictionary_t ports; dictionary_t ports;
dictionary_t plugins;
// #endif // #endif
} config_t; } config_t;
typedef struct typedef struct
{ {
char name[128]; char name[128];
char dbpath[512]; char* dbpath;
char tmpdir[512]; char* tmpdir;
char pdir[512]; char* pdir;
dictionary_t config;
int raw_body; int raw_body;
} plugin_header_t; } plugin_header_t;
int __attribute__((weak)) require_plugin(const char *); int __attribute__((weak)) require_plugin(const char *);
void __attribute__((weak)) htdocs(antd_request_t *rq, char *dest); void __attribute__((weak)) htdocs(antd_request_t *rq, char *dest);
void __attribute__((weak)) dbdir(char *dest); void __attribute__((weak)) dbdir(char **dest);
void __attribute__((weak)) tmpdir(char *dest); void __attribute__((weak)) tmpdir(char **dest);
void __attribute__((weak)) plugindir(char *dest); void __attribute__((weak)) plugindir(char **dest);
int __attribute__((weak)) compressable(char *ctype); int __attribute__((weak)) compressable(char *ctype);

View File

@ -35,11 +35,12 @@ STATIC PART, should be included in any plugin
#ifdef PLUGIN_IMPLEMENT #ifdef PLUGIN_IMPLEMENT
static plugin_header_t __plugin__; static plugin_header_t __plugin__;
// private function // private function
void __init_plugin__(const char* pl){ void __init_plugin__(const char* pl, dictionary_t* conf){
strcpy(__plugin__.name,pl); strcpy(__plugin__.name,pl);
dbdir(__plugin__.dbpath); dbdir(&__plugin__.dbpath);
plugindir(__plugin__.pdir); plugindir(&__plugin__.pdir);
tmpdir(__plugin__.tmpdir); tmpdir(&__plugin__.tmpdir);
__plugin__.config = conf;
__plugin__.raw_body = 0; __plugin__.raw_body = 0;
init(); init();
}; };

View File

@ -4,6 +4,10 @@
#include "lib/utils.h" #include "lib/utils.h"
#include "lib/handle.h" #include "lib/handle.h"
#include "http_server.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 * Plugin table to store the loaded plugin
*/ */
@ -25,7 +29,7 @@ struct plugin_entry *plugin_lookup(char *s)
int require_plugin(const char* name) 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; return ptr != NULL;
} }
@ -33,13 +37,24 @@ int require_plugin(const char* name)
* Load a plugin to the plugin table * Load a plugin to the plugin table
* Only load when not available in the plugin table * Only load when not available in the plugin table
* @param name plugin name * @param name plugin name
* @param config: plugin configuration
* @return pointer to the loaded plugin * @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; struct plugin_entry *np;
unsigned hashval; unsigned hashval;
if(config)
{
pname = dvalue(config, "name");
}
if(!pname)
{
pname = name;
}
if ((np = plugin_lookup(name)) == NULL) { /* not found */ if ((np = plugin_lookup(name)) == NULL) { /* not found */
LOG("Loading plugin: %s -> %s", name, pname);
np = (struct plugin_entry *) malloc(sizeof(*np)); np = (struct plugin_entry *) malloc(sizeof(*np));
if (np == NULL || name == NULL) if (np == NULL || name == NULL)
{ {
@ -47,7 +62,7 @@ struct plugin_entry *plugin_load(char *name)
return NULL; return NULL;
} }
np->pname = strdup(name); 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->pname) free(np->pname);
if(np) free(np); if(np) free(np);
@ -68,12 +83,12 @@ struct plugin_entry *plugin_load(char *name)
* @param name Name of the plugin * @param name Name of the plugin
* @return * @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* error;
char* path = __s("%s/%s%s",config()->plugins_dir,name,config()->plugins_ext); 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); lib_handle = dlopen(path, RTLD_LAZY);
if (!lib_handle) if (!lib_handle)
{ {
@ -83,11 +98,11 @@ void * plugin_from_file(char* name)
return NULL; return NULL;
} }
// set database path // 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) if ((error = dlerror()) != NULL)
ERROR("Problem when finding plugin init function for %s : %s", name,error); ERROR("Problem when finding plugin init function for %s : %s", name,error);
else else
(*fn)(name); (*fn)(name, conf);
if(path) if(path)
free(path); free(path);
return lib_handle; return lib_handle;

View File

@ -1,5 +1,8 @@
#ifndef PLUGIN_MANAGER_H #ifndef PLUGIN_MANAGER_H
#define PLUGIN_MANAGER_H #define PLUGIN_MANAGER_H
#include "lib/dictionary.h"
struct plugin_entry { struct plugin_entry {
struct plugin_entry *next; struct plugin_entry *next;
char *pname; char *pname;
@ -8,10 +11,7 @@ struct plugin_entry {
/* lookup: look for s in hashtab */ /* lookup: look for s in hashtab */
struct plugin_entry *plugin_lookup(char *s); struct plugin_entry *plugin_lookup(char *s);
/* install: put (name, defn) in hashtab */ /* 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_all_plugin();
void unload_plugin(struct plugin_entry*); void unload_plugin(struct plugin_entry*);
void unload_plugin_by_name(const char*);
void * plugin_from_file(char* name);
#endif #endif