commit 8f4a672: [Rework] Use more c++ in cfg_utils

Vsevolod Stakhov vsevolod at rspamd.com
Thu Aug 17 11:49:03 UTC 2023


Author: Vsevolod Stakhov
Date: 2023-08-14 12:15:55 +0100
URL: https://github.com/rspamd/rspamd/commit/8f4a6729d18ba775fdb7861ef0239f312d705f4a

[Rework] Use more c++ in cfg_utils

---
 src/libserver/CMakeLists.txt                 |  86 +--
 src/libserver/cfg_file.h                     |   8 +-
 src/libserver/cfg_file_private.h             |   8 +-
 src/libserver/{cfg_utils.c => cfg_utils.cxx} | 769 ++++++++++++---------------
 src/libutil/mem_pool.c                       |   8 +-
 src/libutil/mem_pool.h                       |   8 +-
 src/lua/lua_common.h                         |   2 +-
 7 files changed, 414 insertions(+), 475 deletions(-)

diff --git a/src/libserver/CMakeLists.txt b/src/libserver/CMakeLists.txt
index c4940f917..701ed42d0 100644
--- a/src/libserver/CMakeLists.txt
+++ b/src/libserver/CMakeLists.txt
@@ -1,49 +1,49 @@
 # Librspamdserver
 ADD_SUBDIRECTORY(css)
 SET(LIBRSPAMDSERVERSRC
-				${CMAKE_CURRENT_SOURCE_DIR}/cfg_utils.c
-				${CMAKE_CURRENT_SOURCE_DIR}/cfg_rcl.c
-				${CMAKE_CURRENT_SOURCE_DIR}/composites/composites.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/composites/composites_manager.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/dkim.c
-				${CMAKE_CURRENT_SOURCE_DIR}/dns.c
-				${CMAKE_CURRENT_SOURCE_DIR}/dynamic_cfg.c
-				${CMAKE_CURRENT_SOURCE_DIR}/async_session.c
-				${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend.c
-				${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_sqlite.c
-				${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_redis.c
-				${CMAKE_CURRENT_SOURCE_DIR}/milter.c
-				${CMAKE_CURRENT_SOURCE_DIR}/monitored.c
-				${CMAKE_CURRENT_SOURCE_DIR}/protocol.c
-				${CMAKE_CURRENT_SOURCE_DIR}/re_cache.c
-				${CMAKE_CURRENT_SOURCE_DIR}/redis_pool.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/roll_history.c
-				${CMAKE_CURRENT_SOURCE_DIR}/spf.c
-				${CMAKE_CURRENT_SOURCE_DIR}/ssl_util.c
-				${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_impl.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_item.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_runtime.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_c.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/task.c
-				${CMAKE_CURRENT_SOURCE_DIR}/url.c
-				${CMAKE_CURRENT_SOURCE_DIR}/worker_util.c
-				${CMAKE_CURRENT_SOURCE_DIR}/logger/logger.c
-				${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_file.c
-				${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_syslog.c
-				${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_console.c
-				${CMAKE_CURRENT_SOURCE_DIR}/http/http_util.c
-				${CMAKE_CURRENT_SOURCE_DIR}/http/http_message.c
-				${CMAKE_CURRENT_SOURCE_DIR}/http/http_connection.c
-				${CMAKE_CURRENT_SOURCE_DIR}/http/http_router.c
-				${CMAKE_CURRENT_SOURCE_DIR}/http/http_context.c
-				${CMAKE_CURRENT_SOURCE_DIR}/maps/map.c
-				${CMAKE_CURRENT_SOURCE_DIR}/maps/map_helpers.c
-				${CMAKE_CURRENT_SOURCE_DIR}/html/html_entities.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/html/html_url.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/html/html.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/html/html_tests.cxx
-				${CMAKE_CURRENT_SOURCE_DIR}/hyperscan_tools.cxx
-				${LIBCSSSRC})
+        ${CMAKE_CURRENT_SOURCE_DIR}/cfg_utils.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/cfg_rcl.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites_manager.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/dkim.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/dns.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_cfg.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/async_session.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_sqlite.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_redis.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/milter.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/monitored.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/protocol.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/re_cache.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/redis_pool.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/roll_history.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/spf.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/ssl_util.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_impl.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_item.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_runtime.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_c.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/task.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/url.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/worker_util.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_file.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_syslog.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_console.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/http/http_util.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/http/http_message.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/http/http_connection.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/http/http_router.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/http/http_context.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/maps/map.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/maps/map_helpers.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/html/html_entities.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/html/html_url.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/html/html.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/html/html_tests.cxx
+        ${CMAKE_CURRENT_SOURCE_DIR}/hyperscan_tools.cxx
+        ${LIBCSSSRC})
 
 # Librspamd-server
 SET(RSPAMD_SERVER ${LIBRSPAMDSERVERSRC} PARENT_SCOPE)
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index 9b09608f2..b4b60a92f 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016-2017 Vsevolod Stakhov
+/*
+ * Copyright 2023 Vsevolod Stakhov
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -487,7 +487,7 @@ struct rspamd_config {
 
 	struct rspamd_external_libs_ctx *libs_ctx;  /**< context for external libraries						*/
 	struct rspamd_monitored_ctx *monitored_ctx; /**< context for monitored resources					*/
-	struct rspamd_redis_pool *redis_pool;       /**< redis connection pool								*/
+	void *redis_pool;                           /**< redis connection pool								*/
 
 	struct rspamd_re_cache *re_cache; /**< static regexp cache								*/
 
diff --git a/src/libserver/cfg_file_private.h b/src/libserver/cfg_file_private.h
index d221e8427..1a1500d09 100644
--- a/src/libserver/cfg_file_private.h
+++ b/src/libserver/cfg_file_private.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2019 Vsevolod Stakhov
+/*
+ * Copyright 2023 Vsevolod Stakhov
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -31,7 +31,7 @@ extern "C" {
  */
 struct rspamd_action {
 	enum rspamd_action_type action_type;
-	enum rspamd_action_flags flags;
+	int flags; /* enum rspamd_action_flags */
 	guint priority;
 	gint lua_handler_ref; /* If special handling is needed */
 	gdouble threshold;
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.cxx
similarity index 81%
rename from src/libserver/cfg_utils.c
rename to src/libserver/cfg_utils.cxx
index cdb1518a8..d39998080 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.cxx
@@ -61,6 +61,13 @@
 
 #include "blas-config.h"
 
+#include <string>
+#include <string_view>
+#include "fmt/core.h"
+#include "cxx/util.hxx"
+#include "frozen/unordered_map.h"
+#include "frozen/string.h"
+
 #define DEFAULT_SCORE 10.0
 
 #define DEFAULT_RLIMIT_NOFILE 2048
@@ -84,7 +91,12 @@
 
 struct rspamd_ucl_map_cbdata {
 	struct rspamd_config *cfg;
-	GString *buf;
+	std::string buf;
+
+	explicit rspamd_ucl_map_cbdata(struct rspamd_config *cfg)
+		: cfg(cfg)
+	{
+	}
 };
 static gchar *rspamd_ucl_read_cb(gchar *chunk,
 								 gint len,
@@ -108,25 +120,29 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
 	const gchar *fdname;
 	gboolean ret = TRUE;
 
-	if (str == NULL) {
+	if (str == nullptr) {
 		return FALSE;
 	}
 
-	cnf = g_malloc0(sizeof(struct rspamd_worker_bind_conf));
+	cnf = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_worker_bind_conf);
 
 	cnf->cnt = 1024;
-	cnf->bind_line = g_strdup(str);
+	cnf->bind_line = rspamd_mempool_strdup(cfg->cfg_pool, str);
+
+	auto bind_line = std::string_view{cnf->bind_line};
 
-	if (g_ascii_strncasecmp(str, "systemd:", sizeof("systemd:") - 1) == 0) {
+	if (bind_line.starts_with("systemd:")) {
 		/* The actual socket will be passed by systemd environment */
 		fdname = str + sizeof("systemd:") - 1;
 		cnf->is_systemd = TRUE;
-		cnf->addrs = g_ptr_array_new_full(1, g_free);
+		cnf->addrs = g_ptr_array_new_full(1, nullptr);
+		rspamd_mempool_add_destructor(cfg->cfg_pool,
+									  rspamd_ptr_array_free_hard, cnf->addrs);
 
 		if (fdname[0]) {
-			g_ptr_array_add(cnf->addrs, g_strdup(fdname));
+			g_ptr_array_add(cnf->addrs, rspamd_mempool_strdup(cfg->cfg_pool, fdname));
 			cnf->cnt = cnf->addrs->len;
-			cnf->name = g_strdup(str);
+			cnf->name = rspamd_mempool_strdup(cfg->cfg_pool, str);
 			LL_PREPEND(cf->bind_conf, cnf);
 		}
 		else {
@@ -136,7 +152,7 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
 	}
 	else {
 		if (rspamd_parse_host_port_priority(str, &cnf->addrs,
-											NULL, &cnf->name, DEFAULT_BIND_PORT, TRUE, NULL) == RSPAMD_PARSE_ADDR_FAIL) {
+											nullptr, &cnf->name, DEFAULT_BIND_PORT, TRUE, cfg->cfg_pool) == RSPAMD_PARSE_ADDR_FAIL) {
 			msg_err_config("cannot parse bind line: %s", str);
 			ret = FALSE;
 		}
@@ -146,15 +162,6 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
 		}
 	}
 
-	if (!ret) {
-		if (cnf->addrs) {
-			g_ptr_array_free(cnf->addrs, TRUE);
-		}
-
-		g_free(cnf->name);
-		g_free(cnf);
-	}
-
 	return ret;
 }
 
@@ -178,11 +185,11 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
 	for (int i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
 		struct rspamd_action *action;
 
-		action = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*action));
+		action = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_action);
 		action->threshold = NAN;
 		action->name = rspamd_mempool_strdup(cfg->cfg_pool,
-											 rspamd_action_to_str(i));
-		action->action_type = i;
+											 rspamd_action_to_str(static_cast<rspamd_action_type>(i)));
+		action->action_type = static_cast<rspamd_action_type>(i);
 
 		if (i == METRIC_ACTION_SOFT_REJECT) {
 			action->flags |= RSPAMD_ACTION_NO_THRESHOLD | RSPAMD_ACTION_HAM;
@@ -233,11 +240,12 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
 	cfg->max_opts_len = 4096;
 
 	/* Default log line */
-	cfg->log_format_str = "id: <$mid>,$if_qid{ qid: <$>,}$if_ip{ ip: $,}"
-						  "$if_user{ user: $,}$if_smtp_from{ from: <$>,} (default: $is_spam "
-						  "($action): [$scores] [$symbols_scores_params]), len: $len, time: $time_real, "
-						  "dns req: $dns_req, digest: <$digest>"
-						  "$if_smtp_rcpts{ rcpts: <$>, }$if_mime_rcpt{ mime_rcpt: <$>, }";
+	cfg->log_format_str = rspamd_mempool_strdup(cfg->cfg_pool,
+												"id: <$mid>,$if_qid{ qid: <$>,}$if_ip{ ip: $,}"
+												"$if_user{ user: $,}$if_smtp_from{ from: <$>,} (default: $is_spam "
+												"($action): [$scores] [$symbols_scores_params]), len: $len, time: $time_real, "
+												"dns req: $dns_req, digest: <$digest>"
+												"$if_smtp_rcpts{ rcpts: <$>, }$if_mime_rcpt{ mime_rcpt: <$>, }");
 	/* Allow non-mime input by default */
 	cfg->allow_raw_input = TRUE;
 	/* Default maximum words processed */
@@ -252,12 +260,12 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
 	cfg->full_gc_iters = DEFAULT_GC_MAXITERS;
 
 	/* Default hyperscan cache */
-	cfg->hs_cache_dir = RSPAMD_DBDIR "/";
+	cfg->hs_cache_dir = rspamd_mempool_strdup(cfg->cfg_pool, RSPAMD_DBDIR "/");
 
 	if (!(flags & RSPAMD_CONFIG_INIT_SKIP_LUA)) {
-		cfg->lua_state = rspamd_lua_init(flags & RSPAMD_CONFIG_INIT_WIPE_LUA_MEM);
+		cfg->lua_state = (void *) rspamd_lua_init(flags & RSPAMD_CONFIG_INIT_WIPE_LUA_MEM);
 		cfg->own_lua_state = TRUE;
-		cfg->lua_thread_pool = lua_thread_pool_new(cfg->lua_state);
+		cfg->lua_thread_pool = (void *) lua_thread_pool_new(RSPAMD_LUA_CFG_STATE(cfg));
 	}
 
 	cfg->cache = rspamd_symcache_new(cfg);
@@ -269,7 +277,7 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
 	 */
 	cfg->enable_shutdown_workaround = TRUE;
 
-	cfg->ssl_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
+	cfg->ssl_ciphers = rspamd_mempool_strdup(cfg->cfg_pool, "HIGH:!anullptr:!kRSA:!PSK:!SRP:!MD5:!RC4");
 	cfg->max_message = DEFAULT_MAX_MESSAGE;
 	cfg->max_pic_size = DEFAULT_MAX_PIC;
 	cfg->images_cache_size = 256;
@@ -295,27 +303,27 @@ void rspamd_config_free(struct rspamd_config *cfg)
 	struct rspamd_config_settings_elt *set, *stmp;
 	struct rspamd_worker_log_pipe *lp, *ltmp;
 
-	rspamd_lua_run_config_unload(cfg->lua_state, cfg);
+	rspamd_lua_run_config_unload(RSPAMD_LUA_CFG_STATE(cfg), cfg);
 
 	/* Scripts part */
 	DL_FOREACH_SAFE(cfg->on_term_scripts, sc, sctmp)
 	{
-		luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+		luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
 	}
 
 	DL_FOREACH_SAFE(cfg->on_load_scripts, sc, sctmp)
 	{
-		luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+		luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
 	}
 
 	DL_FOREACH_SAFE(cfg->post_init_scripts, sc, sctmp)
 	{
-		luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+		luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
 	}
 
 	DL_FOREACH_SAFE(cfg->config_unload_scripts, sc, sctmp)
 	{
-		luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+		luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
 	}
 
 	DL_FOREACH_SAFE(cfg->setting_ids, set, stmp)
@@ -348,9 +356,9 @@ void rspamd_config_free(struct rspamd_config *cfg)
 		rspamd_monitored_ctx_destroy(cfg->monitored_ctx);
 	}
 
-	if (cfg->lua_state && cfg->own_lua_state) {
-		lua_thread_pool_free(cfg->lua_thread_pool);
-		rspamd_lua_close(cfg->lua_state);
+	if (RSPAMD_LUA_CFG_STATE(cfg) && cfg->own_lua_state) {
+		lua_thread_pool_free((struct lua_thread_pool *) cfg->lua_thread_pool);
+		rspamd_lua_close(RSPAMD_LUA_CFG_STATE(cfg));
 	}
 
 	if (cfg->redis_pool) {
@@ -382,10 +390,10 @@ rspamd_config_get_module_opt(struct rspamd_config *cfg,
 							 const gchar *module_name,
 							 const gchar *opt_name)
 {
-	const ucl_object_t *res = NULL, *sec;
+	const ucl_object_t *res = nullptr, *sec;
 
 	sec = ucl_obj_get_key(cfg->rcl_obj, module_name);
-	if (sec != NULL) {
+	if (sec != nullptr) {
 		res = ucl_obj_get_key(sec, opt_name);
 	}
 
@@ -445,173 +453,122 @@ gint rspamd_config_parse_flag(const gchar *str, guint len)
 	return -1;
 }
 
+// A mapping between names and log format types + flags
+constexpr const auto config_vars = frozen::make_unordered_map<frozen::string, std::pair<rspamd_log_format_type, int>>({
+	{"mid", {RSPAMD_LOG_MID, 0}},
+	{"qid", {RSPAMD_LOG_QID, 0}},
+	{"user", {RSPAMD_LOG_USER, 0}},
+	{"ip", {RSPAMD_LOG_IP, 0}},
+	{"len", {RSPAMD_LOG_LEN, 0}},
+	{"dns_req", {RSPAMD_LOG_DNS_REQ, 0}},
+	{"smtp_from", {RSPAMD_LOG_SMTP_FROM, 0}},
+	{"mime_from", {RSPAMD_LOG_MIME_FROM, 0}},
+	{"smtp_rcpt", {RSPAMD_LOG_SMTP_RCPT, 0}},
+	{"mime_rcpt", {RSPAMD_LOG_MIME_RCPT, 0}},
+	{"smtp_rcpts", {RSPAMD_LOG_SMTP_RCPTS, 0}},
+	{"mime_rcpts", {RSPAMD_LOG_MIME_RCPTS, 0}},
+	{"time_real", {RSPAMD_LOG_TIME_REAL, 0}},
+	{"time_virtual", {RSPAMD_LOG_TIME_VIRTUAL, 0}},
+	{"lua", {RSPAMD_LOG_LUA, 0}},
+	{"digest", {RSPAMD_LOG_DIGEST, 0}},
+	{"checksum", {RSPAMD_LOG_DIGEST, 0}},
+	{"filename", {RSPAMD_LOG_FILENAME, 0}},
+	{"forced_action", {RSPAMD_LOG_FORCED_ACTION, 0}},
+	{"settings_id", {RSPAMD_LOG_SETTINGS_ID, 0}},
+	{"mempool_size", {RSPAMD_LOG_MEMPOOL_SIZE, 0}},
+	{"mempool_waste", {RSPAMD_LOG_MEMPOOL_WASTE, 0}},
+	{"action", {RSPAMD_LOG_ACTION, 0}},
+	{"scores", {RSPAMD_LOG_SCORES, 0}},
+	{"symbols", {RSPAMD_LOG_SYMBOLS, 0}},
+	{"symbols_scores", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES}},
+	{"symbols_params", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS}},
+	{"symbols_scores_params", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS | RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES}},
+	{"groups", {RSPAMD_LOG_GROUPS, 0}},
+	{"public_groups", {RSPAMD_LOG_PUBLIC_GROUPS, 0}},
+});
+
 static gboolean
 rspamd_config_process_var(struct rspamd_config *cfg, const rspamd_ftok_t *var,
 						  const rspamd_ftok_t *content)
 {
-	guint flags = RSPAMD_LOG_FLAG_DEFAULT;
-	struct rspamd_log_format *lf;
-	enum rspamd_log_format_type type;
-	rspamd_ftok_t tok;
-	gint id;
+	g_assert(var != nullptr);
 
-	g_assert(var != NULL);
+	auto flags = 0;
+	auto lc_var = std::string{var->begin, var->len};
+	std::transform(lc_var.begin(), lc_var.end(), lc_var.begin(), g_ascii_tolower);
+	auto tok = std::string_view{lc_var};
 
-	if (var->len > 3 && rspamd_lc_cmp(var->begin, "if_", 3) == 0) {
+	if (var->len > 3 && tok.starts_with("if_")) {
 		flags |= RSPAMD_LOG_FMT_FLAG_CONDITION;
-		tok.begin = var->begin + 3;
-		tok.len = var->len - 3;
-	}
-	else {
-		tok.begin = var->begin;
-		tok.len = var->len;
+		tok = tok.substr(3);
 	}
 
-	/* Now compare variable and check what we have */
-	if (rspamd_ftok_cstr_equal(&tok, "mid", TRUE)) {
-		type = RSPAMD_LOG_MID;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "qid", TRUE)) {
-		type = RSPAMD_LOG_QID;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "user", TRUE)) {
-		type = RSPAMD_LOG_USER;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "is_spam", TRUE)) {
-		type = RSPAMD_LOG_ISSPAM;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "action", TRUE)) {
-		type = RSPAMD_LOG_ACTION;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "scores", TRUE)) {
-		type = RSPAMD_LOG_SCORES;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "symbols", TRUE)) {
-		type = RSPAMD_LOG_SYMBOLS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "symbols_scores", TRUE)) {
-		type = RSPAMD_LOG_SYMBOLS;
-		flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "symbols_params", TRUE)) {
-		type = RSPAMD_LOG_SYMBOLS;
-		flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "symbols_scores_params", TRUE)) {
-		type = RSPAMD_LOG_SYMBOLS;
-		flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS | RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "groups", TRUE)) {
-		type = RSPAMD_LOG_GROUPS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "public_groups", TRUE)) {
-		type = RSPAMD_LOG_PUBLIC_GROUPS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "ip", TRUE)) {
-		type = RSPAMD_LOG_IP;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "len", TRUE)) {
-		type = RSPAMD_LOG_LEN;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "dns_req", TRUE)) {
-		type = RSPAMD_LOG_DNS_REQ;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "smtp_from", TRUE)) {
-		type = RSPAMD_LOG_SMTP_FROM;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "mime_from", TRUE)) {
-		type = RSPAMD_LOG_MIME_FROM;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "smtp_rcpt", TRUE)) {
-		type = RSPAMD_LOG_SMTP_RCPT;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "mime_rcpt", TRUE)) {
-		type = RSPAMD_LOG_MIME_RCPT;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "smtp_rcpts", TRUE)) {
-		type = RSPAMD_LOG_SMTP_RCPTS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "mime_rcpts", TRUE)) {
-		type = RSPAMD_LOG_MIME_RCPTS;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "time_real", TRUE)) {
-		type = RSPAMD_LOG_TIME_REAL;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "time_virtual", TRUE)) {
-		type = RSPAMD_LOG_TIME_VIRTUAL;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "lua", TRUE)) {
-		type = RSPAMD_LOG_LUA;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "digest", TRUE) ||
-			 rspamd_ftok_cstr_equal(&tok, "checksum", TRUE)) {
-		type = RSPAMD_LOG_DIGEST;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "filename", TRUE)) {
-		type = RSPAMD_LOG_FILENAME;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "forced_action", TRUE)) {
-		type = RSPAMD_LOG_FORCED_ACTION;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "settings_id", TRUE)) {
-		type = RSPAMD_LOG_SETTINGS_ID;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "mempool_size", TRUE)) {
-		type = RSPAMD_LOG_MEMPOOL_SIZE;
-	}
-	else if (rspamd_ftok_cstr_equal(&tok, "mempool_waste", TRUE)) {
-		type = RSPAMD_LOG_MEMPOOL_WASTE;
-	}
-	else {
-		msg_err_config("unknown log variable: %T", &tok);
-		return FALSE;
-	}
+	auto maybe_fmt_var = rspamd::find_map(config_vars, tok);
 
-	lf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*lf));
-	lf->type = type;
-	lf->flags = flags;
+	if (maybe_fmt_var) {
+		auto &fmt_var = maybe_fmt_var.value().get();
+		auto *log_format = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_log_format);
 
-	if (type != RSPAMD_LOG_LUA) {
-		if (content && content->len > 0) {
-			lf->data = rspamd_mempool_alloc0(cfg->cfg_pool,
-											 sizeof(rspamd_ftok_t));
-			memcpy(lf->data, content, sizeof(*content));
-			lf->len = sizeof(*content);
-		}
-	}
-	else {
-		/* Load lua code and ensure that we have function ref returned */
-		if (!content || content->len == 0) {
-			msg_err_config("lua variable needs content: %T", &tok);
-			return FALSE;
-		}
+		log_format->type = fmt_var.first;
+		log_format->flags = fmt_var.second | flags;
 
-		if (luaL_loadbuffer(cfg->lua_state, content->begin, content->len,
-							"lua log variable") != 0) {
-			msg_err_config("error loading lua code: '%T': %s", content,
-						   lua_tostring(cfg->lua_state, -1));
-			return FALSE;
+		if (log_format->type != RSPAMD_LOG_LUA) {
+			if (content && content->len > 0) {
+				log_format->data = rspamd_mempool_alloc0(cfg->cfg_pool,
+														 sizeof(rspamd_ftok_t));
+				memcpy(log_format->data, content, sizeof(*content));
+				log_format->len = sizeof(*content);
+			}
 		}
-		if (lua_pcall(cfg->lua_state, 0, 1, 0) != 0) {
-			msg_err_config("error executing lua code: '%T': %s", content,
-						   lua_tostring(cfg->lua_state, -1));
-			lua_pop(cfg->lua_state, 1);
+		else {
+			/* Load lua code and ensure that we have function ref returned */
+			if (!content || content->len == 0) {
+				msg_err_config("lua variable needs content: %T", &tok);
+				return FALSE;
+			}
 
-			return FALSE;
-		}
+			if (luaL_loadbuffer(RSPAMD_LUA_CFG_STATE(cfg), content->begin, content->len,
+								"lua log variable") != 0) {
+				msg_err_config("error loading lua code: '%T': %s", content,
+							   lua_tostring(RSPAMD_LUA_CFG_STATE(cfg), -1));
+				return FALSE;
+			}
+			if (lua_pcall(RSPAMD_LUA_CFG_STATE(cfg), 0, 1, 0) != 0) {
+				msg_err_config("error executing lua code: '%T': %s", content,
+							   lua_tostring(RSPAMD_LUA_CFG_STATE(cfg), -1));
+				lua_pop(RSPAMD_LUA_CFG_STATE(cfg), 1);
 
-		if (lua_type(cfg->lua_state, -1) != LUA_TFUNCTION) {
-			msg_err_config("lua variable should return function: %T", content);
-			lua_pop(cfg->lua_state, 1);
-			return FALSE;
+				return FALSE;
+			}
+
+			if (lua_type(RSPAMD_LUA_CFG_STATE(cfg), -1) != LUA_TFUNCTION) {
+				msg_err_config("lua variable should return function: %T", content);
+				lua_pop(RSPAMD_LUA_CFG_STATE(cfg), 1);
+				return FALSE;
+			}
+
+			auto id = luaL_ref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX);
+			log_format->data = GINT_TO_POINTER(id);
+			log_format->len = 0;
 		}
 
-		id = luaL_ref(cfg->lua_state, LUA_REGISTRYINDEX);
-		lf->data = GINT_TO_POINTER(id);
-		lf->len = 0;
+		DL_APPEND(cfg->log_format, log_format);
 	}
+	else {
+		std::string known_formats;
 
-	DL_APPEND(cfg->log_format, lf);
+		for (const auto &v: config_vars) {
+			known_formats += std::string_view{v.first.data(), v.first.size()};
+			known_formats += ", ";
+		}
+
+		if (known_formats.size() > 2) {
+			// Remove last comma
+			known_formats.resize(known_formats.size() - 2);
+		}
+		msg_err_config("unknown log variable: %T, known vars are: \"%s\"", var, known_formats.c_str());
+		return FALSE;
+	}
 
 	return TRUE;
 }
@@ -621,7 +578,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
 {
 	const gchar *p, *c, *end, *s;
 	gchar *d;
-	struct rspamd_log_format *lf = NULL;
+	struct rspamd_log_format *lf = nullptr;
 	rspamd_ftok_t var, var_content;
 	enum {
 		parse_str,
@@ -631,10 +588,10 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
 	} state = parse_str;
 	gint braces = 0;
 
-	g_assert(cfg != NULL);
+	g_assert(cfg != nullptr);
 	c = cfg->log_format_str;
 
-	if (c == NULL) {
+	if (c == nullptr) {
 		return FALSE;
 	}
 
@@ -654,12 +611,12 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
 		case parse_dollar:
 			if (p > c) {
 				/* We have string element that we need to store */
-				lf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*lf));
+				lf = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_log_format);
 				lf->type = RSPAMD_LOG_STRING;
 				lf->data = rspamd_mempool_alloc(cfg->cfg_pool, p - c + 1);
 				/* Filter \r\n from the destination */
 				s = c;
-				d = lf->data;
+				d = (char *) lf->data;
 
 				while (s < p) {
 					if (*s != '\r' && *s != '\n') {
@@ -674,7 +631,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
 
 				lf->len = d - (char *) lf->data;
 				DL_APPEND(cfg->log_format, lf);
-				lf = NULL;
+				lf = nullptr;
 			}
 			p++;
 			c = p;
*** OUTPUT TRUNCATED, 1168 LINES SKIPPED ***


More information about the Commits mailing list