@@ -634,8 +634,12 @@ ELSE(ENABLE_LUAJIT MATCHES "ON") | |||
ENDIF(NOT LUA_FOUND) | |||
ENDIF(ENABLE_LUAJIT MATCHES "ON") | |||
ProcessPackage(GLIB2 LIBRARY glib-2.0 INCLUDE glib.h INCLUDE_SUFFIXES include/glib | |||
ProcessPackage(GLIB2 LIBRARY glib-2.0 INCLUDE glib.h | |||
INCLUDE_SUFFIXES include/glib | |||
ROOT ${GLIB_ROOT_DIR} MODULES glib-2.0>=2.28) | |||
ProcessPackage(GMODULE2 LIBRARY gmodule-2.0 INCLUDE glib.h | |||
INCLUDE_SUFFIXES include/glib | |||
ROOT ${GLIB_ROOT_DIR} MODULES gmodule-2.0>=2.28) | |||
IF(ENABLE_PCRE2 MATCHES "ON") | |||
ProcessPackage(PCRE LIBRARY pcre2 INCLUDE pcre2.h INCLUDE_SUFFIXES include/pcre2 |
@@ -528,9 +528,11 @@ rspamd_rcl_worker_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
struct rspamd_rcl_section *section, GError **err) | |||
{ | |||
const ucl_object_t *val, *cur, *cur_obj; | |||
struct rspamd_dynamic_worker *dyn_wrk; | |||
worker_t *dyn_ctx; | |||
ucl_object_t *robj; | |||
ucl_object_iter_t it = NULL; | |||
const gchar *worker_type, *worker_bind; | |||
const gchar *worker_type, *worker_bind, *lib_path; | |||
struct rspamd_config *cfg = ud; | |||
GQuark qtype; | |||
struct rspamd_worker_conf *wrk; | |||
@@ -541,6 +543,49 @@ rspamd_rcl_worker_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
g_assert (key != NULL); | |||
worker_type = key; | |||
val = ucl_object_find_any_key (obj, "module", "load", NULL); | |||
if (val != NULL && ucl_object_tostring_safe (val, &lib_path)) { | |||
if (!g_module_supported ()) { | |||
msg_err_config ("modules are not supported, so load of %s is impossible", | |||
worker_type); | |||
return FALSE; | |||
} | |||
dyn_wrk = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*dyn_wrk)); | |||
dyn_wrk->lib = g_module_open (lib_path, G_MODULE_BIND_LAZY); | |||
if (dyn_wrk->lib == NULL) { | |||
msg_err_config ("cannot load %s at %s: %s", worker_type, | |||
lib_path, strerror (errno)); | |||
return FALSE; | |||
} | |||
if (!g_module_symbol (dyn_wrk->lib, "rspamd_dyn_worker", | |||
(gpointer *)&dyn_ctx)) { | |||
msg_err_config ("cannot load %s at %s: missing entry point", | |||
worker_type, | |||
lib_path); | |||
g_module_close (dyn_wrk->lib); | |||
return FALSE; | |||
} | |||
if (!rspamd_check_worker (cfg, dyn_ctx)) { | |||
g_module_close (dyn_wrk->lib); | |||
return FALSE; | |||
} | |||
memcpy (&dyn_wrk->wrk, dyn_ctx, sizeof (dyn_wrk->wrk)); | |||
dyn_wrk->path = lib_path; | |||
dyn_wrk->type = g_quark_from_static_string (worker_type); | |||
cfg->dynamic_workers = g_list_prepend (cfg->dynamic_workers, dyn_wrk); | |||
} | |||
qtype = g_quark_try_string (worker_type); | |||
if (qtype != 0) { | |||
wrk = rspamd_config_new_worker (cfg, NULL); | |||
@@ -563,11 +608,8 @@ rspamd_rcl_worker_handler (rspamd_mempool_t *pool, const ucl_object_t *obj, | |||
return TRUE; | |||
} | |||
val = ucl_object_find_key (obj, "bind_socket"); | |||
val = ucl_object_find_any_key (obj, "bind_socket", "listen", "bind", NULL); | |||
/* This name is more logical */ | |||
if (val == NULL) { | |||
val = ucl_object_find_key (obj, "listen"); | |||
} | |||
if (val != NULL) { | |||
it = ucl_object_iterate_new (val); | |||
while ((cur = ucl_object_iterate_safe (it, true)) != NULL) { |
@@ -162,6 +162,10 @@ rspamd_config_new (void) | |||
void | |||
rspamd_config_free (struct rspamd_config *cfg) | |||
{ | |||
struct rspamd_dynamic_module *dyn_mod; | |||
struct rspamd_dynamic_worker *dyn_wrk; | |||
GList *cur; | |||
rspamd_map_remove_all (cfg); | |||
ucl_object_unref (cfg->rcl_obj); | |||
ucl_object_unref (cfg->doc_strings); | |||
@@ -182,6 +186,28 @@ rspamd_config_free (struct rspamd_config *cfg) | |||
g_free (cfg->checksum); | |||
} | |||
/* Unload dynamic workers/modules */ | |||
cur = g_list_first (cfg->dynamic_modules); | |||
while (cur) { | |||
dyn_mod = cur->data; | |||
if (dyn_mod->lib) { | |||
g_module_close (dyn_mod->lib); | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
cur = g_list_first (cfg->dynamic_workers); | |||
while (cur) { | |||
dyn_wrk = cur->data; | |||
if (dyn_wrk->lib) { | |||
g_module_close (dyn_wrk->lib); | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
g_list_free (cfg->classifiers); | |||
g_list_free (cfg->metrics_list); | |||
rspamd_symbols_cache_destroy (cfg->cache); | |||
@@ -1192,6 +1218,7 @@ rspamd_init_filters (struct rspamd_config *cfg, bool reconfig) | |||
{ | |||
GList *cur; | |||
module_t *mod, **pmod; | |||
struct rspamd_dynamic_module *dyn_mod; | |||
struct module_ctx *mod_ctx; | |||
/* Init all compiled modules */ | |||
@@ -1214,16 +1241,20 @@ rspamd_init_filters (struct rspamd_config *cfg, bool reconfig) | |||
cur = g_list_first (cfg->dynamic_modules); | |||
while (cur) { | |||
mod = cur->data; | |||
dyn_mod = cur->data; | |||
if (rspamd_check_module (cfg, mod)) { | |||
mod_ctx = g_slice_alloc0 (sizeof (struct module_ctx)); | |||
if (dyn_mod->lib) { | |||
mod = &dyn_mod->mod; | |||
if (mod->module_init_func (cfg, &mod_ctx) == 0) { | |||
g_hash_table_insert (cfg->c_modules, | |||
(gpointer) mod->name, | |||
mod_ctx); | |||
mod_ctx->mod = mod; | |||
if (rspamd_check_module (cfg, mod)) { | |||
mod_ctx = g_slice_alloc0 (sizeof (struct module_ctx)); | |||
if (mod->module_init_func (cfg, &mod_ctx) == 0) { | |||
g_hash_table_insert (cfg->c_modules, | |||
(gpointer) mod->name, | |||
mod_ctx); | |||
mod_ctx->mod = mod; | |||
} | |||
} | |||
} | |||
@@ -50,6 +50,7 @@ worker_t * | |||
rspamd_get_worker_by_type (struct rspamd_config *cfg, GQuark type) | |||
{ | |||
worker_t **pwrk, *wrk; | |||
struct rspamd_dynamic_worker *dyn_wrk; | |||
GList *cur; | |||
pwrk = cfg->compiled_workers; | |||
@@ -65,11 +66,15 @@ rspamd_get_worker_by_type (struct rspamd_config *cfg, GQuark type) | |||
cur = g_list_first (cfg->dynamic_workers); | |||
while (cur) { | |||
wrk = cur->data; | |||
dyn_wrk = cur->data; | |||
if (rspamd_check_worker (cfg, wrk)) { | |||
if (g_quark_from_string (wrk->name) == type) { | |||
return wrk; | |||
if (dyn_wrk->lib) { | |||
wrk = &dyn_wrk->wrk; | |||
if (rspamd_check_worker (cfg, wrk)) { | |||
if (g_quark_from_string (wrk->name) == type) { | |||
return wrk; | |||
} | |||
} | |||
} | |||
@@ -162,6 +162,20 @@ typedef struct worker_s { | |||
const gchar *rspamd_features; | |||
} worker_t; | |||
struct rspamd_dynamic_module { | |||
module_t mod; | |||
GModule *lib; | |||
const gchar *path; | |||
GQuark type; | |||
}; | |||
struct rspamd_dynamic_worker { | |||
worker_t wrk; | |||
GModule *lib; | |||
GQuark type; | |||
const gchar *path; | |||
}; | |||
/** | |||
* Check if loaded worker is compatible with rspamd | |||
* @param cfg |