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
*/
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 */
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
{
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);
+ }
+}
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':
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;
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;
}
}
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);
}
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 */
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);