123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /*
- * 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
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #include "symcache_internal.hxx"
- #include "symcache_periodic.hxx"
- #include "symcache_item.hxx"
- #include "symcache_runtime.hxx"
-
- /**
- * C API for symcache
- */
-
- #define C_API_SYMCACHE(ptr) (reinterpret_cast<rspamd::symcache::symcache *>(ptr))
- #define C_API_SYMCACHE_RUNTIME(ptr) (reinterpret_cast<rspamd::symcache::symcache_runtime *>(ptr))
- #define C_API_SYMCACHE_ITEM(ptr) (reinterpret_cast<rspamd::symcache::cache_item *>(ptr))
- #define C_API_SYMCACHE_DYN_ITEM(ptr) (reinterpret_cast<rspamd::symcache::cache_dynamic_item *>(ptr))
-
- void rspamd_symcache_destroy(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- delete real_cache;
- }
-
- struct rspamd_symcache *
- rspamd_symcache_new(struct rspamd_config *cfg)
- {
- auto *ncache = new rspamd::symcache::symcache(cfg);
-
- return (struct rspamd_symcache *) ncache;
- }
-
- gboolean
- rspamd_symcache_init(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- return real_cache->init();
- }
-
- void rspamd_symcache_save(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->save_items();
- }
-
- int rspamd_symcache_add_symbol(struct rspamd_symcache *cache,
- const char *name,
- int priority,
- symbol_func_t func,
- gpointer user_data,
- int type,
- int parent)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- /* Legacy stuff */
- if (name == nullptr) {
- name = "";
- }
-
- if (parent == -1) {
- return real_cache->add_symbol_with_callback(name, priority, func, user_data, type);
- }
- else {
- return real_cache->add_virtual_symbol(name, parent, type);
- }
- }
-
- bool rspamd_symcache_add_symbol_augmentation(struct rspamd_symcache *cache,
- int sym_id,
- const char *augmentation,
- const char *value)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- auto log_tag = [&]() { return real_cache->log_tag(); };
-
- if (augmentation == nullptr) {
- msg_err_cache("null augmentation is not allowed for item %d", sym_id);
- return false;
- }
-
-
- auto *item = real_cache->get_item_by_id_mut(sym_id, false);
-
- if (item == nullptr) {
- msg_err_cache("item %d is not found", sym_id);
- return false;
- }
-
- /* Handle empty or absent strings equally */
- if (value == nullptr || value[0] == '\0') {
- return item->add_augmentation(*real_cache, augmentation, std::nullopt);
- }
-
- return item->add_augmentation(*real_cache, augmentation, value);
- }
-
- void rspamd_symcache_set_peak_callback(struct rspamd_symcache *cache, int cbref)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->set_peak_cb(cbref);
- }
-
- gboolean
- rspamd_symcache_add_condition_delayed(struct rspamd_symcache *cache,
- const char *sym, lua_State *L, int cbref)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->add_delayed_condition(sym, cbref);
-
- return TRUE;
- }
-
- int rspamd_symcache_find_symbol(struct rspamd_symcache *cache,
- const char *name)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- /* Legacy stuff but used */
- if (name == nullptr) {
- return -1;
- }
-
- auto sym_maybe = real_cache->get_item_by_name(name, false);
-
- if (sym_maybe != nullptr) {
- return sym_maybe->id;
- }
-
- return -1;
- }
-
- gboolean
- rspamd_symcache_stat_symbol(struct rspamd_symcache *cache,
- const char *name,
- double *frequency,
- double *freq_stddev,
- double *tm,
- unsigned int *nhits)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto sym_maybe = real_cache->get_item_by_name(name, false);
-
- if (sym_maybe != nullptr) {
- *frequency = sym_maybe->st->avg_frequency;
- *freq_stddev = sqrt(sym_maybe->st->stddev_frequency);
- *tm = sym_maybe->st->time_counter.mean;
-
- if (nhits) {
- *nhits = sym_maybe->st->hits;
- }
-
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- unsigned int rspamd_symcache_stats_symbols_count(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- return real_cache->get_stats_symbols_count();
- }
-
- uint64_t
- rspamd_symcache_get_cksum(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- return real_cache->get_cksum();
- }
-
- gboolean
- rspamd_symcache_validate(struct rspamd_symcache *cache,
- struct rspamd_config *cfg,
- gboolean strict)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- return real_cache->validate(strict);
- }
-
- ucl_object_t *
- rspamd_symcache_counters(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- return real_cache->counters();
- }
-
- void *
- rspamd_symcache_start_refresh(struct rspamd_symcache *cache,
- struct ev_loop *ev_base, struct rspamd_worker *w)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- return new rspamd::symcache::cache_refresh_cbdata{real_cache, ev_base, w};
- }
-
- void rspamd_symcache_inc_frequency(struct rspamd_symcache *cache, struct rspamd_symcache_item *item,
- const char *sym_name)
- {
- auto *real_item = C_API_SYMCACHE_ITEM(item);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (real_item) {
- real_item->inc_frequency(sym_name, *real_cache);
- }
- }
-
- void rspamd_symcache_add_delayed_dependency(struct rspamd_symcache *cache,
- const char *from, const char *to)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- real_cache->add_delayed_dependency(from, to);
- }
-
- const char *
- rspamd_symcache_get_parent(struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *sym = real_cache->get_item_by_name(symbol, false);
-
- if (sym && sym->is_virtual()) {
- auto *parent = sym->get_parent(*real_cache);
-
- if (parent) {
- return parent->get_name().c_str();
- }
- }
-
- return nullptr;
- }
-
- const char *
- rspamd_symcache_item_name(struct rspamd_symcache_item *item)
- {
- auto *real_item = C_API_SYMCACHE_ITEM(item);
-
- if (real_item == nullptr) {
- return nullptr;
- }
-
- return real_item->get_name().c_str();
- }
-
- int rspamd_symcache_item_flags(struct rspamd_symcache_item *item)
- {
- auto *real_item = C_API_SYMCACHE_ITEM(item);
-
- if (real_item == nullptr) {
- return 0;
- }
-
- return real_item->get_flags();
- }
-
-
- const char *
- rspamd_symcache_dyn_item_name(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *dyn_item)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(dyn_item);
-
- if (cache_runtime == nullptr || real_dyn_item == nullptr) {
- return nullptr;
- }
-
- auto static_item = cache_runtime->get_item_by_dynamic_item(real_dyn_item);
-
- return static_item->get_name().c_str();
- }
-
- int rspamd_symcache_item_flags(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *dyn_item)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(dyn_item);
-
- if (cache_runtime == nullptr || real_dyn_item == nullptr) {
- return 0;
- }
-
- auto static_item = cache_runtime->get_item_by_dynamic_item(real_dyn_item);
-
- return static_item->get_flags();
- }
-
- unsigned int rspamd_symcache_get_symbol_flags(struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *sym = real_cache->get_item_by_name(symbol, false);
-
- if (sym) {
- return sym->get_flags();
- }
-
- return 0;
- }
-
- const struct rspamd_symcache_item_stat *
- rspamd_symcache_item_stat(struct rspamd_symcache_item *item)
- {
- auto *real_item = C_API_SYMCACHE_ITEM(item);
- return real_item->st;
- }
-
- void rspamd_symcache_get_symbol_details(struct rspamd_symcache *cache,
- const char *symbol,
- ucl_object_t *this_sym_ucl)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *sym = real_cache->get_item_by_name(symbol, false);
-
- if (sym) {
- ucl_object_insert_key(this_sym_ucl,
- ucl_object_fromstring(sym->get_type_str()),
- "type", strlen("type"), false);
- }
- }
-
- void rspamd_symcache_foreach(struct rspamd_symcache *cache,
- void (*func)(struct rspamd_symcache_item *item, gpointer /* userdata */),
- gpointer ud)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->symbols_foreach([&](const rspamd::symcache::cache_item *item) {
- func((struct rspamd_symcache_item *) item, ud);
- });
- }
-
- void rspamd_symcache_process_settings_elt(struct rspamd_symcache *cache,
- struct rspamd_config_settings_elt *elt)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->process_settings_elt(elt);
- }
-
- bool rspamd_symcache_set_allowed_settings_ids(struct rspamd_symcache *cache,
- const char *symbol,
- const uint32_t *ids,
- unsigned int nids)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *item = real_cache->get_item_by_name_mut(symbol, false);
-
- if (item == nullptr) {
- return false;
- }
-
- item->allowed_ids.set_ids(ids, nids);
- return true;
- }
-
- bool rspamd_symcache_set_forbidden_settings_ids(struct rspamd_symcache *cache,
- const char *symbol,
- const uint32_t *ids,
- unsigned int nids)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *item = real_cache->get_item_by_name_mut(symbol, false);
-
- if (item == nullptr) {
- return false;
- }
-
- item->forbidden_ids.set_ids(ids, nids);
- return true;
- }
-
- const uint32_t *
- rspamd_symcache_get_allowed_settings_ids(struct rspamd_symcache *cache,
- const char *symbol,
- unsigned int *nids)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- const auto *item = real_cache->get_item_by_name(symbol, false);
- return item->allowed_ids.get_ids(*nids);
- }
-
- const uint32_t *
- rspamd_symcache_get_forbidden_settings_ids(struct rspamd_symcache *cache,
- const char *symbol,
- unsigned int *nids)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- const auto *item = real_cache->get_item_by_name(symbol, false);
- return item->forbidden_ids.get_ids(*nids);
- }
-
- void rspamd_symcache_disable_all_symbols(struct rspamd_task *task,
- struct rspamd_symcache *_cache,
- unsigned int skip_mask)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
-
- cache_runtime->disable_all_symbols(skip_mask);
- }
-
- gboolean
- rspamd_symcache_disable_symbol(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (cache_runtime == nullptr) {
- return FALSE;
- }
-
- return cache_runtime->disable_symbol(task, *real_cache, symbol);
- }
-
- gboolean
- rspamd_symcache_enable_symbol(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (cache_runtime == nullptr) {
- return FALSE;
- }
-
- return cache_runtime->enable_symbol(task, *real_cache, symbol);
- }
-
- void rspamd_symcache_disable_symbol_static(struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->disable_symbol_delayed(symbol);
- }
-
- void rspamd_symcache_enable_symbol_static(struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- real_cache->enable_symbol_delayed(symbol);
- }
-
- /* A real structure to match C results without extra copying */
- struct rspamd_symcache_real_timeout_result {
- struct rspamd_symcache_timeout_result c_api_result;
- std::vector<std::pair<double, const rspamd::symcache::cache_item *>> elts;
- };
-
- struct rspamd_symcache_timeout_result *
- rspamd_symcache_get_max_timeout(struct rspamd_symcache *cache)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- auto *res = new rspamd_symcache_real_timeout_result;
-
- res->c_api_result.max_timeout = real_cache->get_max_timeout(res->elts);
- res->c_api_result.items = reinterpret_cast<struct rspamd_symcache_timeout_item *>(res->elts.data());
- res->c_api_result.nitems = res->elts.size();
-
- return &res->c_api_result;
- }
-
- void rspamd_symcache_timeout_result_free(struct rspamd_symcache_timeout_result *res)
- {
- auto *real_result = reinterpret_cast<rspamd_symcache_real_timeout_result *>(res);
- delete real_result;
- }
-
- gboolean
- rspamd_symcache_is_checked(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (cache_runtime == nullptr) {
- return FALSE;
- }
-
- return cache_runtime->is_symbol_checked(*real_cache, symbol);
- }
-
- gboolean
- rspamd_symcache_process_settings(struct rspamd_task *task,
- struct rspamd_symcache *cache)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (cache_runtime == nullptr) {
- return FALSE;
- }
-
- return cache_runtime->process_settings(task, *real_cache);
- }
-
- gboolean
- rspamd_symcache_is_item_allowed(struct rspamd_task *task,
- struct rspamd_symcache_item *item,
- gboolean exec_only)
- {
- auto *real_item = C_API_SYMCACHE_ITEM(item);
-
- if (real_item == nullptr) {
- return TRUE;
- }
-
- return real_item->is_allowed(task, exec_only);
- }
-
- gboolean
- rspamd_symcache_is_symbol_enabled(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (!cache_runtime) {
- return TRUE;
- }
-
- return cache_runtime->is_symbol_enabled(task, *real_cache, symbol);
- }
-
- struct rspamd_symcache_dynamic_item *
- rspamd_symcache_get_cur_item(struct rspamd_task *task)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
-
- if (!cache_runtime) {
- return nullptr;
- }
-
- return (struct rspamd_symcache_dynamic_item *) cache_runtime->get_cur_item();
- }
-
- struct rspamd_symcache_dynamic_item *
- rspamd_symcache_set_cur_item(struct rspamd_task *task, struct rspamd_symcache_dynamic_item *item)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(item);
-
- if (!cache_runtime || !real_dyn_item) {
- return nullptr;
- }
-
- return (struct rspamd_symcache_dynamic_item *) cache_runtime->set_cur_item(real_dyn_item);
- }
-
- void rspamd_symcache_enable_profile(struct rspamd_task *task)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- if (!cache_runtime) {
- return;
- }
-
- cache_runtime->set_profile_mode(true);
- }
-
- unsigned int rspamd_symcache_item_async_inc_full(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *item,
- const char *subsystem,
- const char *loc)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(item);
-
- auto *static_item = cache_runtime->get_item_by_dynamic_item(real_dyn_item);
- msg_debug_cache_task("increase async events counter for %s(%d) = %d + 1; "
- "subsystem %s (%s)",
- static_item->symbol.c_str(), static_item->id,
- real_dyn_item->async_events, subsystem, loc);
-
- return ++real_dyn_item->async_events;
- }
-
- unsigned int rspamd_symcache_item_async_dec_full(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *item,
- const char *subsystem,
- const char *loc)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(item);
-
- auto *static_item = cache_runtime->get_item_by_dynamic_item(real_dyn_item);
- msg_debug_cache_task("decrease async events counter for %s(%d) = %d - 1; "
- "subsystem %s (%s)",
- static_item->symbol.c_str(), static_item->id,
- real_dyn_item->async_events, subsystem, loc);
-
- if (G_UNLIKELY(real_dyn_item->async_events == 0)) {
- msg_err_cache_task("INTERNAL ERROR: trying decrease async events counter for %s(%d) that is already zero; "
- "subsystem %s (%s)",
- static_item->symbol.c_str(), static_item->id,
- real_dyn_item->async_events, subsystem, loc);
- g_abort();
- g_assert_not_reached();
- }
-
- return --real_dyn_item->async_events;
- }
-
- gboolean
- rspamd_symcache_item_async_dec_check_full(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *item,
- const char *subsystem,
- const char *loc)
- {
- if (rspamd_symcache_item_async_dec_full(task, item, subsystem, loc) == 0) {
- rspamd_symcache_finalize_item(task, item);
-
- return TRUE;
- }
-
- return FALSE;
- }
-
- struct rspamd_abstract_callback_data *
- rspamd_symcache_get_cbdata(struct rspamd_symcache *cache,
- const char *symbol)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- auto *item = real_cache->get_item_by_name(symbol, true);
-
- if (item) {
- return (struct rspamd_abstract_callback_data *) item->get_cbdata();
- }
-
- return nullptr;
- }
-
- void rspamd_symcache_composites_foreach(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- GHFunc func,
- gpointer fd)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
-
- real_cache->composites_foreach([&](const auto *item) {
- auto *dyn_item = cache_runtime->get_dynamic_item(item->id);
-
- if (dyn_item && !dyn_item->started) {
- auto *old_item = cache_runtime->set_cur_item(dyn_item);
- func((void *) item->get_name().c_str(), item->get_cbdata(), fd);
- dyn_item->finished = true;
- cache_runtime->set_cur_item(old_item);
- }
- });
-
- cache_runtime->set_cur_item(nullptr);
- }
-
- gboolean
- rspamd_symcache_process_symbols(struct rspamd_task *task,
- struct rspamd_symcache *cache,
- unsigned int stage)
- {
- auto *real_cache = C_API_SYMCACHE(cache);
-
- if (task->symcache_runtime == nullptr) {
- task->symcache_runtime = rspamd::symcache::symcache_runtime::create(task, *real_cache);
- }
-
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- return cache_runtime->process_symbols(task, *real_cache, stage);
- }
-
- void rspamd_symcache_finalize_item(struct rspamd_task *task,
- struct rspamd_symcache_dynamic_item *item)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- auto *real_dyn_item = C_API_SYMCACHE_DYN_ITEM(item);
-
- cache_runtime->finalize_item(task, real_dyn_item);
- }
-
- void rspamd_symcache_runtime_destroy(struct rspamd_task *task)
- {
- auto *cache_runtime = C_API_SYMCACHE_RUNTIME(task->symcache_runtime);
- cache_runtime->savepoint_dtor();
- }
|