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