Allow Kore to load multiple modules at once.

This commit is contained in:
Joris Vink 2013-12-15 01:11:56 +01:00
parent f2aa206f3b
commit 21b148e3a5
4 changed files with 103 additions and 76 deletions

View File

@ -171,6 +171,15 @@ struct kore_handler_params {
#define HANDLER_TYPE_STATIC 1 #define HANDLER_TYPE_STATIC 1
#define HANDLER_TYPE_DYNAMIC 2 #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 { struct kore_module_handle {
char *path; char *path;
char *func; char *func;
@ -263,7 +272,6 @@ extern int kore_debug;
extern int skip_chroot; extern int skip_chroot;
extern char *chroot_path; extern char *chroot_path;
extern char *runas_user; extern char *runas_user;
extern char *kore_module_onload;
extern char *kore_pidfile; extern char *kore_pidfile;
extern char *config_file; extern char *config_file;
extern char *kore_cb_name; 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); void kore_domain_init(void);
int kore_domain_new(char *); int kore_domain_new(char *);
void kore_module_load(char *); void kore_module_init(void);
void kore_module_reload(void); void kore_module_reload(void);
int kore_module_loaded(void); int kore_module_loaded(void);
void kore_domain_closelogs(void); void kore_domain_closelogs(void);
void *kore_module_getsym(char *); void *kore_module_getsym(char *);
void kore_module_load(char *, char *);
void kore_domain_sslstart(struct kore_domain *); void kore_domain_sslstart(struct kore_domain *);
int kore_module_handler_new(char *, char *, char *, int); int kore_module_handler_new(char *, char *, char *, int);
struct kore_domain *kore_domain_lookup(const char *); struct kore_domain *kore_domain_lookup(const char *);

View File

@ -24,7 +24,6 @@
static int configure_bind(char **); static int configure_bind(char **);
static int configure_load(char **); static int configure_load(char **);
static int configure_onload(char **);
static int configure_handler(char **); static int configure_handler(char **);
static int configure_domain(char **); static int configure_domain(char **);
static int configure_chroot(char **); static int configure_chroot(char **);
@ -58,7 +57,6 @@ static struct {
} config_names[] = { } config_names[] = {
{ "bind", configure_bind }, { "bind", configure_bind },
{ "load", configure_load }, { "load", configure_load },
{ "onload", configure_onload },
{ "static", configure_handler }, { "static", configure_handler },
{ "dynamic", configure_handler }, { "dynamic", configure_handler },
{ "ssl_cipher", configure_ssl_cipher }, { "ssl_cipher", configure_ssl_cipher },
@ -148,7 +146,8 @@ kore_parse_config(void)
if (!kore_module_loaded()) if (!kore_module_loaded())
fatal("no site module was 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)) if (LIST_EMPTY(&listeners))
fatal("no listeners defined"); fatal("no listeners defined");
if (chroot_path == NULL) if (chroot_path == NULL)
@ -177,22 +176,7 @@ configure_load(char **argv)
if (argv[1] == NULL) if (argv[1] == NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
kore_module_load(argv[1]); kore_module_load(argv[1], argv[2]);
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]);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }

View File

@ -88,6 +88,7 @@ main(int argc, char *argv[])
kore_log_init(); kore_log_init();
kore_mem_init(); kore_mem_init();
kore_domain_init(); kore_domain_init();
kore_module_init();
kore_validator_init(); kore_validator_init();
kore_server_sslstart(); kore_server_sslstart();
kore_parse_config(); kore_parse_config();

View File

@ -20,94 +20,118 @@
#include "kore.h" #include "kore.h"
static void *mod_handle = NULL; static TAILQ_HEAD(, kore_module) modules;
static char *mod_name = NULL;
static time_t mod_last_mtime = 0;
char *kore_cb_name = NULL; char *kore_cb_name = NULL;
char *kore_module_onload = NULL;
void void
kore_module_load(char *module_name) kore_module_init(void)
{
TAILQ_INIT(&modules);
TAILQ_INIT(&domains);
}
void
kore_module_load(char *path, char *onload)
{ {
struct stat st; 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) if (stat(path, &st) == -1)
fatal("site module already loaded, skipping %s", module_name); fatal("stat(%s): %s", path, errno_s);
if (stat(module_name, &st) == -1) module = kore_malloc(sizeof(struct kore_module));
fatal("stat(%s): %s", module_name, errno_s); module->path = kore_strdup(path);
module->mtime = st.st_mtime;
module->onload = NULL;
mod_last_mtime = st.st_mtime; module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL);
mod_handle = dlopen(module_name, RTLD_NOW); if (module->handle == NULL)
if (mod_handle == NULL) fatal("%s: %s", path, dlerror());
fatal("%s", dlerror());
TAILQ_INIT(&domains); if (onload != NULL) {
mod_name = kore_strdup(module_name); module->onload = kore_strdup(onload);
cb = dlsym(module->handle, onload);
if (kore_module_onload != NULL) { if (cb == NULL)
onload = dlsym(mod_handle, kore_module_onload); fatal("%s: onload '%s' not present", path, onload);
if (onload == NULL) cb();
fatal("onload '%s' not present", kore_module_onload);
onload();
} }
if (kore_cb_name != NULL) { if (kore_cb_name != NULL && kore_cb == NULL)
kore_cb = dlsym(mod_handle, kore_cb_name); kore_cb = dlsym(module->handle, kore_cb_name);
if (kore_cb == NULL)
fatal("kore_cb '%s' not present", kore_cb_name); TAILQ_INSERT_TAIL(&modules, module, list);
}
} }
void void
kore_module_reload(void) kore_module_reload(void)
{ {
struct stat st;
struct kore_domain *dom; struct kore_domain *dom;
struct kore_module_handle *hdlr; struct kore_module_handle *hdlr;
struct kore_module *module;
void (*onload)(void); void (*onload)(void);
if (dlclose(mod_handle)) 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()); fatal("cannot close existing module: %s", dlerror());
mod_handle = dlopen(mod_name, RTLD_NOW); module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL);
if (mod_handle == NULL) if (module->handle == NULL)
fatal("kore_module_reload(): %s", dlerror()); 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();
}
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(dom, &domains, list) {
TAILQ_FOREACH(hdlr, &(dom->handlers), list) { TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
hdlr->errors = 0; hdlr->addr = kore_module_getsym(hdlr->func);
hdlr->addr = dlsym(mod_handle, hdlr->func);
if (hdlr->func == NULL) if (hdlr->func == NULL)
fatal("no function '%s' found", hdlr->func); fatal("no function '%s' found", hdlr->func);
hdlr->errors = 0;
} }
} }
kore_validator_reload(); 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 int
kore_module_loaded(void) kore_module_loaded(void)
{ {
return (mod_handle != NULL ? KORE_RESULT_OK : KORE_RESULT_ERROR); if (TAILQ_EMPTY(&modules))
return (0);
return (1);
} }
int 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, kore_debug("kore_module_handler_new(%s, %s, %s, %d)", path,
domain, func, type); domain, func, type);
addr = dlsym(mod_handle, func); addr = kore_module_getsym(func);
if (addr == NULL) { if (addr == NULL) {
kore_debug("function '%s' not found", func); kore_debug("function '%s' not found", func);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
@ -177,5 +201,14 @@ kore_module_handler_find(char *domain, char *path)
void * void *
kore_module_getsym(char *symbol) 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);
} }