commit 4d32fb1: [Project] Add preprocessed settings to the config structure

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Jun 14 19:00:04 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-06-14 13:23:15 +0100
URL: https://github.com/rspamd/rspamd/commit/4d32fb1b37d2ff46b4c6e1213a5bc163e3f2e96c

[Project] Add preprocessed settings to the config structure

---
 src/libserver/cfg_file.h        |  42 +++++++++++++++
 src/libserver/cfg_utils.c       | 112 ++++++++++++++++++++++++++++++++++++++++
 src/libserver/protocol.c        |  18 +++----
 src/libserver/rspamd_symcache.c |  12 +++--
 src/libserver/task.c            |   4 ++
 src/libserver/task.h            |   2 +-
 src/lua/lua_task.c              |   4 +-
 7 files changed, 177 insertions(+), 17 deletions(-)

diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index b5780a599..dc11d7aab 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -302,6 +302,15 @@ struct rspamd_config_post_load_script {
 
 struct rspamd_lang_detector;
 
+struct rspamd_config_settings_elt {
+	guint32 id;
+	const gchar *name;
+	ucl_object_t *symbols_enabled;
+	ucl_object_t *symbols_disabled;
+	struct rspamd_config_settings_elt *prev, *next;
+	ref_entry_t ref;
+};
+
 /**
  * Structure that stores all config data
  */
@@ -458,6 +467,7 @@ struct rspamd_config {
 	gchar *zstd_output_dictionary;					/**< path to zstd output dictionary						*/
 	ucl_object_t *neighbours;						/**< other servers in the cluster						*/
 
+	struct rspamd_config_settings_elt *setting_ids;	/**< preprocessed settings ids							*/
 	struct rspamd_lang_detector *lang_det;			/**< language detector									*/
 
 	ref_entry_t ref;								/**< reference counter									*/
@@ -715,6 +725,38 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
 		struct rspamd_radix_map_helper **target,
 		GError **err);
 
+/**
+ * Adds new settings id to be preprocessed
+ * @param cfg
+ * @param name
+ * @param symbols_enabled
+ * @param symbols_disabled
+ */
+void rspamd_config_register_settings_id (struct rspamd_config *cfg,
+										 const gchar *name,
+										 ucl_object_t *symbols_enabled,
+										 ucl_object_t *symbols_disabled);
+
+/**
+ * Finds settings id element and obtain reference count (must be unrefed by callee)
+ * @param cfg
+ * @param id
+ * @return
+ */
+struct rspamd_config_settings_elt *rspamd_config_find_settings_id_ref (
+		struct rspamd_config *cfg,
+		guint32 id);
+
+/**
+ * Finds settings id element and obtain reference count (must be unrefed by callee)
+ * @param cfg
+ * @param id
+ * @return
+ */
+struct rspamd_config_settings_elt *rspamd_config_find_settings_name_ref (
+		struct rspamd_config *cfg,
+		const gchar *name, gsize namelen);
+
 /**
  * Returns action object by name
  * @param cfg
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index 1c8b2ce5f..e32ca7020 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -2334,3 +2334,115 @@ rspamd_actions_sort (struct rspamd_config *cfg)
 {
 	HASH_SORT (cfg->actions, rspamd_actions_cmp);
 }
+
+static void
+rspamd_config_settings_elt_dtor (struct rspamd_config_settings_elt *e)
+{
+	if (e->symbols_enabled) {
+		ucl_object_unref (e->symbols_enabled);
+	}
+	if (e->symbols_disabled) {
+		ucl_object_unref (e->symbols_disabled);
+	}
+}
+
+static inline guint32
+rspamd_config_name_to_id (const gchar *name, gsize namelen)
+{
+	guint64 h;
+
+	h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
+			name, strlen (name), 0x0);
+	/* Take the lower part of hash as LE number */
+	return ((guint32)GUINT64_TO_LE (h));
+}
+
+struct rspamd_config_settings_elt *
+rspamd_config_find_settings_id_ref (struct rspamd_config *cfg,
+									guint32 id)
+{
+	struct rspamd_config_settings_elt *cur;
+
+	DL_FOREACH (cfg->setting_ids, cur) {
+		if (cur->id == id) {
+			REF_RETAIN (cur);
+			return cur;
+		}
+	}
+
+	return NULL;
+}
+
+struct rspamd_config_settings_elt *rspamd_config_find_settings_name_ref (
+		struct rspamd_config *cfg,
+		const gchar *name, gsize namelen)
+{
+	guint32 id;
+
+	id = rspamd_config_name_to_id (name, namelen);
+
+	return rspamd_config_find_settings_id_ref (cfg, id);
+}
+
+void
+rspamd_config_register_settings_id (struct rspamd_config *cfg,
+										 const gchar *name,
+										 ucl_object_t *symbols_enabled,
+										 ucl_object_t *symbols_disabled)
+{
+	struct rspamd_config_settings_elt *elt;
+	guint32 id;
+
+	id = rspamd_config_name_to_id (name, strlen (name));
+	elt = rspamd_config_find_settings_id_ref (cfg, id);
+
+	if (elt) {
+		/* Need to replace */
+		struct rspamd_config_settings_elt *nelt;
+
+		DL_DELETE (cfg->setting_ids, elt);
+
+		nelt = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*nelt));
+
+		nelt->id = id;
+		nelt->name = rspamd_mempool_strdup (cfg->cfg_pool, name);
+
+		if (symbols_enabled) {
+			nelt->symbols_enabled = ucl_object_ref (symbols_enabled);
+		}
+
+		if (symbols_disabled) {
+			nelt->symbols_disabled = ucl_object_ref (symbols_disabled);
+		}
+
+		REF_INIT_RETAIN (nelt, rspamd_config_settings_elt_dtor);
+		msg_info_config ("replace settings id %d (%s)", id, name);
+		DL_APPEND (cfg->setting_ids, nelt);
+
+		/*
+		 * Need to unref old element twice as there are two reference holders:
+		 * 1. Config structure as we call REF_INIT_RETAIN
+		 * 2. rspamd_config_find_settings_id_ref also increases refcount
+		 */
+		REF_RELEASE (elt);
+		REF_RELEASE (elt);
+	}
+	else {
+		elt = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*elt));
+
+		elt->id = id;
+		elt->name = rspamd_mempool_strdup (cfg->cfg_pool, name);
+
+		if (symbols_enabled) {
+			elt->symbols_enabled = ucl_object_ref (symbols_enabled);
+		}
+
+		if (symbols_disabled) {
+			elt->symbols_disabled = ucl_object_ref (symbols_disabled);
+		}
+
+		msg_info_config ("register new settings id %d (%s)", id, name);
+		REF_INIT_RETAIN (elt, rspamd_config_settings_elt_dtor);
+		DL_APPEND (cfg->setting_ids, elt);
+	}
+}
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c
index 7d3ccb27d..5cd0568da 100644
--- a/src/libserver/protocol.c
+++ b/src/libserver/protocol.c
@@ -483,13 +483,14 @@ rspamd_protocol_handle_headers (struct rspamd_task *task,
 					task->subject = rspamd_mempool_ftokdup (task->task_pool, hv_tok);
 				}
 				IF_HEADER (SETTINGS_ID_HEADER) {
-					guint64 h;
-
 					msg_debug_protocol ("read settings-id header, value: %V", hv);
-					h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
-							hv_tok->begin, hv_tok->len, 0x0);
-					/* Take the lower part of hash as LE number */
-					task->settings_id = (guint32)GUINT64_TO_LE (h);
+					task->settings_elt = rspamd_config_find_settings_name_ref (
+							task->cfg, hv_tok->begin, hv_tok->len);
+
+					if (task->settings_elt == NULL) {
+						msg_warn_protocol ("unknown settings id: %V",
+								hv);
+					}
 				}
 				break;
 			case 'u':
@@ -1702,10 +1703,9 @@ rspamd_protocol_write_log_pipe (struct rspamd_task *task)
 					ls = g_malloc0 (sz);
 
 					/* Handle settings id */
-					sid = task->settings_id;
 
-					if (sid) {
-						ls->settings_id = sid;
+					if (task->settings_elt) {
+						ls->settings_id = task->settings_elt->id;
 					}
 					else {
 						ls->settings_id = 0;
diff --git a/src/libserver/rspamd_symcache.c b/src/libserver/rspamd_symcache.c
index 034049005..22f4c3229 100644
--- a/src/libserver/rspamd_symcache.c
+++ b/src/libserver/rspamd_symcache.c
@@ -1425,24 +1425,26 @@ static gboolean
 rspamd_symcache_is_item_allowed (struct rspamd_task *task,
 								 struct rspamd_symcache_item *item)
 {
-	if (task->settings_id != 0) {
+	if (task->settings_elt != 0) {
+		guint32 id = task->settings_elt->id;
+
 		if (item->forbidden_ids.st[0] != 0 &&
 			rspamd_symcache_check_id_list (&item->forbidden_ids,
-					task->settings_id)) {
+					id)) {
 			msg_debug_cache_task ("deny execution of %s as it is forbidden for "
 						 "settings id %d",
 						 item->symbol,
-						 task->settings_id);
+						 id);
 			return FALSE;
 		}
 
 		if (item->allowed_ids.st[0] != 0 &&
 				!rspamd_symcache_check_id_list (&item->allowed_ids,
-						task->settings_id)) {
+						id)) {
 			msg_debug_cache_task ("deny execution of %s as it is not listed as allowed for "
 								  "settings id %d",
 								  item->symbol,
-								  task->settings_id);
+								  id);
 			return FALSE;
 		}
 	}
diff --git a/src/libserver/task.c b/src/libserver/task.c
index a7c1bc478..16b33294e 100644
--- a/src/libserver/task.c
+++ b/src/libserver/task.c
@@ -313,6 +313,10 @@ rspamd_task_free (struct rspamd_task *task)
 			ucl_object_unref (task->settings);
 		}
 
+		if (task->settings_elt != NULL) {
+			REF_RELEASE (task->settings_elt);
+		}
+
 		if (task->client_addr) {
 			rspamd_inet_address_free (task->client_addr);
 		}
diff --git a/src/libserver/task.h b/src/libserver/task.h
index 079e388df..263f06719 100644
--- a/src/libserver/task.h
+++ b/src/libserver/task.h
@@ -206,7 +206,7 @@ struct rspamd_task {
 	gpointer checkpoint;							/**< Opaque checkpoint data							*/
 	ucl_object_t *settings;							/**< Settings applied to task						*/
 	guint32 processed_stages;							/**< bits of stages that are processed			*/
-	guint32 settings_id;							/**< hashed settings id								*/
+	struct rspamd_config_settings_elt *settings_elt;	/**< preprocessed settings id elt				*/
 
 	const gchar *classifier;						/**< Classifier to learn (if needed)				*/
 	struct rspamd_lang_detector *lang_det;			/**< Languages detector								*/
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 3218a958f..f562d1ca6 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -4872,8 +4872,8 @@ lua_task_get_settings_id (lua_State *L)
 
 	if (task != NULL) {
 
-		if (task->settings_id) {
-			lua_pushnumber (L, task->settings_id);
+		if (task->settings_elt) {
+			lua_pushnumber (L, task->settings_elt->id);
 		}
 		else {
 			lua_pushnil (L);


More information about the Commits mailing list