Skip to content

Commit

Permalink
[Feature] Preliminary implementation of dynamic composites
Browse files Browse the repository at this point in the history
  • Loading branch information
vstakhov committed Jun 25, 2023
1 parent 0a04052 commit 2872db1
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/libserver/composites/composites_internal.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public:
}

auto add_composite(std::string_view, const ucl_object_t *, bool silent_duplicate) -> rspamd_composite *;
auto add_composite(std::string_view name, std::string_view expression, bool silent_duplicate) -> rspamd_composite *;
auto add_composite(std::string_view name, std::string_view expression, bool silent_duplicate, double score = NAN) -> rspamd_composite *;
private:
~composites_manager() = default;
static void composites_manager_dtor(void *ptr) {
Expand Down
111 changes: 108 additions & 3 deletions src/libserver/composites/composites_manager.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "composites_internal.hxx"
#include "libserver/cfg_file.h"
#include "libserver/logger.h"
#include "libserver/maps/map.h"
#include "libutil/cxx/util.hxx"

namespace rspamd::composites {

Expand Down Expand Up @@ -149,7 +151,7 @@ composites_manager::add_composite(std::string_view composite_name, const ucl_obj
auto
composites_manager::add_composite(std::string_view composite_name,
std::string_view composite_expression,
bool silent_duplicate) -> rspamd_composite *
bool silent_duplicate, double score) -> rspamd_composite *
{
GError *err = nullptr;
rspamd_expression *expr = nullptr;
Expand Down Expand Up @@ -178,8 +180,8 @@ composites_manager::add_composite(std::string_view composite_name,
return nullptr;
}

auto score = std::isnan(cfg->unknown_weight) ? 0.0 : cfg->unknown_weight;
rspamd_config_add_symbol(cfg, composite_name.data(), score,
auto final_score = std::isnan(score) ? (std::isnan(cfg->unknown_weight) ? 0.0 : cfg->unknown_weight) : score;
rspamd_config_add_symbol(cfg, composite_name.data(), final_score,
composite_name.data(), "composite",
0,
0,
Expand All @@ -188,6 +190,89 @@ composites_manager::add_composite(std::string_view composite_name,
return new_composite(composite_name, expr, composite_expression).get();
}

struct map_cbdata {
composites_manager *cm;
struct rspamd_config *cfg;
std::string buf;

explicit map_cbdata(struct rspamd_config *cfg) : cfg(cfg) {
cm = COMPOSITE_MANAGER_FROM_PTR(cfg->composites_manager);
}

static char *map_read(char *chunk, int len,
struct map_cb_data *data,
gboolean _final) {

if (data->cur_data == nullptr) {
data->cur_data = data->prev_data;
reinterpret_cast<map_cbdata *>(data->cur_data)->buf.clear();
}

auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);

cbd->buf.append(chunk, len);
return nullptr;
}

static void
map_fin(struct map_cb_data *data, void **target) {
auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);

if (data->errored) {
if (cbd) {
cbd->buf.clear();
}
}
else if (cbd != nullptr) {
if (target) {
*target = data->cur_data;
}

rspamd::string_foreach_line(cbd->buf, [&](std::string_view line) {
auto [name_and_score, expr] = rspamd::string_split_on(line, ' ');
auto [name, score] = rspamd::string_split_on(name_and_score, ':');

if (!score.empty()) {
/* I wish it was supported properly */
//auto conv_res = std::from_chars(value->data(), value->size(), num);
char numbuf[128], *endptr = nullptr;
rspamd_strlcpy(numbuf, score.data(), MIN(score.size(), sizeof(numbuf)));
auto num = g_ascii_strtod(numbuf, &endptr);

if (fabs(num) >= G_MAXFLOAT || std::isnan(num)) {
msg_err("invalid score for %*s", (int)name_and_score.size(), name_and_score.data());
return;
}

auto ret = cbd->cm->add_composite(name, expr, true, num);

if (ret == nullptr) {
msg_err("cannot add composite %*s", (int)name_and_score.size(), name_and_score.data());
return;
}
}
else {
msg_err("missing score for %*s", (int)name_and_score.size(), name_and_score.data());
return;
}
});

}
else {
msg_err ("no data read for composites map");
}
}

static void
map_dtor (struct map_cb_data *data) {
auto *cbd = reinterpret_cast<map_cbdata *>(data->cur_data);

if (cbd) {
delete cbd;
}
}
};

}


Expand Down Expand Up @@ -229,3 +314,23 @@ rspamd_composites_manager_add_from_string_silent(void *cm, const char *sym, cons
{
return reinterpret_cast<void *>(COMPOSITE_MANAGER_FROM_PTR(cm)->add_composite(sym, expr, true));
}



bool
rspamd_composites_add_map_handlers(const ucl_object_t *obj, struct rspamd_config *cfg)
{
auto **pcbdata = rspamd_mempool_alloc_type(cfg->cfg_pool, rspamd::composites::map_cbdata *);
auto *cbdata = new rspamd::composites::map_cbdata{cfg};
*pcbdata = cbdata;

if (struct rspamd_map *m; (m = rspamd_map_add_from_ucl(cfg, obj, "composites map",
rspamd::composites::map_cbdata::map_read, rspamd::composites::map_cbdata::map_fin,
rspamd::composites::map_cbdata::map_dtor, (void **)pcbdata,
nullptr, RSPAMD_MAP_DEFAULT)) == nullptr) {
msg_err_config("cannot load composites map from %s", ucl_object_key(obj));
return false;
}

return true;
}

0 comments on commit 2872db1

Please sign in to comment.