diff --git a/modules/listDetector/src/CMakeLists.txt b/modules/listDetector/src/CMakeLists.txt index a19007d1..1a0f4f3f 100644 --- a/modules/listDetector/src/CMakeLists.txt +++ b/modules/listDetector/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_executable(listDetector main.cpp configParser.cpp + configReloader.cpp csvConfigParser.cpp ipAddressPrefix.cpp rule.cpp diff --git a/modules/listDetector/src/configReloader.cpp b/modules/listDetector/src/configReloader.cpp new file mode 100644 index 00000000..6c6673c9 --- /dev/null +++ b/modules/listDetector/src/configReloader.cpp @@ -0,0 +1,56 @@ +/** + * @file + * @author Alex Petras + * @brief Implementation of the ConfigReloader base class for checking for updates in the + * configuration and handling the reloading process + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "configReloader.hpp" + +#include +#include + +namespace ListDetector { + +ConfigReloader::ConfigReloader(char** m_argv) + : argv(m_argv) +{ +} + +std::time_t ConfigReloader::getLastModified(const std::string& filePath) +{ + struct stat file_stat; + if (stat(filePath.c_str(), &file_stat) == 0) { + return file_stat.st_mtime; + } + return -1; +} + +void ConfigReloader::checkReloadConfig(std::string filePath) +{ + auto previousTimestamp = getLastModified(filePath); + while (true) { + sleep(CHECK_INTERVAL); + auto currentTimestamp = getLastModified(filePath); + if (currentTimestamp != previousTimestamp && currentTimestamp != -1) { + previousTimestamp = currentTimestamp; + + this->restart(); + } + } +} + +void ConfigReloader::restart() +{ + execv(argv[0], argv); +} + +void ConfigReloader::startThread(std::string filePath) +{ + checkConfigThread = std::thread(&ConfigReloader::checkReloadConfig, this, filePath); + checkConfigThread.detach(); +} + +} // namespace ListDetector diff --git a/modules/listDetector/src/configReloader.hpp b/modules/listDetector/src/configReloader.hpp new file mode 100644 index 00000000..16c8b78b --- /dev/null +++ b/modules/listDetector/src/configReloader.hpp @@ -0,0 +1,67 @@ +/** + * @file + * @author Alex Petras + * @brief Declaration of the ConfigReloader base class for checking for updates in the configuration + * and handling the reloading process + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace ListDetector { + +/** + * @brief Base class for dealing with reloading the config. + * + * The `ConfigReloader` class provides functionality for checking for updates in the configuration + * and handling the reloading process. + */ +class ConfigReloader { +public: + ConfigReloader(char** m_argv); + + /** + * Start a thread that checks for updates in the configuration file. + * + * @param filePath Path to the configuration file to monitor. + */ + void startThread(std::string filePath); + + /** + * Get the last modified timestamp of a file. + * + * @param filePath Path to the configuration file. + * + * @return The last modified timestamp of the file, or -1 if an error occurred. + */ + static std::time_t getLastModified(const std::string& filePath); + + /** + * Check for changes in the configuration file and reload if the configuration file has changed. + * + * @param filePath Path to the configuration file to monitor. + */ + void checkReloadConfig(std::string filePath); + + /** + * Restart the current process with the same arguments effectively reloading the configuration. + */ + void restart(); + + /** + * @brief Interval in seconds to check for file changes. + */ + static const unsigned int CHECK_INTERVAL = 5; + +private: + char** argv; + std::thread checkConfigThread; +}; + +} // namespace ListDetector diff --git a/modules/listDetector/src/main.cpp b/modules/listDetector/src/main.cpp index 2ac53525..f0b3b739 100644 --- a/modules/listDetector/src/main.cpp +++ b/modules/listDetector/src/main.cpp @@ -12,6 +12,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "configReloader.hpp" #include "csvConfigParser.hpp" #include "listDetector.hpp" #include "logger/logger.hpp" @@ -103,6 +104,15 @@ static void processUnirecRecords( int main(int argc, char** argv) { + // make a copy of argv + char** argv_copy = new char*[argc + 1]; + for (int i = 0; i < argc; ++i) { + argv_copy[i] = new char[strlen(argv[i]) + 1]; + argv_copy[argc] = nullptr; + strcpy(argv_copy[i], argv[i]); + } + + ListDetector::ConfigReloader reloader(argv_copy); argparse::ArgumentParser program("listdetector"); Nm::loggerInit(); @@ -189,6 +199,7 @@ int main(int argc, char** argv) ListDetector::ListDetector listDetector(configParser.get(), mode); auto listDetectorTelemetryDirectory = telemetryRootDirectory->addDir("listdetector"); listDetector.setTelemetryDirectory(listDetectorTelemetryDirectory); + reloader.startThread(program.get("--rules")); processUnirecRecords(biInterface, listDetector);