]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add neighbours option to support Rspamd cluster in WebUI
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 5 Jan 2017 17:20:13 +0000 (17:20 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 5 Jan 2017 17:20:13 +0000 (17:20 +0000)
src/controller.c
src/libserver/cfg_file.h
src/libserver/cfg_rcl.c
src/libserver/cfg_utils.c

index b780e3c4cf87690bed635c7b065007de2ea845fd..78c397c8065d60bb1456fbef249b715578951f72 100644 (file)
@@ -57,6 +57,7 @@
 #define PATH_STAT_RESET "/statreset"
 #define PATH_COUNTERS "/counters"
 #define PATH_ERRORS "/errors"
+#define PATH_NEIGHBOURS "/neighbours"
 
 #define msg_err_session(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, \
         session->pool->tag.tagname, session->pool->tag.uid, \
@@ -1403,6 +1404,31 @@ rspamd_controller_handle_errors (struct rspamd_http_connection_entry *conn_ent,
        return 0;
 }
 
+/*
+ * Neighbours command handler:
+ * request: /neighbours
+ * headers: Password
+ * reply: json {name: {url: "http://...", host: "host"}}
+ */
+static int
+rspamd_controller_handle_neighbours (struct rspamd_http_connection_entry *conn_ent,
+       struct rspamd_http_message *msg)
+{
+       struct rspamd_controller_session *session = conn_ent->ud;
+       struct rspamd_controller_worker_ctx *ctx;
+
+       ctx = session->ctx;
+
+       if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) {
+               return 0;
+       }
+
+       rspamd_controller_send_ucl (conn_ent, ctx->cfg->neighbours);
+
+       return 0;
+}
+
+
 static int
 rspamd_controller_handle_history_reset (struct rspamd_http_connection_entry *conn_ent,
                struct rspamd_http_message *msg)
@@ -3140,6 +3166,9 @@ start_controller_worker (struct rspamd_worker *worker)
        rspamd_http_router_add_path (ctx->http,
                        PATH_ERRORS,
                        rspamd_controller_handle_errors);
+       rspamd_http_router_add_path (ctx->http,
+                       PATH_NEIGHBOURS,
+                       rspamd_controller_handle_neighbours);
 
        rspamd_regexp_t *lua_re = rspamd_regexp_new ("^/.*/.*\\.lua$", NULL, NULL);
        rspamd_http_router_add_regexp (ctx->http, lua_re,
index 3be0c7c4d70ac04bbfe6a821770cea63510dc890..a6399010bcaf48e88099b1b994dab91e71bc8075 100644 (file)
@@ -425,6 +425,7 @@ struct rspamd_config {
        gchar *ssl_ciphers;                                                             /**< set of preferred ciphers                                                   */
        gchar *zstd_input_dictionary;                                   /**< path to zstd input dictionary                                              */
        gchar *zstd_output_dictionary;                                  /**< path to zstd output dictionary                                             */
+       ucl_object_t *neighbours;                                               /**< other servers in the cluster                                               */
 
        ref_entry_t ref;                                                                /**< reference counter                                                                  */
 };
index 20dc7ea606a701c4abe159b3f02ebe9afcb514db..f2d8bcd08c898c97e4ae8d61cd8fde20346d765c 100644 (file)
@@ -236,9 +236,9 @@ rspamd_rcl_options_handler (rspamd_mempool_t *pool, const ucl_object_t *obj,
        const gchar *key, gpointer ud,
        struct rspamd_rcl_section *section, GError **err)
 {
-       const ucl_object_t *dns, *upstream;
+       const ucl_object_t *dns, *upstream, *neighbours;
        struct rspamd_config *cfg = ud;
-       struct rspamd_rcl_section *dns_section, *upstream_section;
+       struct rspamd_rcl_section *dns_section, *upstream_section, *neighbours_section;
 
        HASH_FIND_STR (section->subsections, "dns", dns_section);
 
@@ -262,6 +262,20 @@ rspamd_rcl_options_handler (rspamd_mempool_t *pool, const ucl_object_t *obj,
                }
        }
 
+       HASH_FIND_STR (section->subsections, "neighbours", neighbours_section);
+
+       neighbours = ucl_object_lookup (obj, "neighbours");
+       if (neighbours_section != NULL && neighbours != NULL) {
+               const ucl_object_t *cur;
+
+               LL_FOREACH (neighbours, cur) {
+                       if (!rspamd_rcl_process_section (cfg, neighbours_section, cfg, cur,
+                                       pool, err)) {
+                               return FALSE;
+                       }
+               }
+       }
+
        if (rspamd_rcl_section_parse_defaults (cfg,
                        section, cfg->cfg_pool, obj,
                        cfg, err)) {
@@ -1489,6 +1503,82 @@ rspamd_rcl_composites_handler (rspamd_mempool_t *pool,
        return success;
 }
 
+static gboolean
+rspamd_rcl_neighbours_handler (rspamd_mempool_t *pool,
+               const ucl_object_t *obj,
+               const gchar *key,
+               gpointer ud,
+               struct rspamd_rcl_section *section,
+               GError **err)
+{
+       struct rspamd_config *cfg = ud;
+       const ucl_object_t *hostval, *pathval;
+       ucl_object_t *neigh;
+       gboolean has_port = FALSE, has_proto = FALSE;
+       GString *urlstr;
+       const gchar *p;
+
+       if (key == NULL) {
+               g_set_error (err,
+                               CFG_RCL_ERROR,
+                               EINVAL,
+                               "missing name for neighbour");
+               return FALSE;
+       }
+
+       hostval = ucl_object_lookup (obj, "host");
+
+       if (hostval == NULL || ucl_object_type (hostval) != UCL_STRING) {
+               g_set_error (err,
+                               CFG_RCL_ERROR,
+                               EINVAL,
+                               "missing host for neighbour: %s", ucl_object_key (obj));
+               return FALSE;
+       }
+
+       neigh = ucl_object_typed_new (UCL_OBJECT);
+       ucl_object_insert_key (neigh, ucl_object_ref (hostval), "host", 0, false);
+
+       if ((p = strrchr (ucl_object_tostring (hostval), ':')) != NULL) {
+               if (g_ascii_isdigit (p[1])) {
+                       has_port = TRUE;
+               }
+       }
+
+       if (strstr (ucl_object_tostring (hostval), "://") != NULL) {
+               has_proto = TRUE;
+       }
+
+       /* Now make url */
+       urlstr = g_string_sized_new (63);
+       pathval = ucl_object_lookup (obj, "path");
+
+       if (!has_proto) {
+               g_string_append_len (urlstr, "http://", sizeof ("http://") - 1);
+       }
+
+       g_string_append (urlstr, ucl_object_tostring (hostval));
+
+       if (!has_port) {
+               g_string_append (urlstr, ":11334");
+       }
+
+       if (pathval == NULL) {
+               g_string_append (urlstr, "/rspamd/");
+       }
+       else {
+               g_string_append (urlstr,  ucl_object_tostring (pathval));
+       }
+
+       ucl_object_insert_key (neigh,
+                       ucl_object_fromlstring (urlstr->str, urlstr->len),
+                       "url", 0, false);
+       g_string_free (urlstr, TRUE);
+       ucl_object_insert_key (cfg->neighbours, neigh, key, 0, true);
+
+       return TRUE;
+}
+
 
 struct rspamd_rcl_section *
 rspamd_rcl_add_section (struct rspamd_rcl_section **top,
@@ -2032,6 +2122,13 @@ rspamd_rcl_config_init (struct rspamd_config *cfg)
                        0,
                        "Use pre 1.4 style of messages in the protocol");
 
+       /* Neighbours configuration */
+       rspamd_rcl_add_section_doc (&sub->subsections, "neighbours", "name",
+                       rspamd_rcl_neighbours_handler,
+                       UCL_OBJECT, FALSE, TRUE,
+                       cfg->doc_strings,
+                       "List of members of Rspamd cluster");
+
        /* New DNS configuration */
        ssub = rspamd_rcl_add_section_doc (&sub->subsections, "dns", NULL, NULL,
                        UCL_OBJECT, FALSE, TRUE,
index 306965df8d25a6232240251a2d31f5aa1c4db532..8ee284212afdb0e6f647754bcc01446cff4b125e 100644 (file)
@@ -175,6 +175,7 @@ rspamd_config_new (void)
        cfg->max_pic_size = DEFAULT_MAX_PIC;
        cfg->images_cache_size = 256;
        cfg->monitored_ctx = rspamd_monitored_ctx_init ();
+       cfg->neighbours = ucl_object_typed_new (UCL_OBJECT);
 #ifdef WITH_HIREDIS
        cfg->redis_pool = rspamd_redis_pool_init ();
 #endif
@@ -193,6 +194,7 @@ rspamd_config_free (struct rspamd_config *cfg)
        ucl_object_unref (cfg->rcl_obj);
        ucl_object_unref (cfg->config_comments);
        ucl_object_unref (cfg->doc_strings);
+       ucl_object_unref (cfg->neighbours);
        g_hash_table_remove_all (cfg->metrics);
        g_hash_table_unref (cfg->metrics);
        g_hash_table_unref (cfg->c_modules);