From 58a7738afee006a1a816bfab15ae54e879eb723a Mon Sep 17 00:00:00 2001 From: DanyLE Date: Wed, 13 Mar 2024 18:07:07 +0100 Subject: [PATCH] feat: rework on plugin support - New plugin interface that supports multiple instances - Fix and improve memory bugs - Refactory and cleanup lib - Improve scheduler --- Makefile.am | 3 +- antd-config.ini | 2 - config.c | 46 ++++--- decode.c | 4 +- httpd.c | 16 +-- lib/dictionary.c | 1 + lib/handle.c | 22 +++- lib/handle.h | 24 +--- lib/plugin.c | 51 ++++++++ lib/plugin.h | 78 ++++------- lib/plugin_ctx.h | 18 +++ lib/scheduler.c | 2 +- lib/scheduler.h | 2 - lib/utils.c | 10 +- lib/utils.h | 8 +- plugin_manager.c | 335 +++++++++++++++++++++++++++-------------------- plugin_manager.h | 19 +-- server.c | 55 +------- server.h | 8 +- 19 files changed, 389 insertions(+), 315 deletions(-) create mode 100644 lib/plugin.c create mode 100644 lib/plugin_ctx.h diff --git a/Makefile.am b/Makefile.am index d97a0d5..2382a81 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,8 @@ libantd_la_SOURCES = lib/ini.c \ lib/sha1.c \ lib/list.c \ lib/bst.c \ - lib/scheduler.c + lib/scheduler.c \ + lib/plugin.c pkginclude_HEADERS = lib/ini.h \ lib/handle.h \ diff --git a/antd-config.ini b/antd-config.ini index dd5125b..a2c3707 100644 --- a/antd-config.ini +++ b/antd-config.ini @@ -3,8 +3,6 @@ plugins=/opt/www/lib/ ; plugin extension plugins_ext=.so -; SQLITE database path -database=/opt/www/database/ ; tmp dir tmpdir=/opt/www/tmp/ ; max concurent connection diff --git a/config.c b/config.c index b9e8099..b0bea88 100644 --- a/config.c +++ b/config.c @@ -63,8 +63,8 @@ static void init_plugins() 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); + LOG("Plugin %s: auto loading...", it->key); + UNUSED(antd_plugin_load(it->key)); } } } @@ -105,23 +105,6 @@ static int config_handler(void *conf, const char *section, const char *name, free(pconfig->plugins_ext); pconfig->plugins_ext = strdup(value); } - else if (MATCH("SERVER", "database")) - { - if (stat(value, &st) == -1) - mkdirp(value, 0700); - tmp = realpath(value, NULL); - if (!tmp) - { - ERROR("Unable to query real path for %s: %s", value, strerror(errno)); - } - else - { - if (pconfig->db_path) - free(pconfig->db_path); - pconfig->db_path = tmp; - LOG("Database root is %s", pconfig->db_path); - } - } else if (MATCH("SERVER", "tmpdir")) { if (stat(value, &st) == -1) @@ -341,6 +324,13 @@ void load_config(const char *file) LOG("SSL Cipher suite: %s", g_server_config.ssl_cipher);*/ #endif } + set_mimes_list(g_server_config.mimes); +#ifdef USE_ZLIB + if(g_server_config.gzip_enable && g_server_config.gzip_types != NULL) + { + set_gzip_types(g_server_config.gzip_types); + } +#endif LOG("%d mimes entries found", g_server_config.mimes->size); // Init plugins if necessary init_plugins(); @@ -361,9 +351,17 @@ void destroy_config() if (g_server_config.ssl_cipher) free(g_server_config.ssl_cipher); if (g_server_config.gzip_types) + { list_free(&g_server_config.gzip_types); +#ifdef USE_ZLIB + set_gzip_types(g_server_config.gzip_types); +#endif + } if (g_server_config.mimes) + { freedict(g_server_config.mimes); + set_mimes_list(NULL); + } if (g_server_config.stat_fifo_path) free(g_server_config.stat_fifo_path); if (g_server_config.plugins) @@ -371,9 +369,18 @@ void destroy_config() for_each_assoc(it, g_server_config.plugins) { freedict((dictionary_t)it->value); + it->value = NULL; } freedict(g_server_config.plugins); } + if(g_server_config.sslcert) + { + free(g_server_config.sslcert); + } + if(g_server_config.sslkey) + { + free(g_server_config.sslkey); + } if (g_server_config.ports) { port_config_t *cnf; @@ -396,4 +403,5 @@ void destroy_config() freedict(g_server_config.ports); } LOG("Unclosed connection: %d", g_server_config.connection); + LOG("Config destroyed"); } \ No newline at end of file diff --git a/decode.c b/decode.c index 085ff10..e89379b 100644 --- a/decode.c +++ b/decode.c @@ -254,6 +254,7 @@ static void *check_proxy(antd_request_t *rq, const char *path, const char *query if (!ret) { + free(task); return NULL; } @@ -367,7 +368,7 @@ void *decode_request_header(void *data) dictionary_t request = dvalue(rq->request, "REQUEST_DATA"); char *port_s = (char *)dvalue(rq->request, "SERVER_PORT"); port_config_t *pcnf = (port_config_t *)dvalue(g_server_config.ports, port_s); - antd_task_t *task; + antd_task_t *task = NULL; // first real all header // this for check if web socket is enabled @@ -757,7 +758,6 @@ void *decode_post_request(void *data) { // WARN: this may not work on ssl socket // antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_READABLE | TASK_EVT_ON_WRITABLE); - // task->handle = decode_post_request; antd_error(rq->client, 400, "Bad Request, missing content data"); return task; } diff --git a/httpd.c b/httpd.c index 3764dcb..dbd1471 100644 --- a/httpd.c +++ b/httpd.c @@ -140,7 +140,6 @@ static void configure_context(SSL_CTX *ctx) static void stop_serve(int dummy) { - UNUSED(dummy); // close log server closelog(); sigset_t mask; @@ -151,7 +150,7 @@ static void stop_serve(int dummy) sigaddset(&mask, SIGABRT); sigprocmask(SIG_BLOCK, &mask, NULL); antd_scheduler_destroy(scheduler); - unload_all_plugin(); + antd_unload_all_plugin(); #ifdef USE_OPENSSL // DEPRECATED FIPS_mode_set(0); SSL_CTX_free(ctx); @@ -165,6 +164,7 @@ static void stop_serve(int dummy) #endif destroy_config(); sigprocmask(SIG_UNBLOCK, &mask, NULL); + exit(dummy); } static void antd_monitor(port_config_t *pcnf, int sock) @@ -182,6 +182,7 @@ static void antd_monitor(port_config_t *pcnf, int sock) // just dump the scheduler when we have a connection antd_client_t *client = (antd_client_t *)malloc(sizeof(antd_client_t)); antd_request_t *request = (antd_request_t *)malloc(sizeof(*request)); + request->context = NULL; request->client = client; request->request = dict(); client->zstream = NULL; @@ -378,8 +379,7 @@ int main(int argc, char *argv[]) if (scheduler == NULL) { ERROR("Unable to initialise scheduler. Exit"); - stop_serve(0); - exit(1); + stop_serve(1); } FD_ZERO(&master_set); for_each_assoc(it, g_server_config.ports) @@ -411,15 +411,13 @@ int main(int argc, char *argv[]) if (nlisten == 0) { ERROR("No port is listened, quit!!"); - stop_serve(0); - exit(1); + stop_serve(1); } // Start scheduler if (pthread_create(&sched_th, NULL, (void *(*)(void *))antd_scheduler_wait, (void *)scheduler) != 0) { ERROR("pthread_create: cannot start scheduler thread"); - stop_serve(0); - exit(1); + stop_serve(1); } else { @@ -460,5 +458,5 @@ int main(int argc, char *argv[]) } } stop_serve(0); - return (0); + return 0; } diff --git a/lib/dictionary.c b/lib/dictionary.c index 97fd4f8..1431cdd 100644 --- a/lib/dictionary.c +++ b/lib/dictionary.c @@ -152,6 +152,7 @@ void free_association(chain_t *asoc) if (a->key) { + //printf("Free key %s\n", a->key); free(a->key); if (a->value) free(a->value); diff --git a/lib/handle.c b/lib/handle.c index 1902c8c..909f561 100644 --- a/lib/handle.c +++ b/lib/handle.c @@ -100,11 +100,31 @@ int require_plugin(const char *name) return 0; } +#ifdef USE_ZLIB +static list_t g_gzip_types = NULL; +void set_gzip_types(list_t list) +{ + g_gzip_types = list; +} int compressable(char *ctype) { - UNUSED(ctype); + if (g_gzip_types == NULL) + return 0; + item_t it; + list_for_each(it, g_gzip_types) + { + if(it->type == LIST_TYPE_POINTER && it->value.ptr) + { + //LOG("Checking content type %s against GZIP support %s", ctype,(const char *)it->value.ptr); + if (regex_match((const char *)it->value.ptr, ctype, 0, NULL)) + { + return 1; + } + } + } return 0; } +#endif const char *get_status_str(int stat) { diff --git a/lib/handle.h b/lib/handle.h index beabfc3..d26edc9 100644 --- a/lib/handle.h +++ b/lib/handle.h @@ -5,6 +5,7 @@ #include "list.h" #include "dictionary.h" +#include "plugin.h" #define SERVER_NAME "Antd" #define IS_POST(method) (strcmp(method, "POST") == 0) @@ -28,9 +29,6 @@ #define ANTD_CLIENT_RQ_DATA_DECODE 0x7 #define ANTD_CLIENT_PROXY_MONITOR 0x8 -#define ANTD_PLUGIN_READY 0x0 -#define ANTD_PLUGIN_PANNIC 0x1 -#define ANTD_PLUGIN_INIT 0x2 #define MAX_PATH_LEN 256 typedef enum @@ -63,6 +61,7 @@ typedef struct { antd_client_t *client; dictionary_t request; + antd_plugin_ctx_t * context; } antd_request_t; typedef struct @@ -73,23 +72,12 @@ typedef struct } antd_response_header_t; -typedef struct -{ - char name[MAX_PATH_LEN]; - char dbpath[MAX_PATH_LEN]; - char tmpdir[MAX_PATH_LEN]; - char pdir[MAX_PATH_LEN]; - dictionary_t config; - int raw_body; - int status; - void *instance_data; -} plugin_header_t; - void set_nonblock(int socket); //void set_block(int socket); - -int __attribute__((weak)) compressable(char *ctype); - +#ifdef USE_ZLIB +int compressable(char *ctype); +void set_gzip_types(list_t list); +#endif void antd_send_header(void *, antd_response_header_t *); const char *get_status_str(int stat); int __t(void *, const char *, ...); diff --git a/lib/plugin.c b/lib/plugin.c new file mode 100644 index 0000000..b11cde5 --- /dev/null +++ b/lib/plugin.c @@ -0,0 +1,51 @@ +#include "plugin_ctx.h" +#include "plugin.h" + + +const char * antd_plugin_basedir(antd_plugin_ctx_t * ctx) +{ + return ctx->basedir; +} +const char * antd_plugin_tmpdir(antd_plugin_ctx_t * ctx) +{ + return ctx->tmpdir; +} +const char * antd_plugin_confdir(antd_plugin_ctx_t *ctx) +{ + if(ctx->confdir == NULL) + { + struct stat st; + ctx->confdir = __s("%s%s%s", ctx->basedir,DIR_SEP, ctx->name); + if (stat(ctx->confdir, &st) == -1) + mkdir(ctx->confdir, 0755); + } + return ctx->confdir; +} +const char * antd_plugin_name(antd_plugin_ctx_t *ctx) +{ + return ctx->name; +} +void antd_plugin_set_status(antd_plugin_ctx_t * ctx, int stat) +{ + ctx->status = stat; +} +int antd_plugin_status(antd_plugin_ctx_t * ctx) +{ + return ctx->status; +} +void antd_plugin_use_raw_body(antd_plugin_ctx_t * ctx) +{ + ctx->raw_body = 1; +} +int antd_plugin_is_raw_body(antd_plugin_ctx_t *ctx) +{ + return ctx->raw_body == 1; +} +void* antd_plugin_data(antd_plugin_ctx_t* ctx) +{ + return ctx->data; +} +dictionary_t antd_plugin_config(antd_plugin_ctx_t* ctx) +{ + return ctx->config; +} diff --git a/lib/plugin.h b/lib/plugin.h index 0d63ab9..c855022 100644 --- a/lib/plugin.h +++ b/lib/plugin.h @@ -1,61 +1,41 @@ #ifndef PLUGIN_H #define PLUGIN_H - #include +#define ANTD_PLUGIN_READY 0x0 +#define ANTD_PLUGIN_PANNIC 0x1 +#define ANTD_PLUGIN_INIT 0x2 + +#define PLUGIN_INIT "create" +#define PLUGIN_HANDLE "handle" +#define PLUGIN_DROP "drop" + +#define DEF_PLUGIN_INTERFACE(name, param, ret) ret##name(param) + #include "utils.h" -#include "handle.h" - +#include "dictionary.h" +#define PLUGIN_PANIC(ctx, a, ...) \ + ERROR("%s: " a, antd_plugin_name(ctx), ##__VA_ARGS__); \ + antd_plugin_set_status(ctx, ANTD_PLUGIN_PANNIC); -char* config_dir(); -/*Default function for plugin*/ -// init the plugin -void init(); -void destroy(); -void* handle(void*); -plugin_header_t* meta(); -void use_raw_body(); +typedef struct _plugin_ctx_t antd_plugin_ctx_t; -/* -STATIC PART, should be included in any plugin -*/ -#ifdef PLUGIN_IMPLEMENT +const char *antd_plugin_basedir(antd_plugin_ctx_t *); +const char *antd_plugin_tmpdir(antd_plugin_ctx_t *); +const char *antd_plugin_confdir(antd_plugin_ctx_t *); +const char *antd_plugin_name(antd_plugin_ctx_t *); +void antd_plugin_set_status(antd_plugin_ctx_t *, int); +int antd_plugin_status(antd_plugin_ctx_t *); +void antd_plugin_use_raw_body(antd_plugin_ctx_t *); +int antd_plugin_is_raw_body(antd_plugin_ctx_t *); +void *antd_plugin_data(antd_plugin_ctx_t *); +dictionary_t antd_plugin_config(antd_plugin_ctx_t*); -#define PLUGIN_PANIC(a,...) \ - ERROR("%s: "a,__plugin__.name, ##__VA_ARGS__); \ - __plugin__.status = ANTD_PLUGIN_PANNIC; +/*Default interfaces shall be implemented by plugin*/ +void *create(antd_plugin_ctx_t *); +void drop(antd_plugin_ctx_t *); +void *handle(void *); -static plugin_header_t __plugin__; -// private function -void __init_plugin__(plugin_header_t* pl, dictionary_t* conf){ - (void) memcpy(&__plugin__, pl, sizeof(plugin_header_t)); - __plugin__.status = ANTD_PLUGIN_READY; - init(); -}; -void use_raw_body() -{ - __plugin__.raw_body = 1; -} - -plugin_header_t* meta() -{ - return &__plugin__; -} - -char* config_dir() -{ - struct stat st; - char* path = __s("%s%s%s", __plugin__.pdir,DIR_SEP, __plugin__.name); - if (stat(path, &st) == -1) - mkdir(path, 0755); - return path; -} - -void __release__() -{ - destroy(); -} -#endif #endif diff --git a/lib/plugin_ctx.h b/lib/plugin_ctx.h new file mode 100644 index 0000000..31a1dd0 --- /dev/null +++ b/lib/plugin_ctx.h @@ -0,0 +1,18 @@ +#ifndef PLUGIN_CTX_H +#define PLUGIN_CTX_H +#include "handle.h" +struct _plugin_ctx_t +{ + char * name; + const char * tmpdir; + const char * basedir; + char * confdir; + int raw_body; + int status; + dictionary_t config; + void * data; + void *(*handle)(void *); + void *(*create)(struct _plugin_ctx_t *); + void (*drop)(struct _plugin_ctx_t *); +} ; +#endif \ No newline at end of file diff --git a/lib/scheduler.c b/lib/scheduler.c index 7a14eae..093f177 100644 --- a/lib/scheduler.c +++ b/lib/scheduler.c @@ -533,7 +533,7 @@ void antd_scheduler_destroy(antd_scheduler_t *scheduler) */ antd_task_t *antd_create_task(void *(*handle)(void *), void *data, void *(*callback)(void *), time_t atime) { - antd_task_t *task = (antd_task_t *)malloc(sizeof *task); + antd_task_t *task = (antd_task_t *)malloc(sizeof(antd_task_t)); task->stamp = (unsigned long)time(NULL); task->data = data; task->handle = handle; diff --git a/lib/scheduler.h b/lib/scheduler.h index 2d11a13..8a9a01f 100644 --- a/lib/scheduler.h +++ b/lib/scheduler.h @@ -1,8 +1,6 @@ #ifndef ANT_SCHEDULER #define ANT_SCHEDULER -#include -#include #include diff --git a/lib/utils.c b/lib/utils.c index 08d6176..c81c6bf 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -46,6 +46,8 @@ THE SOFTWARE. #include "dictionary.h" // #include +static dictionary_t g_mime_list = NULL; + /** * Trim a string by a character on both ends * @param str The target string @@ -184,8 +186,14 @@ void verify_header(char *k) dictionary_t mimes_list() { - return NULL; + return g_mime_list; } + +void set_mimes_list(dictionary_t dict) +{ + g_mime_list = dict; +} + /*get mime file info from type*/ mime_t mime_from_type(const char *type) { diff --git a/lib/utils.h b/lib/utils.h index 3c36a8a..dc08cdb 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -34,6 +34,7 @@ THE SOFTWARE. #include "dictionary.h" +#define STRINGIFY(x) #x #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) #define EQU(a,b) (strcmp(a,b) == 0) #define IEQU(a,b) (strcasecmp(a,b) == 0) @@ -44,9 +45,9 @@ THE SOFTWARE. #define true 1 #define false 0 -#define LOG(a,...) syslog (LOG_NOTICE,"ANTD_LOG@[%s: %d]: " a "\n", __FILE__, \ +#define LOG(a,...) syslog (LOG_NOTICE,"ANTD_LOG@[%s:%d]: " a "\n", __FILE__, \ __LINE__, ##__VA_ARGS__) -#define ERROR(a,...) syslog (LOG_ERR, "ANTD_ERROR@[%s: %d]: " a "\n", __FILE__, \ +#define ERROR(a,...) syslog (LOG_ERR, "ANTD_ERROR@[%s:%d]: " a "\n", __FILE__, \ __LINE__, ##__VA_ARGS__) // add this to the utils #define UNUSED(x) (void)(x) @@ -65,7 +66,8 @@ typedef union struct sockaddr_in addr4; } antd_sockaddr_t; -dictionary_t __attribute__((weak)) mimes_list(); +dictionary_t mimes_list(); +void set_mimes_list(dictionary_t); char* __s(const char*,...); void trim(char*,const char); void removeAll(const char* path,int mode); diff --git a/plugin_manager.c b/plugin_manager.c index 9b762e9..ab8c791 100644 --- a/plugin_manager.c +++ b/plugin_manager.c @@ -5,16 +5,21 @@ #include #include #include -#include "plugin_manager.h" #include "lib/utils.h" #include "lib/handle.h" #include "config.h" +#include "lib/plugin_ctx.h" +#include "plugin_manager.h" + +struct plugin_entry { + struct plugin_entry *next; + char *name; + void *handle; + dictionary_t instances; +}; extern config_t g_server_config; -static void unload_plugin_by_name(const char *); -static void *plugin_from_file(char *name, char *path, dictionary_t conf); - /** * Plugin table to store the loaded plugin */ @@ -25,8 +30,12 @@ static struct plugin_entry *plugin_table[HASHSIZE]; * @param s plugin name * @return a plugin entry in the plugin table */ -struct plugin_entry *plugin_lookup(char *s) +static struct plugin_entry *plugin_lookup(const char *s) { + if(!s) + { + return NULL; + } struct plugin_entry *np; for (np = plugin_table[hash(s, HASHSIZE)]; np != NULL; np = np->next) if (strcmp(s, np->name) == 0) @@ -34,6 +43,136 @@ struct plugin_entry *plugin_lookup(char *s) return NULL; /* not found */ } +static void antd_plugin_ctx_drop(struct plugin_entry* np, antd_plugin_ctx_t* ctx) +{ + if(!ctx) + { + return; + } + if(ctx->drop) + { + if(ctx->name) + LOG("Release user resource for context: %s", ctx->name); + ctx->drop((void*)ctx); + } + if(ctx->name) + { + LOG("Dropping plugin context: %s", ctx->name); + if(np->instances) + { + dput(np->instances, ctx->name, NULL); + } + free(ctx->name); + } + if(ctx->confdir) + { + free(ctx->confdir); + } + free(ctx); +} + + +static antd_plugin_ctx_t* antd_plugin_ctx_lookup(struct plugin_entry* np, const char* name) +{ + if(!np || !np->instances) + { + return NULL; + } + LOG("Looking for plugin context: %s", name); + antd_plugin_ctx_t* ctx = dvalue(np->instances, name); + if(ctx == NULL) + { + char *error; + LOG("Create new plugin context: %s", name); + ctx = (antd_plugin_ctx_t *)malloc(sizeof(antd_plugin_ctx_t)); + if(!ctx) + { + ERROR("Unable to allocate memory for plugin context `%s`: %s", name, strerror(errno)); + return NULL; + } + // init the context + ctx->basedir = g_server_config.plugins_dir; + ctx->tmpdir = g_server_config.tmpdir; + ctx->name = strdup(name); + ctx->confdir = NULL; + ctx->raw_body = 0; + ctx->status = ANTD_PLUGIN_INIT; + ctx->config=dvalue(g_server_config.plugins, name); + ctx->data = NULL; + ctx->handle = NULL; + ctx->create = NULL; + ctx->drop = NULL; + // look for handle function + ctx->handle = (void* (*)(void *))dlsym(np->handle, PLUGIN_HANDLE); + if ((error = dlerror()) != NULL) + { + ERROR("Problem when finding plugin handle function for %s : %s", name, error); + ctx->handle = NULL; + antd_plugin_ctx_drop(np, ctx); + return NULL; + } + // look for drop function + ctx->drop = (void (*)(antd_plugin_ctx_t *))dlsym(np->handle, PLUGIN_DROP); + if ((error = dlerror()) != NULL) + { + ERROR("Problem when finding plugin drop function for %s : %s", name, error); + ctx->drop = NULL; + antd_plugin_ctx_drop(np, ctx); + return NULL; + } + // look for init function + ctx->create = (void* (*)(antd_plugin_ctx_t *))dlsym(np->handle, PLUGIN_INIT); + if ((error = dlerror()) != NULL) + { + ERROR("Problem when finding plugin init function for %s : %s.", name, error); + ctx->create = NULL; + antd_plugin_ctx_drop(np, ctx); + return NULL; + } + else + { + // run the init function + ctx->data = ctx->create(ctx); + if(ctx->status == ANTD_PLUGIN_PANNIC) + { + ERROR("PANIC happens when init plugin context %s. drop it", name); + antd_plugin_ctx_drop(np, ctx); + return NULL; + } + ctx->status = ANTD_PLUGIN_READY; + } + dput(np->instances, name, (void*)ctx); + } + return ctx; +} + +static void antd_plugin_entry_drop(struct plugin_entry* np) +{ + if(!np) + { + return; + } + if(np->name) + { + LOG("Unloaded %s", np->name); + free(np->name); + } + if(np->instances) + { + chain_t it; + for_each_assoc(it, np->instances) + { + antd_plugin_ctx_drop(np,(antd_plugin_ctx_t*)it->value); + } + freedict(np->instances); + } + if(np->handle) + { + dlclose(np->handle); + } + free(np); +} + /** * Load a plugin to the plugin table * Only load when not available in the plugin table @@ -41,170 +180,76 @@ struct plugin_entry *plugin_lookup(char *s) * @param config: plugin configuration * @return pointer to the loaded plugin */ -struct plugin_entry *plugin_load(char *name, dictionary_t pconf) +antd_plugin_ctx_t* antd_plugin_load(const char *name) { - char *pname = NULL; + const char *plugin_file_name = NULL; char path[BUFFLEN]; struct plugin_entry *np; unsigned hashval; - plugin_header_t *(*metafn)(); - plugin_header_t *meta = NULL; - int fromfd, tofd; - char *error; - struct stat st; - int is_tmp = 0; + antd_plugin_ctx_t *ctx; + dictionary_t pconf = dvalue(g_server_config.plugins, name); if (pconf) { - pname = dvalue(pconf, "name"); + plugin_file_name = dvalue(pconf, "name"); } - if ((np = plugin_lookup(name)) == NULL) + if(plugin_file_name == NULL) + { + plugin_file_name = name; + } + if(plugin_file_name == NULL) + { + return NULL; + } + if ((np = plugin_lookup(plugin_file_name)) == NULL) { /* not found */ - LOG("Loading plugin: %s...", name); - np = (struct plugin_entry *)malloc(sizeof(*np)); - if (np == NULL || name == NULL) + LOG("Loading plugin: %s...", plugin_file_name); + np = (struct plugin_entry *)malloc(sizeof(struct plugin_entry)); + np->instances = NULL; + if (np == NULL) { - if (np) - free(np); return NULL; } - (void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, name, g_server_config.plugins_ext); - if (pname && strcmp(name, pname) != 0) + (void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, plugin_file_name, g_server_config.plugins_ext); + np->name = strdup(plugin_file_name); + // now load it from file + np->handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL /*| RTLD_NODELETE*/); + if (!np->handle) { - // copy plugin file to tmpdir - (void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, pname, g_server_config.plugins_ext); - LOG("Original plugin file: %s", path); - if ((fromfd = open(path, O_RDONLY)) < 0) - { - ERROR("Unable to open file for reading %s: %s", path, strerror(errno)); - return NULL; - } - if (stat(path, &st) != 0) - { - close(fromfd); - ERROR("Unable to get file stat %s: %s", path, strerror(errno)); - return NULL; - } - (void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.tmpdir, name, g_server_config.plugins_ext); - LOG("TMP plugin file: %s", path); - if ((tofd = open(path, O_WRONLY | O_CREAT, 0600)) < 0) - { - close(fromfd); - ERROR("Unable open file for reading %s: %s", path, strerror(errno)); - return NULL; - } - if (sendfile(tofd, fromfd, NULL, st.st_size) != st.st_size) - { - close(fromfd); - close(tofd); - ERROR("Unable to copy file: %s", strerror(errno)); - return NULL; - } - is_tmp = 1; - } - - np->name = strdup(name); - np->handle = plugin_from_file(name, path, pconf); - if (is_tmp) - { - //TODO change this - (void)remove(path); - } - if (np->handle == NULL) - { - if (np->name) - free(np->name); - if (np) - free(np); + ERROR("Cannot load plugin '%s' : '%s'", plugin_file_name, dlerror()); + antd_plugin_entry_drop(np); return NULL; } + np->instances = dict(); hashval = hash(name, HASHSIZE); np->next = plugin_table[hashval]; plugin_table[hashval] = np; } else /* already there */ { - LOG("The plugin %s id already loaded", name); + LOG("The plugin %s id already loaded", plugin_file_name); } - + // now look for the plugin context + ctx = antd_plugin_ctx_lookup(np, name); // check if plugin is ready - metafn = (plugin_header_t * (*)()) dlsym(np->handle, "meta"); - if ((error = dlerror()) != NULL) + if (ctx == NULL) { - ERROR("Unable to fetch plugin meta-data: [%s] %s", name, error); - unload_plugin_by_name(name); - free(np); + ERROR("Unable to fetch plugin context for: [%s] %s", plugin_file_name, name); return NULL; } - meta = metafn(); - LOG("PLugin status: [%s] %d", name, meta->status); - if (!meta || meta->status != ANTD_PLUGIN_READY) + LOG("PLugin instance status: [%s] %d", name, ctx->status); + if (ctx->status != ANTD_PLUGIN_READY) { - ERROR("Plugin is not ready or error: [%s].", name); - unload_plugin_by_name(name); - free(np); + ERROR("Plugin instance is not ready or error: [%s].", name); + antd_plugin_ctx_drop(np, ctx); return NULL; } - return np; -} -/** - * Find a plugin in a file, and load it in to the plugin table - * @param name Name of the plugin - * @return - */ -static void *plugin_from_file(char *name, char *path, dictionary_t conf) -{ - void *lib_handle; - char *error; - void (*fn)(plugin_header_t *, dictionary_t); - lib_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL /*| RTLD_NODELETE*/); - if (!lib_handle) - { - ERROR("Cannot load plugin '%s' : '%s'", name, dlerror()); - return NULL; - } - fn = (void (*)(plugin_header_t *, dictionary_t))dlsym(lib_handle, "__init_plugin__"); - if ((error = dlerror()) != NULL) - ERROR("Problem when finding plugin init function for %s : %s", name, error); - else - { - plugin_header_t header; - strncpy(header.name, name, MAX_PATH_LEN - 1); - strncpy(header.dbpath, g_server_config.db_path, MAX_PATH_LEN - 1); - strncpy(header.tmpdir, g_server_config.tmpdir, MAX_PATH_LEN - 1); - strncpy(header.pdir, g_server_config.plugins_dir, MAX_PATH_LEN - 1); - header.config = conf; - header.raw_body = 0; - header.status = ANTD_PLUGIN_INIT; - (*fn)(&header, conf); - } - // trick libc that we close this lib, but it is not realy deleted - return lib_handle; + return ctx; } -void unload_plugin(struct plugin_entry *np) -{ - char *error; - void (*fn)() = NULL; - // find and execute the exit function - fn = (void (*)())dlsym(np->handle, "__release__"); - if ((error = dlerror()) != NULL) - { - ERROR("Cant not release plugin %s : %s", np->name, error); - } - if (fn) - { - (*fn)(); - } - dlclose(np->handle); - LOG("Unloaded %s", np->name); - // free((void *) np->handle); - if (np->name) - free((void *)np->name); -} /* Unload a plugin by its name -*/ + void unload_plugin_by_name(const char *name) { struct plugin_entry *np; @@ -212,7 +257,7 @@ void unload_plugin_by_name(const char *name) np = plugin_table[hasval]; if (strcmp(np->name, name) == 0) { - unload_plugin(np); + antd_plugin_entry_drop(np); plugin_table[hasval] = np->next; } else @@ -226,14 +271,16 @@ void unload_plugin_by_name(const char *name) } if (np == NULL) return; // the plugin is is not loaded - unload_plugin(np->next); + antd_plugin_entry_drop(np->next); np->next = np->next->next; } } +*/ + /** * Unload all the plugin loaded on the plugin table */ -void unload_all_plugin() +void antd_unload_all_plugin() { LOG("Unload all plugins"); for (int i = 0; i < HASHSIZE; i++) @@ -244,10 +291,14 @@ void unload_all_plugin() while ((curr = *np) != NULL) { (*np) = (*np)->next; - unload_plugin(curr); - free(curr); + antd_plugin_entry_drop(curr); + //free(curr); } plugin_table[i] = NULL; } - exit(0); +} + +antd_plugin_handle_t antd_get_ctx_handle(antd_plugin_ctx_t *ctx) +{ + return ctx->handle; } diff --git a/plugin_manager.h b/plugin_manager.h index d3384b7..991cffa 100644 --- a/plugin_manager.h +++ b/plugin_manager.h @@ -2,19 +2,12 @@ #define PLUGIN_MANAGER_H #include "lib/dictionary.h" +#include "lib/plugin.h" +#include "lib/scheduler.h" -#define PLUGIN_HANDLER "handle" +typedef void*(*antd_plugin_handle_t)(void *); -struct plugin_entry { - struct plugin_entry *next; - char *name; - void *handle; - dictionary_t instances; -}; -/* lookup: look for s in hashtable */ -struct plugin_entry *plugin_lookup(char *s); -/* install: put (name, defn) in hashtable */ -struct plugin_entry *plugin_load(char *name, dictionary_t config); -void unload_all_plugin(); -void unload_plugin(struct plugin_entry*); +antd_plugin_ctx_t *antd_plugin_load(const char *name); +void antd_unload_all_plugin(); +antd_plugin_handle_t antd_get_ctx_handle(antd_plugin_ctx_t *); #endif \ No newline at end of file diff --git a/server.c b/server.c index 33c0be1..3b835f2 100644 --- a/server.c +++ b/server.c @@ -3,7 +3,6 @@ #endif #include #include -#include #include #include #include @@ -534,13 +533,8 @@ void *proxify(void *data) */ void *execute_plugin(void *data, const char *pname) { - void *(*fn)(void *); - plugin_header_t *(*metafn)(); - plugin_header_t *meta = NULL; - struct plugin_entry *plugin; - char *error; char pattern[256]; - + antd_plugin_ctx_t* ctx; antd_request_t *rq = (antd_request_t *)data; antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io); antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); @@ -561,58 +555,23 @@ void *execute_plugin(void *data, const char *pname) rq->client->state = ANTD_CLIENT_PLUGIN_EXEC; // load the plugin pthread_mutex_lock(&server_mux); - plugin = plugin_load((char *)pname, dvalue(g_server_config.plugins, pname)); + ctx = antd_plugin_load(pname); pthread_mutex_unlock(&server_mux); - if (plugin == NULL) + if (ctx == NULL) { 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"); - if ((error = dlerror()) == NULL) - { - meta = metafn(); - } - // load the function - fn = (void *(*)(void *))dlsym(plugin->handle, PLUGIN_HANDLER); - if ((error = dlerror()) != NULL) - { - ERROR("Problem when finding %s method from %s : %s", PLUGIN_HANDLER, pname, error); - antd_error(rq->client, 503, "Requested service not found"); - return task; - } + rq->context = ctx; // check if we need the raw data or not - if (meta && meta->raw_body == 1) + if (antd_plugin_is_raw_body(ctx) == 1) { - task->handle = fn; + task->handle = antd_get_ctx_handle(ctx); } else { free(task); - task = antd_create_task(decode_post_request, (void *)rq, fn, rq->client->last_io); + task = antd_create_task(decode_post_request, (void *)rq, antd_get_ctx_handle(ctx), rq->client->last_io); } return task; } - -dictionary_t mimes_list() -{ - return g_server_config.mimes; -} - -#ifdef USE_ZLIB -int compressable(char *ctype) -{ - if (!g_server_config.gzip_enable || g_server_config.gzip_types == NULL) - return 0; - item_t it; - list_for_each(it, g_server_config.gzip_types) - { - if (it->type == LIST_TYPE_POINTER && it->value.ptr && regex_match((const char *)it->value.ptr, ctype, 0, NULL)) - { - return 1; - } - } - return 0; -} -#endif diff --git a/server.h b/server.h index 90bf66a..e32667a 100644 --- a/server.h +++ b/server.h @@ -1,8 +1,8 @@ #ifndef HTTP_SERVER #define HTTP_SERVER -void *accept_request(void *); -void *proxify(void *data); -void *resolve_request(void *data); -void *finish_request(void *data); +void * accept_request(void *); +void * proxify(void *data); +void * resolve_request(void *data); +void * finish_request(void *data); #endif \ No newline at end of file