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
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
; 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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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();
};

View File

@ -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;

View File

@ -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