]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Start C API implementation
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 22 Oct 2022 13:55:52 +0000 (14:55 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 22 Oct 2022 13:55:52 +0000 (14:55 +0100)
src/libserver/hyperscan_tools.cxx
src/libserver/hyperscan_tools.h [new file with mode: 0644]

index 1272aa4526cc18d9a7aca94269a58c968c6a6ffe..309f821dd8e3fb7e97b4600037a9eeea10c455f0 100644 (file)
@@ -25,6 +25,7 @@
 #include "hs.h"
 #include "logger.h"
 #include "worker_util.h"
+#include "hyperscan_tools.h"
 
 #include <glob.h> /* for glob */
 #include <unistd.h> /* for unlink */
         "hyperscan", "", \
         RSPAMD_LOG_FUNC, \
         __VA_ARGS__)
-
+#define msg_err_hyperscan(...)   rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
+        "hyperscan", "", \
+        RSPAMD_LOG_FUNC, \
+        __VA_ARGS__)
 #define msg_debug_hyperscan(...)  rspamd_conditional_debug_fast (NULL, NULL, \
         rspamd_hyperscan_log_id, "hyperscan", "", \
         RSPAMD_LOG_FUNC, \
@@ -45,6 +49,12 @@ INIT_LOG_MODULE_PUBLIC(hyperscan)
 
 namespace rspamd::util {
 
+/*
+ * A singleton class that is responsible for deletion of the outdated hyperscan files
+ * One issue is that it must know about HS files in all workers, which is a problem
+ * TODO: we need to export hyperscan caches from all workers to a single place where
+ * we can clean them up (probably, to the main process)
+ */
 class hs_known_files_cache {
 private:
        // These fields are filled when we add new known cache files
@@ -136,7 +146,7 @@ public:
  * This is a higher level representation of the cached hyperscan file
  */
 struct hs_shared_database {
-       hs_database_t *db; /**< internal database (might be in a shared memory) */
+       hs_database_t *db = nullptr; /**< internal database (might be in a shared memory) */
        std::optional<raii_mmaped_file> maybe_map;
 
        ~hs_shared_database() {
@@ -148,6 +158,16 @@ struct hs_shared_database {
 
        explicit hs_shared_database(raii_mmaped_file &&map, hs_database_t *db) : db(db), maybe_map(std::move(map)) {}
        explicit hs_shared_database(hs_database_t *db) : db(db), maybe_map(std::nullopt) {}
+       hs_shared_database(const hs_shared_database &other) = delete;
+       hs_shared_database() = default;
+       hs_shared_database(hs_shared_database &&other) noexcept {
+               *this = std::move(other);
+       }
+       hs_shared_database& operator=(hs_shared_database &&other) noexcept {
+               std::swap(db, other.db);
+               std::swap(maybe_map, other.maybe_map);
+               return *this;
+       }
 };
 
 static auto
@@ -286,5 +306,56 @@ auto load_cached_hs_file(const char *fname) -> tl::expected<hs_shared_database,
 }
 } // namespace rspamd::util
 
+/* C API */
+
+#define CXX_DB_FROM_C(obj) (reinterpret_cast<rspamd::util::hs_shared_database *>(obj))
+#define C_DB_FROM_CXX(obj) (reinterpret_cast<rspamd_hyperscan_t *>(obj))
+
+rspamd_hyperscan_t *
+rspamd_maybe_load_hyperscan(const char *filename)
+{
+       auto maybe_db = rspamd::util::load_cached_hs_file(filename);
+
+       if (maybe_db.has_value()) {
+               auto *ndb = new rspamd::util::hs_shared_database;
+               *ndb = std::move(maybe_db.value());
+               return C_DB_FROM_CXX(ndb);
+       }
+       else {
+               auto error = maybe_db.error();
+
+               switch(error.category) {
+               case rspamd::util::error_category::CRITICAL:
+                       msg_err_hyperscan("critical error when trying to load cached hyperscan: %s",
+                               error.error_message.data());
+                       break;
+               case rspamd::util::error_category::IMPORTANT:
+                       msg_info_hyperscan("error when trying to load cached hyperscan: %s",
+                               error.error_message.data());
+                       break;
+               default:
+                       msg_debug_hyperscan("error when trying to load cached hyperscan: %s",
+                               error.error_message.data());
+                       break;
+               }
+       }
+
+       return nullptr;
+}
+
+hs_database_t*
+rspamd_hyperscan_get_database(rspamd_hyperscan_t *db)
+{
+       auto *real_db = CXX_DB_FROM_C(db);
+       return real_db->db;
+}
+
+void
+rspamd_hyperscan_free(rspamd_hyperscan_t *db)
+{
+       auto *real_db = CXX_DB_FROM_C(db);
+
+       delete real_db;
+}
 
 #endif // WITH_HYPERSCAN
\ No newline at end of file
diff --git a/src/libserver/hyperscan_tools.h b/src/libserver/hyperscan_tools.h
new file mode 100644 (file)
index 0000000..31139e6
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * Copyright 2022 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 "config.h"
+
+#ifndef RSPAMD_HYPERSCAN_TOOLS_H
+#define RSPAMD_HYPERSCAN_TOOLS_H
+
+#ifdef WITH_HYPERSCAN
+
+#include "hs.h"
+
+G_BEGIN_DECLS
+
+/**
+ * Opaque structure that represents hyperscan (maybe shared/cached database)
+ */
+typedef struct rspamd_hyperscan_s rspamd_hyperscan_t;
+
+/**
+ * Maybe load or mmap shared a hyperscan from a file
+ * @param filename
+ * @return cached database if available
+ */
+rspamd_hyperscan_t *rspamd_hyperscan_maybe_load(const char *filename);
+/**
+ * Get the internal database
+ * @param db
+ * @return
+ */
+hs_database_t* rspamd_hyperscan_get_database(rspamd_hyperscan_t *db);
+/**
+ * Free the database
+ * @param db
+ */
+void rspamd_hyperscan_free(rspamd_hyperscan_t *db);
+
+G_END_DECLS
+
+#endif
+
+#endif