]> source.dussan.org Git - rspamd.git/commitdiff
* Start new rspamd 0.3.4
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Fri, 3 Dec 2010 18:57:38 +0000 (21:57 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Fri, 3 Dec 2010 18:57:38 +0000 (21:57 +0300)
* Add ability to manage per-module, per-worker and per-classifier options in XML parser

15 files changed:
CMakeLists.txt
src/cfg_xml.c
src/cfg_xml.h
src/controller.c
src/fuzzy_storage.c
src/fuzzy_storage.h
src/logger.c
src/logger.h
src/main.c
src/main.h
src/smtp.c
src/smtp.h
src/util.c
src/util.h
src/worker.c

index cfaa95ed308f83f61ce0ffbea4a25da7b1b63a0c..7945ae059a94020fb500a2f9471ca857d1ff6d35 100644 (file)
@@ -7,7 +7,7 @@ PROJECT(rspamd C)
 
 SET(RSPAMD_VERSION_MAJOR 0)
 SET(RSPAMD_VERSION_MINOR 3)
-SET(RSPAMD_VERSION_PATCH 3)
+SET(RSPAMD_VERSION_PATCH 4)
 
 
 SET(RSPAMD_VERSION         "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}")
@@ -486,6 +486,7 @@ IF(NOT DESTDIR)
 ENDIF(NOT DESTDIR)
 
 # Try to detect tip version from hg
+UNSET(ID CACHE)
 SET(ID "unknown")
 FIND_PROGRAM(HG "hg")
 
index 67523c845bedaa6aaa23e240b582f496052235c7..ddf995481a53e7378e808e966fc1c72757090784 100644 (file)
        NULL                    \
 }                                      \
 
+#define NULL_DEF_ATTR  \
+{                                      \
+       NULL,                   \
+       0,                              \
+       NULL                    \
+}                                      \
+
 enum xml_config_section {
        XML_SECTION_MAIN,
     XML_SECTION_LOGGING, 
@@ -64,16 +71,22 @@ enum xml_config_section {
 };
 
 struct xml_config_param {
-       const gchar *name;
-       element_handler_func handler;
-       gint                            offset;
-       gpointer user_data;
+       const gchar                *name;
+       element_handler_func    handler;
+       gint                                    offset;
+       gpointer                                user_data;
+};
+
+struct xml_default_config_param {
+       element_default_handler_func    handler;
+       gint                                    offset;
+       gpointer                                user_data;
 };
 
 struct xml_parser_rule {
        enum xml_config_section section;
        struct xml_config_param params[MAX_PARAM];
-       struct xml_config_param default_param;
+       struct xml_default_config_param default_param;
 };
 
 /* Here we describes our basic grammar */
@@ -165,7 +178,7 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
        { XML_SECTION_LOGGING, {
                        {
@@ -206,7 +219,7 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
        { XML_SECTION_WORKER, {
                        {
@@ -242,7 +255,6 @@ static struct xml_parser_rule grammar[] = {
                        NULL_ATTR
                },
                {
-                       NULL,
                        worker_handle_param,
                        0,
                        NULL
@@ -287,7 +299,7 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
        { XML_SECTION_CLASSIFIER, {
                        {
@@ -302,15 +314,13 @@ static struct xml_parser_rule grammar[] = {
                                0,
                                NULL
                        },
-                       {
-                               "option",
-                               handle_classifier_opt,
-                               0,
-                               NULL
-                       },
                        NULL_ATTR
                },
-               NULL_ATTR
+               {
+                       handle_classifier_opt,
+                       0,
+                       NULL
+               }
        },
        { XML_SECTION_STATFILE, {
                        {
@@ -357,13 +367,12 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
        { XML_SECTION_MODULE, {
                        NULL_ATTR
                },
                {
-                       NULL,
                        handle_module_opt,
                        0,
                        NULL
@@ -378,7 +387,7 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
        { XML_SECTION_VIEW, {
                        {
@@ -419,10 +428,14 @@ static struct xml_parser_rule grammar[] = {
                        },
                        NULL_ATTR
                },
-               NULL_ATTR
+               NULL_DEF_ATTR
        },
 };
 
+static GHashTable *module_options = NULL,
+                                 *worker_options = NULL,
+                                 *classifier_options = NULL;
+
 GQuark
 xml_error_quark (void)
 {
@@ -510,9 +523,8 @@ call_param_handler (struct rspamd_xml_userdata *ctx, const gchar *name, gchar *v
                                param ++;
                        }
                        if (rule->default_param.handler != NULL) {
-                               param = &rule->default_param;
                                /* Call default handler */
-                               return param->handler (ctx->cfg, ctx, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
+                               return rule->default_param.handler (ctx->cfg, ctx, name, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
                        }
                }
        }
@@ -625,17 +637,32 @@ handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHas
 
 /* Worker section */
 gboolean 
-worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
 {
        struct worker_conf             *wrk = ctx->section_pointer;
-       gchar                           *name;
+       const gchar                    *name;
+       struct xml_config_param        *cparam;
+       GHashTable                     *worker_config;
 
-       if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
-               msg_err ("worker param tag must have \"name\" attribute");
-               return FALSE;
+       if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0)  {
+               if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+                       msg_err ("worker param tag must have \"name\" attribute");
+                       return FALSE;
+               }
+       }
+       else {
+               name = tag;
        }
 
-       g_hash_table_insert (wrk->params, name, memory_pool_strdup (cfg->cfg_pool, data));
+       if (!worker_options ||
+                       (worker_config = g_hash_table_lookup (worker_options, &wrk->type)) == NULL ||
+                       (cparam = g_hash_table_lookup (worker_config, name)) == NULL) {
+               msg_warn ("unregistered worker attribute '%s' for worker %s", name, process_to_str (wrk->type));
+               g_hash_table_insert (wrk->params, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
+       }
+       else {
+               return cparam->handler (cfg, ctx, attrs, data, NULL, cparam->user_data, cparam->offset);
+       }
 
        return TRUE;
 }
@@ -765,27 +792,36 @@ handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
 
 /* Modules section */
 gboolean 
-handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
 {
-       gchar                           *name, *val;
+       gchar                          *val;
        struct module_opt              *cur;
        gboolean                        is_lua = FALSE;
-       
-       if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
-               msg_err ("param tag must have \"name\" attribute");
-               return FALSE;
+       const gchar                    *name;
+
+       if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+               if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+                       msg_err ("worker param tag must have \"name\" attribute");
+                       return FALSE;
+               }
        }
-       
+       else {
+               name = tag;
+       }
+
        /* Check for lua */
        if ((val = g_hash_table_lookup (attrs, "lua")) != NULL) {
                if (g_ascii_strcasecmp (val, "yes") == 0) {
                        is_lua = TRUE;
                }
        }
+       /* XXX: in fact we cannot check for lua modules and need to do it in post-config procedure
+        * so just insert any options provided and try to handle them in further process
+        */
 
        /* Insert option */
        cur = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct module_opt));
-       cur->param = name;
+       cur->param = (char *)name;
        cur->value = data;
        cur->is_lua = is_lua;
        ctx->section_pointer = g_list_prepend (ctx->section_pointer, cur);
@@ -1048,17 +1084,33 @@ handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata
 }
 
 gboolean 
-handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
 {
-       struct classifier_config     *ccf = ctx->section_pointer;
-       gchar                        *val;
-       
-       if ((val = g_hash_table_lookup (attrs, "name")) == NULL) {
-               msg_err ("'name' attribute is required for tag 'option'");
-               return FALSE;
+       struct classifier_config       *ccf = ctx->section_pointer;
+       const gchar                    *name;
+       struct xml_config_param        *cparam;
+       GHashTable                     *classifier_config;
+
+       if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+               if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+                       msg_err ("worker param tag must have \"name\" attribute");
+                       return FALSE;
+               }
+       }
+       else {
+               name = tag;
+       }
+
+       if (!classifier_options ||
+                       (classifier_config = g_hash_table_lookup (classifier_options, ccf->classifier->name)) == NULL ||
+                       (cparam = g_hash_table_lookup (classifier_config, name)) == NULL) {
+               msg_warn ("unregistered classifier attribute '%s' for classifier %s", name, ccf->classifier->name);
+               g_hash_table_insert (ccf->opts, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
+       }
+       else {
+               return cparam->handler (cfg, ctx, attrs, data, NULL, cparam->user_data, cparam->offset);
        }
 
-       g_hash_table_insert (ccf->opts, val, memory_pool_strdup (cfg->cfg_pool, data));
        return TRUE;
 }
 
@@ -1633,6 +1685,118 @@ rspamd_xml_error (GMarkupParseContext *context, GError *error, gpointer user_dat
        msg_err ("xml parser error: %s, at state \"%s\"", error->message, xml_state_to_string (ud));
 }
 
+/* Register handlers for specific parts of config */
+/* Register new module option */
+void
+register_module_opt (const gchar *mname, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+       struct xml_config_param          *param;
+       GHashTable                       *module;
+
+       if (module_options == NULL) {
+               module_options = g_hash_table_new (g_str_hash, g_str_equal);
+       }
+       if ((module = g_hash_table_lookup (module_options, mname)) == NULL) {
+               module = g_hash_table_new (g_str_hash, g_str_equal);
+               g_hash_table_insert (module_options, (char *)mname, module);
+       }
+       if ((param = g_hash_table_lookup (module, optname)) == NULL) {
+               /* Register new param */
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (module, (char *)optname, param);
+       }
+       else {
+               /* Param already exists replace it */
+               msg_warn ("replace old handler for param '%s'", optname);
+               g_free (param);
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (module, (char *)optname, param);
+       }
+}
+
+/* Register new worker's options */
+void
+register_worker_opt (gint wtype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+       struct xml_config_param          *param;
+       GHashTable                       *worker;
+       gint                             *new_key;
+
+       if (worker_options == NULL) {
+               worker_options = g_hash_table_new (g_int_hash, g_int_equal);
+       }
+       if ((worker = g_hash_table_lookup (worker_options, &wtype)) == NULL) {
+               worker = g_hash_table_new (g_str_hash, g_str_equal);
+               new_key = g_malloc (sizeof (gint));
+               *new_key = wtype;
+               g_hash_table_insert (worker_options, new_key, worker);
+       }
+       if ((param = g_hash_table_lookup (worker, optname)) == NULL) {
+               /* Register new param */
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (worker, (char *)optname, param);
+       }
+       else {
+               /* Param already exists replace it */
+               msg_warn ("replace old handler for param '%s'", optname);
+               g_free (param);
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (worker, (char *)optname, param);
+       }
+}
+
+/* Register new classifier option */
+void
+register_classifier_opt (const gchar *ctype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset)
+{
+       struct xml_config_param          *param;
+       GHashTable                       *classifier;
+
+       if (classifier_options == NULL) {
+               classifier_options = g_hash_table_new (g_str_hash, g_str_equal);
+       }
+       if ((classifier = g_hash_table_lookup (classifier_options, ctype)) == NULL) {
+               classifier = g_hash_table_new (g_str_hash, g_str_equal);
+               g_hash_table_insert (classifier_options, (char *)ctype, classifier);
+       }
+       if ((param = g_hash_table_lookup (classifier, optname)) == NULL) {
+               /* Register new param */
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (classifier, (char *)optname, param);
+       }
+       else {
+               /* Param already exists replace it */
+               msg_warn ("replace old handler for param '%s'", optname);
+               g_free (param);
+               param = g_malloc (sizeof (struct xml_config_param));
+               param->handler = func;
+               param->user_data = dest_struct;
+               param->offset = offset;
+               param->name = optname;
+               g_hash_table_insert (classifier, (char *)optname, param);
+       }
+}
+
 
 /* Dumper part */
 
index 456d37fa8e0349e1340d57008416714f86b3bd6e..dc55d2c862947889b62263a48ca864733bf2002e 100644 (file)
@@ -39,6 +39,7 @@ struct rspamd_xml_userdata {
 
 /* Text is NULL terminated here */
 typedef gboolean (*element_handler_func) (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+typedef gboolean (*element_default_handler_func) (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
 /* Callbacks */
 
@@ -88,42 +89,62 @@ gboolean xml_handle_uint16 (struct config_file *cfg, struct rspamd_xml_userdata
 gboolean xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
 /* Specific params */
-gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle workers param */
+gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle metric symbol */
 gboolean handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
-gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+/* Handle common module option */
+gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle loging params */
 gboolean handle_log_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle lua include */
 gboolean handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle path to modules */
 gboolean handle_module_path (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle variables and composites */
 gboolean handle_variable (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle views */
 gboolean handle_view_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_view_client_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_view_from (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_view_rcpt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle settings */
 gboolean handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_domain_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle classifier */
 gboolean handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
-gboolean handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+gboolean handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Handle statfile */
 gboolean handle_statfile_normalizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_statfile_binlog (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_statfile_binlog_rotate (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 gboolean handle_statfile_binlog_master (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
+/* Register new module option */
+void register_module_opt (const gchar *mname, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
+/* Register new worker's options */
+void register_worker_opt (gint wtype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
+/* Register new classifier option */
+void register_classifier_opt (const gchar *ctype, const gchar *optname, element_handler_func func, gpointer dest_struct, gint offset);
+
 /* Dumper functions */
 gboolean xml_dump_config (struct config_file *cfg, const gchar *filename);
 
index 42c0340131f75b29ad69b9e0aa5a4afd38ca85f9..617821bf6af2027a974ec637293738150dbdb256 100644 (file)
@@ -29,6 +29,7 @@
 #include "protocol.h"
 #include "upstream.h"
 #include "cfg_file.h"
+#include "cfg_xml.h"
 #include "modules.h"
 #include "tokenizers/tokenizers.h"
 #include "classifiers/classifiers.h"
@@ -67,6 +68,11 @@ struct custom_controller_command {
        controller_func_t               handler;
 };
 
+struct rspamd_controller_ctx {
+       char                                               *password;
+       guint32                                                 timeout;
+};
+
 static struct controller_command commands[] = {
        {"password", FALSE, COMMAND_PASSWORD},
        {"quit", FALSE, COMMAND_QUIT},
@@ -421,9 +427,9 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
        gchar                           out_buf[BUFSIZ], *arg, *err_str;
        gint                            r = 0, days, hours, minutes;
        time_t                          uptime;
-       guint32                   size = 0;
+       guint32                                 size = 0;
        struct classifier_config       *cl;
-       gchar                           *password = g_hash_table_lookup (session->worker->cf->params, "password");
+       struct rspamd_controller_ctx   *ctx = session->worker->ctx;
 
        switch (cmd->type) {
        case COMMAND_PASSWORD:
@@ -436,14 +442,14 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                        }
                        return TRUE;
                }
-               if (password == NULL) {
+               if (ctx->password == NULL) {
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "password command disabled in config, authorized access unallowed" CRLF);
                        if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
                                return FALSE;
                        }
                        return TRUE;
                }
-               if (strncmp (arg, password, strlen (arg)) == 0) {
+               if (strncmp (arg, ctx->password, strlen (arg)) == 0) {
                        session->authorized = 1;
                        r = rspamd_snprintf (out_buf, sizeof (out_buf), "password accepted" CRLF);
                        if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
@@ -1023,6 +1029,9 @@ accept_socket (gint fd, short what, void *arg)
        struct timeval                 *io_tv;
        socklen_t                       addrlen = sizeof (ss);
        gint                            nfd;
+       struct rspamd_controller_ctx   *ctx;
+
+       ctx = worker->ctx;
 
        if ((nfd = accept_from_socket (fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
                msg_warn ("accept failed: %s", strerror (errno));
@@ -1044,8 +1053,8 @@ accept_socket (gint fd, short what, void *arg)
 
        /* Set up dispatcher */
        io_tv = memory_pool_alloc (new_session->session_pool, sizeof (struct timeval));
-       io_tv->tv_sec = CONTROLLER_IO_TIMEOUT;
-       io_tv->tv_usec = 0;
+       io_tv->tv_sec = ctx->timeout / 1000;
+       io_tv->tv_usec = ctx->timeout - io_tv->tv_sec * 1000;
 
        new_session->s = new_async_session (new_session->session_pool, free_session, new_session);
 
@@ -1055,6 +1064,21 @@ accept_socket (gint fd, short what, void *arg)
        }
 }
 
+gpointer
+init_controller (void)
+{
+       struct rspamd_controller_ctx       *ctx;
+
+       ctx = g_malloc0 (sizeof (struct rspamd_controller_ctx));
+
+       ctx->timeout = CONTROLLER_IO_TIMEOUT * 1000;
+
+       register_worker_opt (TYPE_CONTROLLER, "password", xml_handle_string, ctx, G_STRUCT_OFFSET (struct rspamd_controller_ctx, password));
+       register_worker_opt (TYPE_CONTROLLER, "timeout", xml_handle_seconds, ctx, G_STRUCT_OFFSET (struct rspamd_controller_ctx, timeout));
+
+       return ctx;
+}
+
 void
 start_controller (struct rspamd_worker *worker)
 {
index dc18a694d073d68f80723a2af6c6ce4ac746b7b0..f8d4a855adac4b3c670ed421531ff28c90ea166b 100644 (file)
@@ -32,6 +32,7 @@
 #include "protocol.h"
 #include "upstream.h"
 #include "cfg_file.h"
+#include "cfg_xml.h"
 #include "url.h"
 #include "modules.h"
 #include "message.h"
@@ -66,20 +67,24 @@ static GQueue                  *hashes[BUCKETS];
 static GQueue                  *frequent;
 #ifdef WITH_JUDY
 static gpointer                 jtree;
-static gboolean                 use_judy = FALSE;
 #endif
 static bloom_filter_t          *bf;
 
 /* Number of cache modifications */
 static guint32                 mods = 0;
-static guint32                 max_mods = DEFAULT_MOD_LIMIT;
-/* Frequent score number */
-static guint32                 frequent_score = DEFAULT_FREQUENT_SCORE;
 /* For evtimer */
 static struct timeval           tmv;
 static struct event             tev;
 static struct rspamd_stat      *server_stat;
 
+struct rspamd_fuzzy_storage_ctx {
+       gboolean                        use_judy;
+       char                           *hashfile;
+       guint32                         expire;
+       guint32                         frequent_score;
+       guint32                         max_mods;
+};
+
 struct rspamd_fuzzy_node {
        gint32                          value;
        gint32                          flag;
@@ -120,32 +125,27 @@ static void
 sync_cache (struct rspamd_worker *wrk)
 {
        gint                            fd, i;
-       gchar                           *filename, *exp_str, header[4];
+       gchar                           *filename, header[4];
        GList                          *cur, *tmp;
        struct rspamd_fuzzy_node       *node;
        guint64                         expire, now;
+       struct rspamd_fuzzy_storage_ctx *ctx = wrk->ctx;
 #ifdef WITH_JUDY
        PPvoid_t                        pvalue;
        gchar                           indexbuf[1024], tmpindex[1024];
 #endif
 
        /* Check for modifications */
-       if (mods < max_mods) {
+       if (mods < ctx->max_mods) {
                return;
        }
 
        msg_info ("syncing fuzzy hash storage");
-       filename = g_hash_table_lookup (wrk->cf->params, "hashfile");
+       filename = ctx->hashfile;
        if (filename == NULL) {
                return;
        }
-       exp_str = g_hash_table_lookup (wrk->cf->params, "expire");
-       if (exp_str != NULL) {
-               expire = parse_seconds (exp_str) / 1000;
-       }
-       else {
-               expire = DEFAULT_EXPIRE;
-       }
+       expire = ctx->expire;
        
        if ((fd = open (filename, O_WRONLY | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
                msg_err ("cannot create hash file %s: %s", filename, strerror (errno));
@@ -165,7 +165,7 @@ sync_cache (struct rspamd_worker *wrk)
        }
 
 #ifdef WITH_JUDY
-       if (use_judy) {
+       if (ctx->use_judy) {
                indexbuf[0] = '\0';
                pvalue = JudySLFirst (jtree, indexbuf, PJE0);
                while (pvalue) {
@@ -234,12 +234,14 @@ static void
 sigterm_handler (gint fd, short what, void *arg)
 {
        struct rspamd_worker           *worker = (struct rspamd_worker *)arg;
+       struct rspamd_fuzzy_storage_ctx *ctx;
        static struct timeval           tv = {
                .tv_sec = 0,
                .tv_usec = 0
        };
 
-       mods = max_mods + 1;
+       ctx = worker->ctx;
+       mods = ctx->max_mods + 1;
        sync_cache (worker);
        close (worker->cf->listen_sock);
        (void)event_loopexit (&tv);
@@ -254,7 +256,9 @@ sigusr_handler (gint fd, short what, void *arg)
        struct rspamd_worker           *worker = (struct rspamd_worker *)arg;
        /* Do not accept new connections, preparing to end worker's process */
        struct timeval                  tv;
+       struct rspamd_fuzzy_storage_ctx *ctx;
 
+       ctx = worker->ctx;
        tv.tv_sec = SOFT_SHUTDOWN_TIME;
        tv.tv_usec = 0;
        event_del (&worker->sig_ev);
@@ -263,7 +267,7 @@ sigusr_handler (gint fd, short what, void *arg)
        do_reopen_log = 1;
        msg_info ("worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME);
        event_loopexit (&tv);
-       mods = max_mods + 1;
+       mods = ctx->max_mods + 1;
        sync_cache (worker);
        return;
 }
@@ -276,6 +280,7 @@ read_hashes_file (struct rspamd_worker *wrk)
        gchar                           *filename, header[4];
        gboolean                        touch_stat = TRUE;
        struct rspamd_fuzzy_node       *node;
+       struct rspamd_fuzzy_storage_ctx *ctx = wrk->ctx;
        struct {
                gint32                          value;
                guint64                         time;
@@ -288,7 +293,7 @@ read_hashes_file (struct rspamd_worker *wrk)
                touch_stat = FALSE;
        }
 
-       if (use_judy) {
+       if (ctx->use_judy) {
                jtree = NULL;
        }
        else {
@@ -301,7 +306,7 @@ read_hashes_file (struct rspamd_worker *wrk)
        }
 #endif
 
-       filename = g_hash_table_lookup (wrk->cf->params, "hashfile");
+       filename = ctx->hashfile;
        if (filename == NULL) {
                return FALSE;
        }
@@ -354,13 +359,13 @@ read_hashes_file (struct rspamd_worker *wrk)
                        }
                }
 #ifdef WITH_JUDY
-               if (use_judy) {
+               if (ctx->use_judy) {
                        pvalue = JudySLIns (&jtree, node->h.hash_pipe, PJE0);
                        *pvalue = node;
                }
                else {
 #endif
-               if (node->value > frequent_score) {
+               if (node->value > ctx->frequent_score) {
                        g_queue_push_head (frequent, node);
                }
                else {
@@ -376,7 +381,7 @@ read_hashes_file (struct rspamd_worker *wrk)
        }
 
 #ifdef WITH_JUDY
-       if (!use_judy) {
+       if (!ctx->use_judy) {
 #endif
        /* Sort everything */
        g_queue_sort (frequent, compare_nodes, NULL);
@@ -402,7 +407,7 @@ read_hashes_file (struct rspamd_worker *wrk)
 }
 
 static inline struct rspamd_fuzzy_node *
-check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
+check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        GList                          *cur;
        struct rspamd_fuzzy_node       *h;
@@ -410,7 +415,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
 #ifdef WITH_JUDY
        PPvoid_t                         pvalue;
 
-       if (use_judy) {
+       if (ctx->use_judy) {
                pvalue = JudySLGet (jtree, s->hash_pipe, PJE0);
                if (pvalue != NULL) {
                        h = *((struct rspamd_fuzzy_node **)pvalue);
@@ -449,7 +454,7 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
                                h->value += update_value;
                                msg_info ("new hash weight: %d", h->value);
                        }
-                       if (h->value > frequent_score) {
+                       if (h->value > ctx->frequent_score) {
                                g_queue_unlink (hash, cur);
                                g_queue_push_head_link (frequent, cur);
                                msg_info ("moved hash to frequent list");
@@ -466,11 +471,12 @@ check_hash_node (GQueue *hash, fuzzy_hash_t *s, gint update_value)
 }
 
 static                          gint
-process_check_command (struct fuzzy_cmd *cmd, gint *flag)
+process_check_command (struct fuzzy_cmd *cmd, gint *flag, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        fuzzy_hash_t                    s;
        struct rspamd_fuzzy_node       *h;
 
+
        if (!bloom_check (bf, cmd->hash)) {
                return 0;
        }
@@ -478,7 +484,7 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag)
        memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
        s.block_size = cmd->blocksize;
 
-       h = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0);
+       h = check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, 0, ctx);
 
        if (h == NULL) {
                return 0;
@@ -490,7 +496,7 @@ process_check_command (struct fuzzy_cmd *cmd, gint *flag)
 }
 
 static                          gboolean
-update_hash (struct fuzzy_cmd *cmd)
+update_hash (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        fuzzy_hash_t                    s;
 
@@ -498,11 +504,11 @@ update_hash (struct fuzzy_cmd *cmd)
        s.block_size = cmd->blocksize;
        mods ++;
 
-       return check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, cmd->value) != NULL;
+       return check_hash_node (hashes[cmd->blocksize % BUCKETS], &s, cmd->value, ctx) != NULL;
 }
 
 static                          gboolean
-process_write_command (struct fuzzy_cmd *cmd)
+process_write_command (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        struct rspamd_fuzzy_node       *h;
 #ifdef WITH_JUDY
@@ -510,7 +516,7 @@ process_write_command (struct fuzzy_cmd *cmd)
 #endif
 
        if (bloom_check (bf, cmd->hash)) {
-               if (update_hash (cmd)) {
+               if (update_hash (cmd, ctx)) {
                        return TRUE;
                }
        }
@@ -522,7 +528,7 @@ process_write_command (struct fuzzy_cmd *cmd)
        h->value = cmd->value;
        h->flag = cmd->flag;
 #ifdef WITH_JUDY
-       if (use_judy) {
+       if (ctx->use_judy) {
                pvalue = JudySLIns (&jtree, h->h.hash_pipe, PJE0);
                *pvalue = h;
        }
@@ -542,7 +548,7 @@ process_write_command (struct fuzzy_cmd *cmd)
 }
 
 static gboolean
-delete_hash (GQueue *hash, fuzzy_hash_t *s)
+delete_hash (GQueue *hash, fuzzy_hash_t *s, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        GList                          *cur, *tmp;
        struct rspamd_fuzzy_node       *h;
@@ -551,7 +557,7 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s)
        PPvoid_t                        pvalue;
        gpointer                        data;
 
-       if (use_judy) {
+       if (ctx->use_judy) {
                pvalue = JudySLGet (jtree, s->hash_pipe, PJE0);
                if (pvalue) {
                        data = *pvalue;
@@ -593,7 +599,7 @@ delete_hash (GQueue *hash, fuzzy_hash_t *s)
 }
 
 static                          gboolean
-process_delete_command (struct fuzzy_cmd *cmd)
+process_delete_command (struct fuzzy_cmd *cmd, struct rspamd_fuzzy_storage_ctx *ctx)
 {
        fuzzy_hash_t                    s;
        gboolean                        res = FALSE;
@@ -605,17 +611,17 @@ process_delete_command (struct fuzzy_cmd *cmd)
        memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
        s.block_size = cmd->blocksize;
 #ifdef WITH_JUDY
-       if (use_judy) {
-               return delete_hash (NULL, &s);
+       if (ctx->use_judy) {
+               return delete_hash (NULL, &s, ctx);
        }
        else {
 #endif
-       res = delete_hash (frequent, &s);
+       res = delete_hash (frequent, &s, ctx);
        if (!res) {
-               res = delete_hash (hashes[cmd->blocksize % BUCKETS], &s);
+               res = delete_hash (hashes[cmd->blocksize % BUCKETS], &s, ctx);
        }
        else {
-               (void)delete_hash (hashes[cmd->blocksize % BUCKETS], &s);
+               (void)delete_hash (hashes[cmd->blocksize % BUCKETS], &s, ctx);
        }
 #ifdef WITH_JUDY
        }
@@ -626,7 +632,7 @@ process_delete_command (struct fuzzy_cmd *cmd)
 
 #define CMD_PROCESS(x)                                                                                                                                                 \
 do {                                                                                                                                                                                   \
-if (process_##x##_command (&session->cmd)) {                                                                                                   \
+if (process_##x##_command (&session->cmd, session->worker->ctx)) {                                                                                                     \
        if (sendto (session->fd, "OK" CRLF, sizeof ("OK" CRLF) - 1, 0, (struct sockaddr *)&session->sa, session->salen) == -1) {                                                        \
                msg_err ("error while writing reply: %s", strerror (errno));            \
        }                                                                                                                                                                                       \
@@ -646,7 +652,7 @@ process_fuzzy_command (struct fuzzy_session *session)
 
        switch (session->cmd.cmd) {
        case FUZZY_CHECK:
-               r = process_check_command (&session->cmd, &flag);
+               r = process_check_command (&session->cmd, &flag, session->worker->ctx);
                if (r != 0) {
                        r = rspamd_snprintf (buf, sizeof (buf), "OK %d %d" CRLF, r, flag);
                        if (sendto (session->fd, buf, r, 0, (struct sockaddr *)&session->sa, session->salen) == -1) {
@@ -687,8 +693,8 @@ accept_fuzzy_socket (gint fd, short what, void *arg)
        ssize_t                         r;
        struct {
                u_char                      cmd;
-               guint32                         blocksize;
-               gint32                          value;
+               guint32                     blocksize;
+               gint32                      value;
                u_char                      hash[FUZZY_HASHLEN];
        }                                                               legacy_cmd;
 
@@ -739,6 +745,28 @@ sync_callback (gint fd, short what, void *arg)
        sync_cache (worker);
 }
 
+gpointer
+init_fuzzy_storage (void)
+{
+       struct rspamd_fuzzy_storage_ctx       *ctx;
+
+       ctx = g_malloc0 (sizeof (struct rspamd_fuzzy_storage_ctx));
+
+       ctx->max_mods = DEFAULT_MOD_LIMIT;
+       ctx->frequent_score = DEFAULT_FREQUENT_SCORE;
+
+       register_worker_opt (TYPE_FUZZY, "hashfile", xml_handle_string, ctx,
+                       G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, hashfile));
+       register_worker_opt (TYPE_FUZZY, "max_mods", xml_handle_uint32, ctx,
+                       G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, max_mods));
+       register_worker_opt (TYPE_FUZZY, "frequent_score", xml_handle_uint32, ctx,
+                               G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, frequent_score));
+       register_worker_opt (TYPE_FUZZY, "use_judy", xml_handle_boolean, ctx,
+                               G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, use_judy));
+
+       return ctx;
+}
+
 /*
  * Start worker process
  */
@@ -748,7 +776,6 @@ start_fuzzy_storage (struct rspamd_worker *worker)
        struct sigaction                signals;
        struct event                    sev;
        gint                            retries = 0;
-       gchar                           *value;
 
        worker->srv->pid = getpid ();
        worker->srv->type = TYPE_FUZZY;
@@ -765,20 +792,6 @@ start_fuzzy_storage (struct rspamd_worker *worker)
        signal_add (&worker->sig_ev, NULL);
        signal_set (&sev, SIGTERM, sigterm_handler, (void *)worker);
        signal_add (&sev, NULL);
-       /* Get params */
-       if ((value = g_hash_table_lookup (worker->cf->params, "frequent_score")) != NULL) {
-               frequent_score = strtol (value, NULL, 10);
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "max_mods")) != NULL) {
-               max_mods = strtol (value, NULL, 10);
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "use_judy")) != NULL) {
-#ifdef WITH_JUDY
-               use_judy = TRUE;
-#else
-               msg_err ("cannot use judy storage as judy support is not compiled in");
-#endif
-       }
 
        /* Listen event */
        while ((worker->cf->listen_sock = make_udp_socket (&worker->cf->bind_addr, worker->cf->bind_port, TRUE, TRUE)) == -1) {
@@ -802,13 +815,11 @@ start_fuzzy_storage (struct rspamd_worker *worker)
        tmv.tv_usec = 0;
        evtimer_add (&tev, &tmv);
 
-
        event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker);
        event_add (&worker->bind_ev, NULL);
 
        gperf_profiler_init (worker->srv->cfg, "fuzzy");
 
-
        event_loop (0);
        exit (EXIT_SUCCESS);
 }
index 5a02d48712cade19a3a999ff7e01956505b6c1b6..f5196b1d60f6fb2d6e52e2e0ffc7bd83e0516f63 100644 (file)
@@ -27,6 +27,7 @@ struct fuzzy_session {
        struct sockaddr_storage sa;
 };
 
+gpointer init_fuzzy_storage (void);
 void start_fuzzy_storage (struct rspamd_worker *worker);
 
 #endif
index eda67f1617461a3edc2c0a3da200bb294fc4b0cf..85bd2fc90575827332e08e57d8d212fd9ab84822 100644 (file)
@@ -542,29 +542,8 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla
                tms = localtime (&now);
 
                strftime (timebuf, sizeof (timebuf), "%F %H:%M:%S", tms);
-               switch (rspamd_log->process_type) {
-                       case TYPE_MAIN:
-                               cptype = "main";
-                               break;
-                       case TYPE_WORKER:
-                               cptype = "worker";
-                               break;
-                       case TYPE_CONTROLLER:
-                               cptype = "controller";
-                               break;
-                       case TYPE_LMTP:
-                               cptype = "lmtp";
-                               break;
-                       case TYPE_SMTP:
-                               cptype = "smtp";
-                               break;
-                       case TYPE_FUZZY:
-                               cptype = "fuzzy";
-                               break;
-                       case TYPE_GREYLIST:
-                               cptype = "greylist";
-                               break;
-               }
+               cptype = process_to_str (rspamd_log->process_type);
+
                if (function == NULL) {
                        r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%s #%P(%s) ", timebuf, rspamd_log->pid, cptype);
                }
index f2adf65c695a33fc0ec982f1844f20a40f5fbe38..7a3fade7ccef03c87c341dce2743fd82f1e8e273 100644 (file)
@@ -6,18 +6,6 @@
 #include "radix.h"
 #include "util.h"
 
-/** 
- * Process type: main or worker
- */
-enum process_type {
-       TYPE_MAIN,
-       TYPE_WORKER,
-       TYPE_CONTROLLER,
-       TYPE_LMTP,
-       TYPE_SMTP,
-       TYPE_FUZZY,
-       TYPE_GREYLIST
-};
 
 typedef void (*rspamd_log_func_t)(const gchar * log_domain, const gchar *function,
                                                                  GLogLevelFlags log_level, const gchar * message, 
index 591dd6183194f54b3bedd3f759688b5c039434c9..0fcd4e89a531ee6dd7b02392be3ec0d539820591 100644 (file)
@@ -339,6 +339,7 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
                cur->type = cf->type;
                cur->pid = fork ();
                cur->cf = g_malloc (sizeof (struct worker_conf));
+               cur->ctx = rspamd->workers_ctx[cf->type];
                memcpy (cur->cf, cf, sizeof (struct worker_conf));
                cur->pending = FALSE;
                switch (cur->pid) {
@@ -564,29 +565,6 @@ spawn_workers (struct rspamd_main *rspamd)
        }
 }
 
-static const gchar              *
-get_process_type (enum process_type type)
-{
-       switch (type) {
-       case TYPE_MAIN:
-               return "main";
-       case TYPE_WORKER:
-               return "worker";
-       case TYPE_FUZZY:
-               return "fuzzy";
-       case TYPE_GREYLIST:
-               return "greylist";
-       case TYPE_CONTROLLER:
-               return "controller";
-       case TYPE_LMTP:
-               return "lmtp";
-       case TYPE_SMTP:
-               return "smtp";
-       }
-
-       return NULL;
-}
-
 static void
 kill_old_workers (gpointer key, gpointer value, gpointer unused)
 {
@@ -604,7 +582,7 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused)
 
        waitpid (w->pid, &res, 0);
 
-       msg_debug ("%s process %P terminated", get_process_type (w->type), w->pid);
+       msg_debug ("%s process %P terminated", process_to_str (w->type), w->pid);
        g_free (w->cf);
        g_free (w);
 
@@ -755,6 +733,15 @@ print_symbols_cache (struct config_file *cfg)
        }
 }
 
+static void
+init_workers_ctx (struct rspamd_main *main)
+{
+       main->workers_ctx[TYPE_WORKER] = init_worker ();
+       main->workers_ctx[TYPE_CONTROLLER] = init_controller ();
+       main->workers_ctx[TYPE_FUZZY] = init_fuzzy_storage ();
+       main->workers_ctx[TYPE_SMTP] = init_smtp_worker ();
+}
+
 gint
 main (gint argc, gchar **argv, gchar **env)
 {
@@ -829,6 +816,9 @@ main (gint argc, gchar **argv, gchar **env)
        /* Init listen sockets hash */
        listen_sockets = g_hash_table_new (g_direct_hash, g_direct_equal);
        
+       /* Init contextes */
+       init_workers_ctx (rspamd);
+
        if (! load_rspamd_config (rspamd->cfg, TRUE)) {
                exit (EXIT_FAILURE);
        }
@@ -958,14 +948,14 @@ main (gint argc, gchar **argv, gchar **env)
 
                                if (WIFEXITED (res) && WEXITSTATUS (res) == 0) {
                                        /* Normal worker termination, do not fork one more */
-                                       msg_info ("%s process %P terminated normally", get_process_type (cur->type), cur->pid);
+                                       msg_info ("%s process %P terminated normally", process_to_str (cur->type), cur->pid);
                                }
                                else {
                                        if (WIFSIGNALED (res)) {
-                                               msg_warn ("%s process %P terminated abnormally by signal: %d", get_process_type (cur->type), cur->pid, WTERMSIG (res));
+                                               msg_warn ("%s process %P terminated abnormally by signal: %d", process_to_str (cur->type), cur->pid, WTERMSIG (res));
                                        }
                                        else {
-                                               msg_warn ("%s process %P terminated abnormally", get_process_type (cur->type), cur->pid);
+                                               msg_warn ("%s process %P terminated abnormally", process_to_str (cur->type), cur->pid);
                                        }
                                        /* Fork another worker in replace of dead one */
                                        delay_fork (cur->cf);
index a482cb1b1ab49848b00fd0f9b6a7d5ca42ed8b33..b934ae31e401ffdd411b9d1e97f92708c7119d7f 100644 (file)
@@ -41,8 +41,6 @@
 #define CR '\r'
 #define LF '\n'
 
-
-
 /** 
  * Worker process structure 
  */
@@ -91,9 +89,11 @@ struct rspamd_main {
        /* Pid file structure */
        struct pidfh *pfh;                                                                                      /**< struct pidfh for pidfile                                           */
        enum process_type type;                                                                         /**< process type                                                                       */
-       guint ev_initialized;                                                           /**< is event system is initialized                                     */
+       guint ev_initialized;                                                                           /**< is event system is initialized                                     */
        struct rspamd_stat *stat;                                                                       /**< pointer to statistics                                                      */
 
+       gpointer workers_ctx[TYPE_MAX];                                                         /** Array of workers' contexts                                          */
+
        memory_pool_t *server_pool;                                                                     /**< server's memory pool                                                       */
        statfile_pool_t *statfile_pool;                                                         /**< shared statfiles pool                                                      */
     GHashTable *workers;                                        /**< workers pool indexed by pid                    */
@@ -245,8 +245,12 @@ struct c_module {
        struct module_ctx *ctx;                                                                         /**< pointer to context                                                         */
 };
 
+/* Workers' initialization and start functions */
+gpointer init_worker (void);
 void start_worker (struct rspamd_worker *worker);
+gpointer init_controller (void);
 void start_controller (struct rspamd_worker *worker);
+gpointer init_greylist (void);
 void start_greylist_storage (struct rspamd_worker *worker);
 
 /**
index a76858547b2d444aa8ba176fb299bb8e9e3bb0f8..d1bef023ad5d303e0d1cb090116e48623de08104 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "main.h"
 #include "cfg_file.h"
+#include "cfg_xml.h"
 #include "util.h"
 #include "smtp.h"
 #include "smtp_proto.h"
@@ -895,25 +896,59 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line)
        g_strfreev (strv);
 }
 
-
-static gboolean
-config_smtp_worker (struct rspamd_worker *worker)
+gpointer
+init_smtp_worker (void)
 {
        struct smtp_worker_ctx         *ctx;
-       gchar                           *value;
-       guint32                         timeout;
 
        ctx = g_malloc0 (sizeof (struct smtp_worker_ctx));
        ctx->pool = memory_pool_new (memory_pool_get_size ());
        
        /* Set default values */
-       ctx->smtp_timeout.tv_sec = 300;
-       ctx->smtp_timeout.tv_usec = 0;
+       ctx->smtp_timeout_raw = 300000;
        ctx->smtp_delay = 0;
        ctx->smtp_banner = "220 ESMTP Ready." CRLF;
        bzero (ctx->smtp_filters, sizeof (GList *) * SMTP_STAGE_MAX);
+       ctx->max_errors = DEFAULT_MAX_ERRORS;
+       ctx->reject_message = DEFAULT_REJECT_MESSAGE;
+
+       register_worker_opt (TYPE_SMTP, "upstreams", xml_handle_string, ctx,
+                               G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str));
+       register_worker_opt (TYPE_SMTP, "banner", xml_handle_string, ctx,
+                                       G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str));
+       register_worker_opt (TYPE_SMTP, "timeout", xml_handle_seconds, ctx,
+                                       G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_timeout_raw));
+       register_worker_opt (TYPE_SMTP, "delay", xml_handle_seconds, ctx,
+                                       G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_delay));
+       register_worker_opt (TYPE_SMTP, "jitter", xml_handle_seconds, ctx,
+                                               G_STRUCT_OFFSET (struct smtp_worker_ctx, delay_jitter));
+       register_worker_opt (TYPE_SMTP, "capabilities", xml_handle_string, ctx,
+                                       G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str));
+       register_worker_opt (TYPE_SMTP, "xclient", xml_handle_boolean, ctx,
+                                       G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient));
+       register_worker_opt (TYPE_SMTP, "reject_message", xml_handle_string, ctx,
+                                               G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message));
+       register_worker_opt (TYPE_SMTP, "max_errors", xml_handle_uint32, ctx,
+                                               G_STRUCT_OFFSET (struct smtp_worker_ctx, max_errors));
+       register_worker_opt (TYPE_SMTP, "max_size", xml_handle_size, ctx,
+                                               G_STRUCT_OFFSET (struct smtp_worker_ctx, max_size));
+
+       return ctx;
+}
 
-       if ((value = g_hash_table_lookup (worker->cf->params, "upstreams")) != NULL) {
+/* Make post-init configuration */
+static gboolean
+config_smtp_worker (struct rspamd_worker *worker)
+{
+       struct smtp_worker_ctx         *ctx = worker->ctx;
+       gchar                          *value;
+
+       /* Init timeval */
+       ctx->smtp_timeout.tv_sec = ctx->smtp_timeout_raw / 1000;
+       ctx->smtp_timeout.tv_usec = (ctx->smtp_timeout_raw - ctx->smtp_timeout.tv_sec * 1000) * 1000;
+
+       /* Init upstreams */
+       if ((value = ctx->upstreams_str) != NULL) {
                if (!parse_upstreams_line (ctx, value)) {
                        return FALSE;
                }
@@ -922,53 +957,19 @@ config_smtp_worker (struct rspamd_worker *worker)
                msg_err ("no upstreams defined, don't know what to do");
                return FALSE;
        }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_banner")) != NULL) {
+       /* Create smtp banner */
+       if ((ctx->smtp_banner_str) != NULL) {
                parse_smtp_banner (ctx, value);
        }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_timeout")) != NULL) {
-               errno = 0;
-               timeout = parse_seconds (value);
-               ctx->smtp_timeout.tv_sec = timeout / 1000;
-               ctx->smtp_timeout.tv_usec = (timeout - ctx->smtp_timeout.tv_sec * 1000) * 1000;
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_delay")) != NULL) {
-               ctx->smtp_delay = parse_seconds (value);
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_jitter")) != NULL) {
-               ctx->delay_jitter = parse_seconds (value);
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_capabilities")) != NULL) {
+
+       /* Parse capabilities */
+       if ((value = ctx->smtp_capabilities_str) != NULL) {
                make_capabilities (ctx, value);
        }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_use_xclient")) != NULL) {
-               ctx->use_xclient = parse_flag (value);
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_metric")) != NULL) {
-               ctx->metric = memory_pool_strdup (ctx->pool, value);
-       }
-       else {
-               ctx->metric = DEFAULT_METRIC;
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_max_errors")) != NULL) {
-               ctx->max_errors = strtoul (value, NULL, 10);
-       }
-       else {
-               ctx->max_errors = DEFAULT_MAX_ERRORS;
-       }
-       if ((value = g_hash_table_lookup (worker->cf->params, "smtp_reject_message")) != NULL) {
-               ctx->reject_message = memory_pool_strdup (ctx->pool, value);
-       }
-       else {
-               ctx->reject_message = DEFAULT_REJECT_MESSAGE;
-       }
 
        ctx->resolver = dns_resolver_init (worker->srv->cfg);
-
-       /* Set ctx */
-       worker->ctx = ctx;
        
        return TRUE;
-       
 }
 
 
index 1933376c3804c6a51f6b9f027f04511fde467ced..ddb3024876d616c35fff2b5f41e2dc92af474a5c 100644 (file)
@@ -31,19 +31,23 @@ enum rspamd_smtp_stage {
 struct smtp_worker_ctx {
        struct smtp_upstream upstreams[MAX_UPSTREAM];
        size_t upstream_num;
+       gchar *upstreams_str;
        
        memory_pool_t *pool;
        gchar *smtp_banner;
+       gchar *smtp_banner_str;
        guint32 smtp_delay;
        guint32 delay_jitter;
+       guint32 smtp_timeout_raw;
        struct timeval smtp_timeout;
 
        gboolean use_xclient;
        gboolean helo_required;
        gchar *smtp_capabilities;
+       gchar *smtp_capabilities_str;
        gchar *reject_message;
-       size_t max_size;
-       guint max_errors;
+       gsize max_size;
+       guint32 max_errors;
        gchar *metric;
        GList *smtp_filters[SMTP_STAGE_MAX];
        struct rspamd_dns_resolver *resolver;
@@ -115,6 +119,7 @@ struct smtp_filter {
        gpointer filter_data;
 };
 
+gpointer init_smtp_worker (void);
 void start_smtp_worker (struct rspamd_worker *worker);
 void register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, smtp_filter_t filter, gpointer filter_data);
 
index 78be8cbaf221c1657fb15334c5cab070832e9846..a420493dc2052487ab292e55f29ba6785fc2e92d 100644 (file)
@@ -1641,6 +1641,60 @@ rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz)
        return (s - src - 1);    /* count does not include NUL */
 }
 
+/* Convert process type to its name */
+const gchar              *
+process_to_str (enum process_type type)
+{
+       switch (type) {
+       case TYPE_MAIN:
+               return "main";
+       case TYPE_WORKER:
+               return "worker";
+       case TYPE_FUZZY:
+               return "fuzzy";
+       case TYPE_GREYLIST:
+               return "greylist";
+       case TYPE_CONTROLLER:
+               return "controller";
+       case TYPE_LMTP:
+               return "lmtp";
+       case TYPE_SMTP:
+               return "smtp";
+       default:
+               return "unknown";
+       }
+
+       return NULL;
+}
+/* Convert string to process type */
+enum process_type
+str_to_process (const gchar *str)
+{
+       if (g_ascii_strcasecmp (str, "main") == 0) {
+               return TYPE_MAIN;
+       }
+       else if (g_ascii_strcasecmp (str, "worker") == 0) {
+               return TYPE_WORKER;
+       }
+       else if (g_ascii_strcasecmp (str, "fuzzy") == 0) {
+               return TYPE_FUZZY;
+       }
+       else if (g_ascii_strcasecmp (str, "greylist") == 0) {
+               return TYPE_GREYLIST;
+       }
+       else if (g_ascii_strcasecmp (str, "controller") == 0) {
+               return TYPE_CONTROLLER;
+       }
+       else if (g_ascii_strcasecmp (str, "smtp") == 0) {
+               return TYPE_SMTP;
+       }
+       else if (g_ascii_strcasecmp (str, "lmtp") == 0) {
+               return TYPE_LMTP;
+       }
+
+       return TYPE_UNKNOWN;
+}
+
 /*
  * vi:ts=4
  */
index 36d650877d96b1da32f719501b5703be798244a9..2ba01d05ee99cf795cc03ae4352036198977adb2 100644 (file)
@@ -12,6 +12,21 @@ struct workq;
 struct statfile;
 struct classifier_config;
 
+/**
+ * Process type: main or worker
+ */
+enum process_type {
+       TYPE_UNKNOWN=-1,
+       TYPE_MAIN,
+       TYPE_WORKER,
+       TYPE_CONTROLLER,
+       TYPE_LMTP,
+       TYPE_SMTP,
+       TYPE_FUZZY,
+       TYPE_GREYLIST,
+       TYPE_MAX=255
+};
+
 /* Create socket and bind or connect it to specified address and port */
 gint make_tcp_socket (struct in_addr *, u_short, gboolean is_server, gboolean async);
 /* Create socket and bind or connect it to specified address and port */
@@ -143,4 +158,19 @@ gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz);
  */
 gchar * rspamd_escape_string (gchar *dst, const gchar *src, gsize len);
 
+/*
+ * Convert process type to its name
+ *
+ * @param type numeric type
+ * @return string representation of type
+ */
+const gchar * process_to_str (enum process_type type);
+/*
+ * Convert string to process type
+ *
+ * @param type numeric type
+ * @return string representation of type
+ */
+enum process_type str_to_process (const gchar *str);
+
 #endif
index 80c7dc48c8bc2ffb42ad5ed8cd0fcc3a6a5f950d..d6112ff9de2b34b00bf36b8d8d837d310e799a58 100644 (file)
@@ -32,6 +32,7 @@
 #include "protocol.h"
 #include "upstream.h"
 #include "cfg_file.h"
+#include "cfg_xml.h"
 #include "url.h"
 #include "modules.h"
 #include "message.h"
@@ -261,54 +262,54 @@ parse_line_custom (struct worker_task *task, f_str_t * in)
 void
 free_task (struct worker_task *task, gboolean is_soft)
 {
-  GList                          *part;
-  struct mime_part               *p;
+       GList                          *part;
+       struct mime_part               *p;
 
-  if (task)
-    {
-      debug_task ("free pointer %p", task);
-      while ((part = g_list_first (task->parts)))
-       {
-         task->parts = g_list_remove_link (task->parts, part);
-         p = (struct mime_part *) part->data;
-         g_byte_array_free (p->content, TRUE);
-         g_list_free_1 (part);
-       }
-      if (task->text_parts)
-       {
-         g_list_free (task->text_parts);
-       }
-      if (task->urls)
-       {
-         g_list_free (task->urls);
-       }
-      if (task->images)
-       {
-         g_list_free (task->images);
-       }
-      if (task->messages)
+       if (task)
        {
-         g_list_free (task->messages);
-       }
-      memory_pool_delete (task->task_pool);
-      if (task->dispatcher)
-       {
-         if (is_soft)
-           {
-             /* Plan dispatcher shutdown */
-             task->dispatcher->wanna_die = 1;
-           }
-         else
-           {
-             rspamd_remove_dispatcher (task->dispatcher);
-           }
-       }
-      if (task->sock != -1)
-       {
-         close (task->sock);
+               debug_task ("free pointer %p", task);
+               while ((part = g_list_first (task->parts)))
+               {
+                       task->parts = g_list_remove_link (task->parts, part);
+                       p = (struct mime_part *) part->data;
+                       g_byte_array_free (p->content, TRUE);
+                       g_list_free_1 (part);
+               }
+               if (task->text_parts)
+               {
+                       g_list_free (task->text_parts);
+               }
+               if (task->urls)
+               {
+                       g_list_free (task->urls);
+               }
+               if (task->images)
+               {
+                       g_list_free (task->images);
+               }
+               if (task->messages)
+               {
+                       g_list_free (task->messages);
+               }
+               memory_pool_delete (task->task_pool);
+               if (task->dispatcher)
+               {
+                       if (is_soft)
+                       {
+                               /* Plan dispatcher shutdown */
+                               task->dispatcher->wanna_die = 1;
+                       }
+                       else
+                       {
+                               rspamd_remove_dispatcher (task->dispatcher);
+                       }
+               }
+               if (task->sock != -1)
+               {
+                       close (task->sock);
+               }
+               g_free (task);
        }
-      g_free (task);
-    }
 }
 
 void
@@ -733,6 +734,18 @@ unload_custom_filters (struct rspamd_worker_ctx *ctx)
 
 #endif
 
+gpointer
+init_worker (void)
+{
+       struct rspamd_worker_ctx       *ctx;
+
+       ctx = g_malloc0 (sizeof (struct rspamd_worker_ctx));
+
+       register_worker_opt (TYPE_WORKER, "mime", xml_handle_boolean, ctx, G_STRUCT_OFFSET (struct rspamd_worker_ctx, is_mime));
+
+       return ctx;
+}
+
 /*
  * Start worker process
  */
@@ -740,9 +753,8 @@ void
 start_worker (struct rspamd_worker *worker)
 {
   struct sigaction                signals;
-  gchar                          *is_mime_str;
   gchar                          *is_custom_str;
-  struct rspamd_worker_ctx       *ctx;
+  struct rspamd_worker_ctx       *ctx = worker->ctx;
 
 #ifdef WITH_PROFILER
   extern void                     _start (void), etext (void);
@@ -767,9 +779,6 @@ start_worker (struct rspamd_worker *worker)
             accept_socket, (void *) worker);
   event_add (&worker->bind_ev, NULL);
 
-  /* Fill ctx */
-  ctx = g_malloc0 (sizeof (struct rspamd_worker_ctx));
-  worker->ctx = ctx;
 
 #ifndef BUILD_STATIC
   /* Check if this worker is not usual rspamd worker, but uses custom filters from specified path */
@@ -786,18 +795,6 @@ start_worker (struct rspamd_worker *worker)
 #endif
       /* Maps events */
       start_map_watch ();
-      /* Check whether we are mime worker */
-      is_mime_str = g_hash_table_lookup (worker->cf->params, "mime");
-      if (is_mime_str != NULL
-         && (g_ascii_strcasecmp (is_mime_str, "no") == 0
-             || g_ascii_strcasecmp (is_mime_str, "false") == 0))
-       {
-         ctx->is_mime = FALSE;
-       }
-      else
-       {
-         ctx->is_mime = TRUE;
-       }
 #ifndef BUILD_STATIC
     }
 #endif