kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 21b148e3a596f988b4fff965535e3ac230049d71
parent f2aa206f3bc7cba5faad24913e5063ea6878066d
Author: Joris Vink <joris@coders.se>
Date:   Sun, 15 Dec 2013 01:11:56 +0100

Allow Kore to load multiple modules at once.

Diffstat:
includes/kore.h | 13+++++++++++--
src/config.c | 22+++-------------------
src/kore.c | 1+
src/module.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
4 files changed, 102 insertions(+), 75 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -171,6 +171,15 @@ struct kore_handler_params { #define HANDLER_TYPE_STATIC 1 #define HANDLER_TYPE_DYNAMIC 2 +struct kore_module { + void *handle; + char *path; + char *onload; + time_t mtime; + + TAILQ_ENTRY(kore_module) list; +}; + struct kore_module_handle { char *path; char *func; @@ -263,7 +272,6 @@ extern int kore_debug; extern int skip_chroot; extern char *chroot_path; extern char *runas_user; -extern char *kore_module_onload; extern char *kore_pidfile; extern char *config_file; extern char *kore_cb_name; @@ -357,11 +365,12 @@ void *kore_mem_find(void *, size_t, void *, u_int32_t); void kore_domain_init(void); int kore_domain_new(char *); -void kore_module_load(char *); +void kore_module_init(void); void kore_module_reload(void); int kore_module_loaded(void); void kore_domain_closelogs(void); void *kore_module_getsym(char *); +void kore_module_load(char *, char *); void kore_domain_sslstart(struct kore_domain *); int kore_module_handler_new(char *, char *, char *, int); struct kore_domain *kore_domain_lookup(const char *); diff --git a/src/config.c b/src/config.c @@ -24,7 +24,6 @@ static int configure_bind(char **); static int configure_load(char **); -static int configure_onload(char **); static int configure_handler(char **); static int configure_domain(char **); static int configure_chroot(char **); @@ -58,7 +57,6 @@ static struct { } config_names[] = { { "bind", configure_bind }, { "load", configure_load }, - { "onload", configure_onload }, { "static", configure_handler }, { "dynamic", configure_handler }, { "ssl_cipher", configure_ssl_cipher }, @@ -148,7 +146,8 @@ kore_parse_config(void) if (!kore_module_loaded()) fatal("no site module was loaded"); - + if (kore_cb_name != NULL && kore_cb == NULL) + fatal("no '%s' symbol found for kore_cb", kore_cb_name); if (LIST_EMPTY(&listeners)) fatal("no listeners defined"); if (chroot_path == NULL) @@ -177,22 +176,7 @@ configure_load(char **argv) if (argv[1] == NULL) return (KORE_RESULT_ERROR); - kore_module_load(argv[1]); - return (KORE_RESULT_OK); -} - -static int -configure_onload(char **argv) -{ - if (argv[1] == NULL) - return (KORE_RESULT_ERROR); - - if (kore_module_onload != NULL) { - kore_debug("duplicate onload directive found"); - return (KORE_RESULT_ERROR); - } - - kore_module_onload = kore_strdup(argv[1]); + kore_module_load(argv[1], argv[2]); return (KORE_RESULT_OK); } diff --git a/src/kore.c b/src/kore.c @@ -88,6 +88,7 @@ main(int argc, char *argv[]) kore_log_init(); kore_mem_init(); kore_domain_init(); + kore_module_init(); kore_validator_init(); kore_server_sslstart(); kore_parse_config(); diff --git a/src/module.c b/src/module.c @@ -20,94 +20,118 @@ #include "kore.h" -static void *mod_handle = NULL; -static char *mod_name = NULL; -static time_t mod_last_mtime = 0; +static TAILQ_HEAD(, kore_module) modules; +char *kore_cb_name = NULL; -char *kore_cb_name = NULL; -char *kore_module_onload = NULL; +void +kore_module_init(void) +{ + TAILQ_INIT(&modules); + TAILQ_INIT(&domains); +} void -kore_module_load(char *module_name) +kore_module_load(char *path, char *onload) { struct stat st; - void (*onload)(void); + struct kore_module *module; + void (*cb)(void); - kore_debug("kore_module_load(%s)", module_name); + kore_debug("kore_module_load(%s, %s)", path, onload); - if (mod_handle != NULL) - fatal("site module already loaded, skipping %s", module_name); + if (stat(path, &st) == -1) + fatal("stat(%s): %s", path, errno_s); - if (stat(module_name, &st) == -1) - fatal("stat(%s): %s", module_name, errno_s); + module = kore_malloc(sizeof(struct kore_module)); + module->path = kore_strdup(path); + module->mtime = st.st_mtime; + module->onload = NULL; - mod_last_mtime = st.st_mtime; - mod_handle = dlopen(module_name, RTLD_NOW); - if (mod_handle == NULL) - fatal("%s", dlerror()); + module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); + if (module->handle == NULL) + fatal("%s: %s", path, dlerror()); - TAILQ_INIT(&domains); - mod_name = kore_strdup(module_name); - - if (kore_module_onload != NULL) { - onload = dlsym(mod_handle, kore_module_onload); - if (onload == NULL) - fatal("onload '%s' not present", kore_module_onload); - onload(); + if (onload != NULL) { + module->onload = kore_strdup(onload); + cb = dlsym(module->handle, onload); + if (cb == NULL) + fatal("%s: onload '%s' not present", path, onload); + cb(); } - if (kore_cb_name != NULL) { - kore_cb = dlsym(mod_handle, kore_cb_name); - if (kore_cb == NULL) - fatal("kore_cb '%s' not present", kore_cb_name); - } + if (kore_cb_name != NULL && kore_cb == NULL) + kore_cb = dlsym(module->handle, kore_cb_name); + + TAILQ_INSERT_TAIL(&modules, module, list); } void kore_module_reload(void) { + struct stat st; struct kore_domain *dom; struct kore_module_handle *hdlr; + struct kore_module *module; void (*onload)(void); - if (dlclose(mod_handle)) - fatal("cannot close existing module: %s", dlerror()); + kore_cb = NULL; + + TAILQ_FOREACH(module, &modules, list) { + if (stat(module->path, &st) == -1) { + kore_log(LOG_NOTICE, "stat(%s): %s, skipping reload", + module->path, errno_s); + continue; + } + + if (module->mtime == st.st_mtime) + continue; + + module->mtime = st.st_mtime; + if (dlclose(module->handle)) + fatal("cannot close existing module: %s", dlerror()); + + module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); + if (module->handle == NULL) + fatal("kore_module_reload(): %s", dlerror()); + + if (module->onload != NULL) { + onload = dlsym(module->handle, module->onload); + if (onload == NULL) { + fatal("%s: onload '%s' not present", + module->path, module->onload); + } + + onload(); + } - mod_handle = dlopen(mod_name, RTLD_NOW); - if (mod_handle == NULL) - fatal("kore_module_reload(): %s", dlerror()); + if (kore_cb_name != NULL && kore_cb == NULL) + kore_cb = dlsym(module->handle, kore_cb_name); + + kore_log(LOG_NOTICE, "reloaded '%s' module", module->path); + } + + if (kore_cb_name != NULL && kore_cb == NULL) + fatal("no kore_cb %s found in loaded modules", kore_cb_name); TAILQ_FOREACH(dom, &domains, list) { TAILQ_FOREACH(hdlr, &(dom->handlers), list) { - hdlr->errors = 0; - hdlr->addr = dlsym(mod_handle, hdlr->func); + hdlr->addr = kore_module_getsym(hdlr->func); if (hdlr->func == NULL) fatal("no function '%s' found", hdlr->func); + hdlr->errors = 0; } } kore_validator_reload(); - - if (kore_module_onload != NULL) { - onload = dlsym(mod_handle, kore_module_onload); - if (onload == NULL) - fatal("onload '%s' not present", kore_module_onload); - onload(); - } - - if (kore_cb_name != NULL) { - kore_cb = dlsym(mod_handle, kore_cb_name); - if (kore_cb == NULL) - fatal("kore_cb '%s' not present", kore_cb_name); - } - - kore_log(LOG_NOTICE, "reloaded '%s' module", mod_name); } int kore_module_loaded(void) { - return (mod_handle != NULL ? KORE_RESULT_OK : KORE_RESULT_ERROR); + if (TAILQ_EMPTY(&modules)) + return (0); + + return (1); } int @@ -120,7 +144,7 @@ kore_module_handler_new(char *path, char *domain, char *func, int type) kore_debug("kore_module_handler_new(%s, %s, %s, %d)", path, domain, func, type); - addr = dlsym(mod_handle, func); + addr = kore_module_getsym(func); if (addr == NULL) { kore_debug("function '%s' not found", func); return (KORE_RESULT_ERROR); @@ -177,5 +201,14 @@ kore_module_handler_find(char *domain, char *path) void * kore_module_getsym(char *symbol) { - return (dlsym(mod_handle, symbol)); + void *ptr; + struct kore_module *module; + + TAILQ_FOREACH(module, &modules, list) { + ptr = dlsym(module->handle, symbol); + if (ptr != NULL) + return (ptr); + } + + return (NULL); }