diff --git a/CMakeLists.txt b/CMakeLists.txt index 10b6d0bc..786ff06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,18 @@ include_directories(${CMAKE_SOURCE_DIR}/libs/oatpp) include_directories(${CMAKE_SOURCE_DIR}/libs/oatpp-swagger) include_directories(${CMAKE_SOURCE_DIR}/libs/oatpp-websocket) +find_package(OpenSSL REQUIRED) +if(OpenSSL_FOUND) + message("-- Found OpenSSL ${OPENSSL_VERSION}: ${OPENSSL_LIBRARIES}") +else() + message("-- OpenSSL Not Found") +endif() + +find_package(CFITSIO REQUIRED) +find_package(ZLIB REQUIRED) +find_package(SQLite3 REQUIRED) +find_package(fmt REQUIRED) + ################################################################################# # # Subdirectories of Lithium @@ -118,6 +130,7 @@ add_subdirectory(modules) add_subdirectory(driver) add_subdirectory(${lithium_src_dir}/config) +add_subdirectory(${lithium_src_dir}/server) ################################################################################# # @@ -219,18 +232,6 @@ set(Lithium_module ${lithium_src_dir}/LithiumApp.cpp ) -find_package(OpenSSL REQUIRED) -if(OpenSSL_FOUND) - message("-- Found OpenSSL ${OPENSSL_VERSION}: ${OPENSSL_LIBRARIES}") -else() - message("-- OpenSSL Not Found") -endif() - -find_package(CFITSIO REQUIRED) -find_package(ZLIB REQUIRED) -find_package(SQLite3 REQUIRED) -find_package(fmt REQUIRED) - ################################################################################# # Main @@ -239,6 +240,7 @@ add_executable(lithium_server ${lithium_src_dir}/app.cpp) target_link_directories(lithium_server PUBLIC ${CMAKE_BINARY_DIR}/libs) target_link_libraries(lithium_server lithium_server-library) +target_link_libraries(lithium_server lithium_webserver) target_link_libraries(lithium_server oatpp-websocket oatpp-swagger oatpp-openssl oatpp-zlib oatpp) target_link_libraries(lithium_server loguru) target_link_libraries(lithium_server libzippp) diff --git a/launcher/#launcher.glade# b/launcher/#launcher.glade# deleted file mode 100644 index ef2bca54..00000000 --- a/launcher/#launcher.glade# +++ /dev/null @@ -1,437 +0,0 @@ - - - - - - - - - - - False - True - - - True - False - 介绍页 - - - progress - False - - - - - True - False - 内容页 - - - False - - - - - True - False - 确认页 - - - confirm - False - - - - - False - end - 6 - 6 - 6 - 6 - 6 - 6 - 6 - - - intro - False - - - - - False - 440 - 250 - assets\atom.png - - - True - False - vertical - top - - - True - False - - - True - False - 文件(_F) - True - - - True - False - - - gtk-new - True - False - True - True - - - - - gtk-open - True - False - True - True - - - - - gtk-save - True - False - True - True - - - - - gtk-save-as - True - False - True - True - - - - - True - False - - - - - gtk-quit - True - False - True - True - - - - - - - - - True - False - 编辑(_E) - True - - - True - False - - - gtk-cut - True - False - True - True - - - - - gtk-copy - True - False - True - True - - - - - gtk-paste - True - False - True - True - - - - - gtk-delete - True - False - True - True - - - - - - - - - True - False - 视图(_V) - True - - - - - True - False - 帮助(_H) - True - - - True - False - - - gtk-about - True - False - True - True - - - - - - - - - False - True - 0 - - - - - True - True - left - True - True - - - True - False - vertical - - - - - - - - - - - - - - True - False - Home - center - True - - - Home - True - True - True - - - - - True - False - vertical - - - - - - - - - - - - 1 - - - - - True - False - Installation - - - 1 - False - - - - - True - False - vertical - - - - - - - - - - - - 2 - - - - - True - False - Settings - - - 2 - False - - - - - True - True - 1 - - - - - True - True - - - False - True - 2 - - - - - - - False - About - True - help-about - dialog - Hello ElementAstro Launcher - 1.0.0 - https://github.com/ElementAstro - Official Github Repository - Max Qian - Max Qian - Max Qian - Max Qian - assets\atom.png - gpl-3-0 - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - - - - - False - Lithium Script Editor - True - True - edit-find-replace - dialog - lithium - Lithium Script Editor - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/launcher/assets/atom.png b/launcher/assets/atom.png deleted file mode 100644 index 6d32705b..00000000 Binary files a/launcher/assets/atom.png and /dev/null differ diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp deleted file mode 100644 index a8ea8e84..00000000 --- a/launcher/launcher.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/* - * launcher.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Lithium Server Launcher - -**************************************************/ - -#include "launcher.hpp" - -#include -#include -#include -#include - -#include "atom/system/crash.hpp" -#include "atom/log/loguru.hpp" - -ServerLauncher::ServerLauncher(const std::string &config_file_path, const std::string &DLOG_File_path) - : _config_file_path(config_file_path), _DLOG_File_path(DLOG_File_path) -{ - try - { - // 加载配置文件 - load_config(); - } - catch (const std::exception &e) - { - DLOG_F(ERROR, "Failed to initialize ServerLauncher: {}", e.what()); - throw; - } -} - -void ServerLauncher::run() -{ - try - { - // 检查服务器所需的资源文件是否存在 - if (!check_resources()) - { - DLOG_F(INFO, "Some resource files are missing, downloading now..."); - download_resources(); - } - - check_dependencies(); - - check_config_file(_config_file_path); - - // 启动服务器 - start_server(); - - // 读取服务器输出 - read_server_output(); - - // 发送停止命令给服务器,并等待服务器退出 - stop_server(); - - // 等待服务器退出 - wait_for_server_to_exit(); - - DLOG_F(INFO, "Server stopped."); - } - catch (const std::exception &e) - { - LOG_F(ERROR, "Error occurred in ServerLauncher::run(): {}", e.what()); - throw; - } -} - -void ServerLauncher::stop() -{ - // 设置请求停止服务器的标志 - _stop_requested = true; - - // 唤醒服务器条件变量,以便服务器检测到停止请求 - _server_cv.notify_all(); - - DLOG_F(INFO, "Stop command sent to server."); -} - -bool ServerLauncher::is_running() const -{ - return _server_running; -} - -void ServerLauncher::load_config() -{ - std::ifstream config_file(_config_file_path); - if (!config_file) - { - LOG_F(ERROR, "Failed to open config file: {}", _config_file_path); - throw std::runtime_error("Failed to open config file: " + _config_file_path); - } - try - { - config_file >> _config; - DLOG_F(INFO, "Config file loaded successfully."); - } - catch (const std::exception &e) - { - LOG_F(ERROR, "Error occurred when reading config file: {}", e.what()); - throw; - } -} - -bool ServerLauncher::check_resources() -{ - const auto &resources = _config["resources"]; - - for (const auto &res_file : resources) - { - const std::string filename = res_file; - - if (!fs::exists(filename)) - { - LOG_F(ERROR, "Resource file '{}' is missing.", filename); - return false; - } - - // 计算 SHA256 值 - std::string sha256_val; - if (!calculate_sha256(filename, sha256_val)) - { - LOG_F(ERROR, "Failed to calculate SHA256 value of '" << filename << "'." << std::endl; - return false; - } - - const std::string expected_sha256 = res_file["sha256"]; - if (sha256_val != expected_sha256) - { - LOG_F(ERROR, "SHA256 check failed for '" << filename << "'." << std::endl); - return false; - } - } - - DLOG_F(INFO, "All resource files are found."); - return true; -} - -void ServerLauncher::download_resources() -{ - DLOG_F(INFO, "Downloading missing resources..."); - - // 创建线程池 - ThreadPool pool(std::thread::hardware_concurrency()); - - // 创建任务列表 - std::vector> tasks; - - for (const auto &res_file : _config["resources"]) - { - // 发送 HTTP GET 请求下载文件 - const std::string url = _config["resource_server"].get() + "/" + res_file.get(); - - // 添加下载任务到线程池 - tasks.emplace_back(pool.enqueue([url, res_file, this] - { - try { - httplib::Client client(_config["resource_server"]); - auto res = client.Get(url.c_str()); - - if (!res) { - LOG_F(ERROR, "Failed to download resource: {}", res_file.get()); - return false; - } - - // 将下载的数据写入文件 - std::ofstream outfile(res_file); - outfile.write(res->body.c_str(), res->body.size()); - - DLOG_F(INFO,"Resource file '{}' downloaded.", res_file.get()); - return true; - } - catch (const std::exception &e) { - LOG_F(ERROR, "Error occurred when downloading resource '{}: {}" ,res_file.get(), << e.what()); - return false; - } })); - } - - // 等待所有任务完成 - for (auto &&task : tasks) - { - task.wait(); - } - - // 检查是否有任务失败 - for (auto &&task : tasks) - { - if (!task.get()) - { - LOG_F(ERROR, "Failed to download some resources."); - } - } - - DLOG_F(INFO, "Downloading finished."); -} - -bool check_process(const std::string &name) -{ -#ifdef _WIN32 - std::string command = "tasklist /FI \"IMAGENAME eq " + name + "\""; - - // 创建匿名管道 - SECURITY_ATTRIBUTES saAttr; - HANDLE hReadPipe, hWritePipe; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&hReadPipe, &hWritePipe, &saAttr, 0)) - { - return false; - } - - // 设置命令行输出重定向到管道 - STARTUPINFOA si; - PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(STARTUPINFOA)); - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - si.cb = sizeof(STARTUPINFOA); - si.hStdError = hWritePipe; - si.hStdOutput = hWritePipe; - si.dwFlags |= STARTF_USESTDHANDLES; - - // 启动命令行进程 - if (!CreateProcessA(NULL, const_cast(command.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) - { - CloseHandle(hReadPipe); - CloseHandle(hWritePipe); - return false; - } - - // 关闭写入端,避免读取阻塞 - CloseHandle(hWritePipe); - - // 读取命令行的输出结果 - const int BUFFER_SIZE = 4096; - char buffer[BUFFER_SIZE]; - DWORD bytesRead = 0; - std::string output; - - while (ReadFile(hReadPipe, buffer, BUFFER_SIZE - 1, &bytesRead, NULL)) - { - if (bytesRead == 0) - { - break; - } - - buffer[bytesRead] = '\0'; - output += buffer; - } - - // 关闭管道和进程句柄 - CloseHandle(hReadPipe); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - // 检查输出结果中是否包含进程名 - return (output.find(name) != std::string::npos); -#else - std::string command = "ps aux | grep -v grep | grep -q '" + name + "'"; - return (system(command.c_str()) == 0); -#endif -} - -bool ServerLauncher::check_dependencies() -{ - const std::vector dependencies = {"redis-server", "mysqld"}; - - for (const auto &dependency : dependencies) - { - if (!check_process(dependency)) - { - DLOG_F(INFO, "Dependency process '{}' is not running.", dependency); - return false; - } - } - DLOG_F(INFO, "All dependencies are ready."); - return true; -} - -bool ServerLauncher::check_config_file(const std::string &config_file) -{ - if (!std::filesystem::exists(config_file)) - { - LOG_F(ERROR, "Config file not found: {}", config_file); - return false; - } - - try - { - std::ifstream ifs(config_file); - json config = json::parse(ifs); - - // 检查 "port" 配置项是否存在 - if (config.find("port") == config.end()) - { - LOG_F(ERROR, "Config item 'port' not found in config file."); - return false; - } - - // 检查 "port" 配置项是否合法 - int port = config["port"].get(); - if (port < 0 || port > 65535) - { - LOG_F(ERROR, "Invalid 'port' configuration value: {}", port); - return false; - } - } - catch (const std::exception &e) - { - LOG_F(ERROR, "Failed to parse config file: {}", e.what()); - return false; - } - - return true; -} - -bool ServerLauncher::check_modules(const std::string &modules_dir, const json &module_list) -{ - if (!std::filesystem::exists(modules_dir)) - { - DLOG_F(INFO, "Modules directory not found: {}", modules_dir); - if (!std::filesystem::create_directory(modules_dir)) - { - LOG_F(ERROR, "Failed to create modules directory: {}", modules_dir); - return false; - } - } - - bool all_found = true; - for (const auto &module : module_list) - { - std::string module_path = modules_dir + "/" + module.get(); - if (!std::filesystem::exists(module_path)) - { - DLOG_F(ERROR, "Required module not found: {}", module_path); - all_found = false; - } - } - - return all_found; -} - -void ServerLauncher::start_server() -{ - DLOG_F(INFO, "Starting server..."); - - // 执行启动服务器的命令 - const std::string cmd = _config["server_command"]; - - _server_process = std::shared_ptr(_popen(cmd.c_str(), "r"), [](FILE *f) - { if (f) { _pclose(f); } }); - - if (!_server_process) - { - DLOG_F(ERROR, "Failed to execute server command: {}", cmd); - throw std::runtime_error("Failed to execute server command: " + cmd); - } - else - { - DLOG_F(INFO, "Server process started with command: {}", cmd); - std::cout << "Server process started with command: " << cmd << std::endl; - } - - // 创建一个线程来等待服务器启动 - _server_thread = std::jthread([&] - { - std::unique_lock lock(_server_mutex); - - while (!_stop_requested) { - // 在条件变量上等待,直到服务器启动 - _server_cv.wait(lock, [&] { return _server_running || _stop_requested; }); - } - - // 如果请求停止服务器,则发送停止命令给服务器 - if (_stop_requested) { - fprintf(_server_process.get(), "%c", _config["stop_command"]); - fflush(_server_process.get()); - DLOG_F(INFO,"Stop command sent to server process."); - } }); - - DLOG_F(INFO, "Server started."); -} - -void ServerLauncher::stop_server() -{ - DLOG_F(INFO, "Stopping server..."); - - // 发送停止命令给服务器 - fprintf(_server_process.get(), "%c", _config["stop_command"]); - fflush(_server_process.get()); - - DLOG_F(INFO, "Stop command sent to server process."); -} - -void ServerLauncher::wait_for_server_to_exit() -{ - // 等待服务器退出并获取返回值 - int status = -1; - _server_thread.join(); - _server_process.reset(); - _server_running = false; -} - -void ServerLauncher::read_server_output() -{ - // 定义正则表达式模板,匹配错误信息 - std::regex error_regex("ERROR: \\[(\\S+)\\] (.*)"); - - // 创建一个线程来读取服务器输出 - std::thread read_thread([&] - { - char buffer[1024]; - while (fgets(buffer, sizeof(buffer), _server_process.get())) { - std::cout << buffer; - - // 判断输出中是否包含错误信息 - std::string line(buffer); - std::smatch match; - - if (std::regex_search(line, match, error_regex)) { - // 匹配成功,提取错误类型和错误消息 - std::string error_type = match[1].str(); - std::string error_message = match[2].str(); - - // 根据错误类型处理错误 - if (error_type == "CRITICAL") { - // 生成冲突日志 - //Lithium::CrashReport::saveCrashLog(error_message); - } - else if (error_type == "WARNING") { - } - - // 读取结束,设置服务器运行标志为 false - _server_running = false; - - // 唤醒等待服务器退出的条件变量 - _server_cv.notify_all(); - return; - } - } - - // 读取结束,设置服务器运行标志为 false - _server_running = false; - - // 唤醒等待服务器退出的条件变量 - _server_cv.notify_all(); }); - - // 启动成功,设置服务器运行标志为 true - _server_running = true; - - // 让分离线程自行运行,不阻塞 run() 函数 - read_thread.detach(); -} - -bool ServerLauncher::calculate_sha256(const std::string &filename, std::string &sha256_val) -{ - // 打开文件 - std::ifstream file(filename, std::ios::binary); - if (!file) - { - return false; - } - - // 计算 SHA256 值 - EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); - - char buffer[1024]; - while (file.read(buffer, sizeof(buffer))) - { - EVP_DigestUpdate(mdctx, buffer, sizeof(buffer)); - } - - if (file.gcount() > 0) - { - EVP_DigestUpdate(mdctx, buffer, file.gcount()); - } - - unsigned char hash[EVP_MAX_MD_SIZE]; - unsigned int hash_len = 0; - EVP_DigestFinal_ex(mdctx, hash, &hash_len); - EVP_MD_CTX_free(mdctx); - - // 转换为十六进制字符串 - sha256_val.clear(); - for (unsigned int i = 0; i < hash_len; ++i) - { - char hex_str[3]; - sprintf(hex_str, "%02x", hash[i]); - sha256_val += hex_str; - } - - return true; -} - -void setupLogFile() -{ - std::filesystem::path logsFolder = std::filesystem::current_path() / "logs"; - if (!std::filesystem::exists(logsFolder)) - { - std::filesystem::create_directory(logsFolder); - } - auto now = std::chrono::system_clock::now(); - auto now_time_t = std::chrono::system_clock::to_time_t(now); - std::tm *local_time = std::localtime(&now_time_t); - char filename[100]; - std::strftime(filename, sizeof(filename), "%Y%m%d_%H%M%S.log", local_time); - std::filesystem::path logFilePath = logsFolder / filename; - loguru::add_file(logFilePath.string().c_str(), loguru::Append, loguru::Verbosity_MAX); - - loguru::set_fatal_handler([](const loguru::Message &message) - { Lithium::CrashReport::saveCrashLog(std::string(message.prefix) + message.message); }); -} - -int main(int argc, char *argv[]) -{ - std::vector args(argv + 1, argv + argc); - - if (args.size() < 2) - { - LOG_F(INFO, "Error: Missing arguments."); - LOG_F(INFO, "Usage: launcher "); - return 1; - } - - try - { - ServerLauncher launcher(args[0], args[1]); - launcher.run(); - - if (launcher.is_running()) - { - launcher.stop(); - } - } - catch (const std::exception &e) - { - // 输出错误信息并返回 - LOG_F(ERROR, "Error: {}", e.what()); - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/launcher/launcher.glade b/launcher/launcher.glade deleted file mode 100644 index ffd0f7f7..00000000 --- a/launcher/launcher.glade +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - False - True - - - True - False - 介绍页 - - - progress - False - - - - - True - False - 内容页 - - - False - - - - - True - False - 确认页 - - - confirm - False - - - - - False - end - 6 - 6 - 6 - 6 - 6 - 6 - 6 - - - intro - False - - - - - False - Hello ElementAstro Launcher - True - assets\atom.png - - - True - False - 0 - none - - - True - False - 12 - - - - - - - - True - False - __glade_unnamed_14 - - - - - - - False - About - True - help-about - dialog - Hello ElementAstro Launcher - 1.0.0 - https://github.com/ElementAstro - Official Github Repository - Max Qian - Max Qian - Max Qian - Max Qian - assets\atom.png - gpl-3-0 - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - - - - - False - Lithium Script Editor - True - True - edit-find-replace - dialog - lithium - Lithium Script Editor - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - diff --git a/launcher/launcher.glade~ b/launcher/launcher.glade~ deleted file mode 100644 index 9fbbf465..00000000 --- a/launcher/launcher.glade~ +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - False - True - - - True - False - 介绍页 - - - progress - False - - - - - True - False - 内容页 - - - False - - - - - True - False - 确认页 - - - confirm - False - - - - - False - end - 6 - 6 - 6 - 6 - 6 - 6 - 6 - - - intro - False - - - - - False - Hello ElementAstro Launcher - True - assets\atom.png - - - True - True - False - True - - - - - - - - False - About - True - help-about - dialog - Hello ElementAstro Launcher - 1.0.0 - https://github.com/ElementAstro - Official Github Repository - Max Qian - Max Qian - Max Qian - Max Qian - assets\atom.png - gpl-3-0 - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - - - - - False - Lithium Script Editor - True - True - edit-find-replace - dialog - lithium - Lithium Script Editor - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - diff --git a/launcher/launcher.hpp b/launcher/launcher.hpp deleted file mode 100644 index 18a1989d..00000000 --- a/launcher/launcher.hpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * launcher.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Lithium Server Launcher - -**************************************************/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atom/web/httplib.h" -#include "atom/type/json.hpp" - -using json = nlohmann::json; -namespace fs = std::filesystem; - -/** - * @brief 一个服务器启动器类,用于管理和启动服务器,包括资源下载、依赖检查、配置文件解析等操作。 - */ -class ServerLauncher -{ -public: - /** - * @brief 构造函数,初始化配置文件路径和日志文件路径,但不进行任何初始化操作。 - * @param config_file_path 服务器配置文件路径 - * @param DLOG_File_path 服务器日志文件路径 - */ - ServerLauncher(const std::string &config_file_path, const std::string &DLOG_File_path); - - /** - * @brief 启动服务器并开始监听连接请求。 - * - * 该函数首先检查运行所需的资源是否已下载和依赖项是否已安装,然后加载配置文件, - * 启动服务器进程并开始监听连接请求。启动过程中,服务器输出将定向至日志文件中。 - * - * 如果启动失败,则会发送警告邮件,并打印相关错误并退出程序。 - * - * 在 start_server() 函数内部,会创建一个新的线程来启动服务器进程,并等待子进程结束。 - */ - void run(); - - /** - * @brief 停止服务器进程和启动器。 - * - * 停止服务器进程前会发送停止信号以确保服务器进程优雅地退出。 - */ - void stop(); - - /** - * @brief 检查服务器是否正在运行。 - * @return 如果服务器正在运行,则返回 true,否则返回 false。 - */ - bool is_running() const; - - /** - * @brief 重定向服务器的标准输出和标准错误输出到日志文件中。 - * - * 该函数在服务器启动后应当被调用,以便将服务器输出记录到日志文件中。 - * - * @param DLOG_File_path 日志文件路径。 - */ - void redirect_stdout_stderr(const std::string &DLOG_File_path); - - /** - * @brief 计算指定文件的 SHA-256 哈希值。 - * @param filename 要计算哈希值的文件名。 - * @param sha256_val 输出参数,保存计算出的哈希值。 - * @return 如果文件存在并成功计算出哈希值,则返回 true,否则返回 false。 - */ - bool calculate_sha256(const std::string &filename, std::string &sha256_val); - -private: - /** - * @brief 加载配置文件,并检查其中的参数是否合法。 - * - * 该函数在 ServerLauncher::run() 函数中被调用,用于加载服务器的配置文件, - * 并检查其中的参数是否设置正确。如果参数检查失败,则会打印相关错误信息并退出程序。 - */ - void load_config(); - - /** - * @brief 检查启动器所需的资源是否已下载。 - * - * 该函数在 ServerLauncher::run() 函数中被调用,用于检查启动器所需的资源是否已下载。 - * 如果没有下载,则会提示用户开始下载,或自动下载并安装缺失的资源。 - * - * @return 如果所有必要的资源均已下载,则返回 true,否则返回 false。 - */ - bool check_resources(); - - /** - * @brief 下载启动器所需的资源。 - * - * 该函数在 ServerLauncher::check_resources() 函数中被调用,用于下载启动器所需的资源, - * 包括服务器程序、配置文件、数据文件等。下载完成后,将自动解压和安装这些资源。 - */ - void download_resources(); - - /** - * @brief 检查启动器所需的依赖项是否已安装。 - * - * 该函数在 ServerLauncher::run() 函数中被调用,用于检查启动器所需的依赖项是否已安装。 - * 如果某些依赖项未安装,则会提示用户开始安装,或自动下载并安装这些依赖项。 - * - * @return 如果所有必要的依赖项均已安装,则返回 true,否则返回 false。 - */ - bool check_dependencies(); - - /** - * @brief 检查服务器配置文件是否合法。 - * @param config_file 支持 JSON 或 YAML 格式的配置文件路径。 - * @return 如果配置文件有效,则返回 true,否则返回 false。 - */ - bool check_config_file(const std::string &config_file); - - /** - * @brief 检查已安装的模组是否符合要求。 - * - * 该函数在 ServerLauncher::run() 函数中被调用,用于检查已安装的模组是否符合要求, - * 如果存在不支持或过时的模组,则会提示用户更新或删除这些模组。 - * - * @param modules_dir 模组所在的目录路径。 - * @param module_list 从配置文件中读取的模组列表。 - * @return 如果所有必要的模组均已安装并且都是最新版,则返回 true,否则返回 false。 - */ - bool check_modules(const std::string &modules_dir, const json &module_list); - - /** - * @brief 启动服务器进程并等待其结束。 - * - * 该函数在 ServerLauncher::run() 函数中被调用,用于启动服务器进程并等待其结束。 - * 在启动服务器进程前,将检查服务器程序是否存在以及配置文件是否设置正确。 - * 若服务器程序不存在或配置文件设置错误,则会输出错误信息并退出程序。 - * - * 在函数内部,会创建一个新的线程来启动服务器进程,并等待子进程结束。如果服务器进程 - * 提前结束,则会发送警告邮件给管理员,并打印相关错误信息并退出程序。 - */ - void start_server(); - - /** - * @brief 发送停止信号给服务器进程,并等待其优雅地退出。 - * - * 该函数在 ServerLauncher::stop() 函数中被调用,用于发送停止信号给服务器进程, - * 并等待其在一段时间内优雅地退出。如果服务器未能在规定时间内退出,则会发送 - * kill 信号以强制结束服务器进程。 - */ - void stop_server(); - - /** - * @brief 等待服务器进程结束。 - * - * 该函数在 ServerLauncher::stop_server() 和 ServerLauncher::start_server() - * 函数中都可能被调用,用于等待服务器进程在子线程中结束。 - * - * 通过使用条件变量和互斥锁来控制等待流程,避免了死锁和忙等情况的出现。 - */ - void wait_for_server_to_exit(); - - /** - * @brief 读取服务器输出并将其记录到日志文件中。 - * - * 该函数在 ServerLauncher::start_server() 中被调用,用于读取服务器进程的标准输出 - * 并将其记录到日志文件中。该函数在一个独立的线程中运行,以避免阻塞其他操作。 - */ - void read_server_output(); - - std::string _config_file_path; ///< 配置文件路径 - std::string _DLOG_File_path; ///< 日志文件路径 - json _config; ///< 服务器配置文件 - std::atomic_bool _stop_requested = false; ///< 是否请求停止服务器的标志 - std::atomic_bool _server_running = false; ///< 是否正在运行服务器的标志 - std::jthread _server_thread; ///< 执行服务器进程的线程对象 - std::mutex _server_mutex; ///< 控制等待服务器进程结束的互斥锁 - std::condition_variable _server_cv; ///< 控制等待服务器进程结束的条件变量 - std::shared_ptr _server_process; ///< 指向服务器进程标准输出流的指针 -}; - -/** - * @brief 线程池 - */ -class ThreadPool { -public: - /** - * @brief 构造函数,初始化线程池大小和停止标志位。 - * - * 构造函数会创建 n_threads 个线程,并等待来自任务队列的任务分配。 - * - * @param n_threads 线程池大小 - */ - ThreadPool(std::size_t n_threads) - : stop(false) - { - for (std::size_t i = 0; i < n_threads; ++i) - { - threads.emplace_back([this] - { - for (;;) { - std::function task; - { - std::unique_lock lock(queue_mutex); - condition.wait(lock, [this] { return stop || !tasks.empty(); }); - if (stop && tasks.empty()) { - return; - } - task = std::move(tasks.front()); - tasks.pop(); - } - task(); - } }); - } - } - - /** - * @brief 析构函数,销毁所有线程并退出。 - * - * 析构函数会向任务队列中插入空任务,并等待所有线程完成该任务并退出。 - */ - ~ThreadPool() - { - { - std::unique_lock lock(queue_mutex); - stop = true; - } - condition.notify_all(); - for (std::thread &thread : threads) - { - thread.join(); - } - } - - /** - * @brief 将指定任务添加到任务队列中,并返回该任务的 future 对象。 - * - * 该函数用于将函数 f 和其参数 args 添加到任务队列中等待执行,并返回一 - * 个 std::future 对象,以便查询任务完成情况。当任务队列已满或线程池被 - * 停止时,将会抛出 std::runtime_error 异常。 - * - * @tparam F 函数类型 - * @tparam Args 参数类型 - * @param f 要执行的函数对象 - * @param args 函数参数 - * @return 返回一个 std::future 对象,用于查询任务完成情况 - */ - template - auto enqueue(F &&f, Args &&...args) -> std::future::type> - { - using return_type = typename std::result_of::type; - - auto task = std::make_shared>( - std::bind(std::forward(f), std::forward(args)...)); - - std::future res = task->get_future(); - { - std::unique_lock lock(queue_mutex); - - if (stop) - { - throw std::runtime_error("enqueue on stopped ThreadPool"); - } - - tasks.emplace([task] - { (*task)(); }); - } - condition.notify_one(); - return res; - } - -private: - std::vector threads; ///< 线程池中的线程列表 - std::queue> tasks; ///< 任务队列 - - std::mutex queue_mutex; ///< 任务队列的互斥锁 - std::condition_variable condition; ///< 任务队列的条件变量 - bool stop; ///< 停止标志位 -}; diff --git a/launcher/launcher.json b/launcher/launcher.json deleted file mode 100644 index de0b14a6..00000000 --- a/launcher/launcher.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server_command": "./server", - "stop_command": "q\n", - "resources": [ - "data.json", - "config.ini" - ], - "resource_server": "http://example.com" - } - \ No newline at end of file diff --git a/locale/lithium.pot b/locale/lithium.pot deleted file mode 100644 index 6876ffa8..00000000 --- a/locale/lithium.pot +++ /dev/null @@ -1,23 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR Max Qian -# This file is distributed under the same license as the package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: astro_air@126.com\n" -"POT-Creation-Date: 2024-02-06 17:50+0800\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: E:/msys64/home/Lithium/src/LithiumApp.cpp:551 -#, c++-format -msgid "Dispatched command {} with result: {}" -msgstr "" diff --git a/locale/po/en_US.UTF-8/lithium.po b/locale/po/en_US.UTF-8/lithium.po deleted file mode 100644 index 629b9775..00000000 --- a/locale/po/en_US.UTF-8/lithium.po +++ /dev/null @@ -1,4 +0,0 @@ -#: E:/msys64/home/Lithium/src/LithiumApp.cpp:551 -#, c++-format -msgid "Dispatched command {} with result: {}" -msgstr "" diff --git a/locale/po/es/lithium.po b/locale/po/es/lithium.po deleted file mode 100644 index 94c1bb2c..00000000 --- a/locale/po/es/lithium.po +++ /dev/null @@ -1,46 +0,0 @@ -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:232 -msgid "port the server running on" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:233 -msgid "host the server running on" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:234 -msgid "path to the config file" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:235 -msgid "path to the modules directory" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:236 -msgid "web panel" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:237 -msgid "path to log file" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:239 -msgid "Lithium Command Line Interface:" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:240 -msgid "End." -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:248 -#, c-format -msgid "Failed to parser command line : %s" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:269 -#, c-format -msgid "Command line server port : %d" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:275 -#, c-format -msgid "Set server port to %d" -msgstr "" diff --git a/locale/po/fr_FR/lithium.po b/locale/po/fr_FR/lithium.po deleted file mode 100644 index 94c1bb2c..00000000 --- a/locale/po/fr_FR/lithium.po +++ /dev/null @@ -1,46 +0,0 @@ -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:232 -msgid "port the server running on" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:233 -msgid "host the server running on" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:234 -msgid "path to the config file" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:235 -msgid "path to the modules directory" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:236 -msgid "web panel" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:237 -msgid "path to log file" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:239 -msgid "Lithium Command Line Interface:" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:240 -msgid "End." -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:248 -#, c-format -msgid "Failed to parser command line : %s" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:269 -#, c-format -msgid "Command line server port : %d" -msgstr "" - -#: E:/msys64/home/Qrm/OpenAPT/src/App.cpp:275 -#, c-format -msgid "Set server port to %d" -msgstr "" diff --git a/locale/po/zh-CN.UTF-8/lithium.po b/locale/po/zh-CN.UTF-8/lithium.po deleted file mode 100644 index bdf1643a..00000000 --- a/locale/po/zh-CN.UTF-8/lithium.po +++ /dev/null @@ -1,258 +0,0 @@ -# Language zh-CN translations for Lithium package. -# Copyright (C) 2023 Max Qian -# This file is distributed under the same license as the Lithium package. -# , 2023. -# -msgid "" -msgstr "" -"Project-Id-Version: Lithium \n" -"Report-Msgid-Bugs-To: astro_air@126.com\n" -"POT-Creation-Date: 2023-10-07 12:34+0000\n" -"PO-Revision-Date: 2023-10-07 12:36+0000\n" -"Last-Translator: \n" -"Language-Team: Language zh-CN\n" -"Language: zh-CN\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ASCII\n" -"Content-Transfer-Encoding: 8bit\n" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:63 -msgid "Failed to destroy ThreadManager: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:82 -msgid "Thread manager has stopped, cannot add new thread" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:100 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:122 -msgid "Unhandled exception in thread: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:128 -msgid "Added thread: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:133 -msgid "Failed to add thread {}: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:149 -msgid "All threads joined" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:153 -msgid "Failed to join all threads: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:163 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:180 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:194 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:205 -msgid "Thread {} not found" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:172 -msgid "Thread {} joined" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:184 -msgid "Failed to join thread {}: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:210 -msgid "Failed to check if thread {} is running: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:75 -msgid "Failed to create PowerShell process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:85 -msgid "Running command: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:98 -#: /workspaces/Lithium/src/modules/system/process.cpp:122 -#: /workspaces/Lithium/src/modules/system/process.cpp:143 -msgid "Failed to create process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:108 -#: /workspaces/Lithium/src/modules/system/process.cpp:153 -msgid "Process created: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:132 -msgid "Running script: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:170 -#: /workspaces/Lithium/src/modules/system/process.cpp:182 -msgid "Process terminated: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:174 -msgid "Failed to terminate process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:190 -#: /workspaces/Lithium/src/modules/system/process.cpp:246 -msgid "Process not found" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:205 -msgid "Process not found by name: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:212 -msgid "Currently running processes:" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:216 -msgid "{} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:261 -msgid "Process completed: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:265 -msgid "Failed to wait for process completion" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:271 -#, c-format -msgid "Process completed: %s (PID: %d)" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:276 -msgid "All processes completed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:287 -msgid "Failed to create process snapshot" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:328 -msgid "Failed to open /proc directory" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:357 -msgid "Failed to get process path" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:378 -msgid "Failed to get process info length" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:385 -msgid "Failed to allocate memory" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:391 -msgid "Failed to get process info" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:94 -msgid "CreateToolhelp32Snapshot failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:113 -msgid "Watching process with PID: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:124 -msgid "Process exited with code: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:133 -msgid "GetExitCodeProcess failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:143 -msgid "OpenProcess failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:170 -msgid "Process exited with status: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:179 -msgid "Process terminated by signal: {}" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:223 -msgid "port the server running on" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:224 -msgid "host the server running on" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:225 -msgid "path to the config file" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:226 -msgid "path to the modules directory" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:227 -msgid "web panel" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:228 -msgid "path to log file" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:230 -msgid "Lithium Command Line Interface:" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:231 -msgid "End." -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:239 -#, c-format -msgid "Failed to parser command line : %s" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:260 -#, c-format -msgid "Command line server port : %d" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:266 -#, c-format -msgid "Set server port to %d" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:67 -msgid "Failed to load Lithium App , error : {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:79 -msgid "Get config value: {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:85 -msgid "Set {} to {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:272 -msgid "Failed to run chai command : {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:290 -msgid "Failed to run chai multi command {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:303 -msgid "Failed to load chaiscript file {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:316 -msgid "Failed to run chai script {}" -msgstr "" diff --git a/locale/po/zh-CN/lithium.po b/locale/po/zh-CN/lithium.po deleted file mode 100644 index c863404b..00000000 --- a/locale/po/zh-CN/lithium.po +++ /dev/null @@ -1,258 +0,0 @@ -# Language zh-CN translations for Lithium package. -# Copyright (C) 2023 Max Qian -# This file is distributed under the same license as the Lithium package. -# , 2023. -# -msgid "" -msgstr "" -"Project-Id-Version: Lithium \n" -"Report-Msgid-Bugs-To: astro_air@126.com\n" -"POT-Creation-Date: 2023-10-07 12:34+0000\n" -"PO-Revision-Date: 2023-10-07 12:37+0000\n" -"Last-Translator: \n" -"Language-Team: Language zh-CN\n" -"Language: zh-CN\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ASCII\n" -"Content-Transfer-Encoding: 8bit\n" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:63 -msgid "Failed to destroy ThreadManager: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:82 -msgid "Thread manager has stopped, cannot add new thread" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:100 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:122 -msgid "Unhandled exception in thread: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:128 -msgid "Added thread: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:133 -msgid "Failed to add thread {}: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:149 -msgid "All threads joined" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:153 -msgid "Failed to join all threads: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:163 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:180 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:194 -#: /workspaces/Lithium/src/modules/thread/thread.cpp:205 -msgid "Thread {} not found" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:172 -msgid "Thread {} joined" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:184 -msgid "Failed to join thread {}: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/thread/thread.cpp:210 -msgid "Failed to check if thread {} is running: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:75 -msgid "Failed to create PowerShell process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:85 -msgid "Running command: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:98 -#: /workspaces/Lithium/src/modules/system/process.cpp:122 -#: /workspaces/Lithium/src/modules/system/process.cpp:143 -msgid "Failed to create process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:108 -#: /workspaces/Lithium/src/modules/system/process.cpp:153 -msgid "Process created: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:132 -msgid "Running script: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:170 -#: /workspaces/Lithium/src/modules/system/process.cpp:182 -msgid "Process terminated: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:174 -msgid "Failed to terminate process" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:190 -#: /workspaces/Lithium/src/modules/system/process.cpp:246 -msgid "Process not found" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:205 -msgid "Process not found by name: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:212 -msgid "Currently running processes:" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:216 -msgid "{} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:261 -msgid "Process completed: {} (PID: {})" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:265 -msgid "Failed to wait for process completion" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:271 -#, c-format -msgid "Process completed: %s (PID: %d)" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:276 -msgid "All processes completed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:287 -msgid "Failed to create process snapshot" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:328 -msgid "Failed to open /proc directory" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:357 -msgid "Failed to get process path" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:378 -msgid "Failed to get process info length" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:385 -msgid "Failed to allocate memory" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/process.cpp:391 -msgid "Failed to get process info" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:94 -msgid "CreateToolhelp32Snapshot failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:113 -msgid "Watching process with PID: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:124 -msgid "Process exited with code: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:133 -msgid "GetExitCodeProcess failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:143 -msgid "OpenProcess failed." -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:170 -msgid "Process exited with status: {}" -msgstr "" - -#: /workspaces/Lithium/src/modules/system/pid.cpp:179 -msgid "Process terminated by signal: {}" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:223 -msgid "port the server running on" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:224 -msgid "host the server running on" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:225 -msgid "path to the config file" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:226 -msgid "path to the modules directory" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:227 -msgid "web panel" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:228 -msgid "path to log file" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:230 -msgid "Lithium Command Line Interface:" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:231 -msgid "End." -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:239 -#, c-format -msgid "Failed to parser command line : %s" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:260 -#, c-format -msgid "Command line server port : %d" -msgstr "" - -#: /workspaces/Lithium/src/App.cpp:266 -#, c-format -msgid "Set server port to %d" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:67 -msgid "Failed to load Lithium App , error : {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:79 -msgid "Get config value: {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:85 -msgid "Set {} to {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:272 -msgid "Failed to run chai command : {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:290 -msgid "Failed to run chai multi command {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:303 -msgid "Failed to load chaiscript file {}" -msgstr "" - -#: /workspaces/Lithium/src/LithiumApp.cpp:316 -msgid "Failed to run chai script {}" -msgstr "" diff --git a/src/App.cpp b/src/App.cpp index 3e4cc42b..f83df684 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -14,6 +14,8 @@ Description: Main Entry #include "lithiumapp.hpp" +#include "preload.hpp" + #include "atom/log/loguru.hpp" #include "atom/server/global_ptr.hpp" #include "atom/system/crash.hpp" @@ -26,9 +28,7 @@ Description: Main Entry using namespace Lithium::Terminal; #endif -#if ENABLE_WEBPANEL #include "server/App.hpp" -#endif #include #include @@ -180,9 +180,7 @@ int main(int argc, char *argv[]) { LOG_F(ERROR, "Invalid args format! Error: {}", e.what()); } -#if ENABLE_WEBPANEL - runServer(argc, argv); -#endif + runServer(); return 0; } \ No newline at end of file diff --git a/src/atom/algorithm/CMakeLists.txt b/src/atom/algorithm/CMakeLists.txt index 6165958f..ee460e74 100644 --- a/src/atom/algorithm/CMakeLists.txt +++ b/src/atom/algorithm/CMakeLists.txt @@ -18,6 +18,7 @@ set(${PROJECT_NAME}_SOURCES huffman.cpp math.cpp md5.cpp + mhash.cpp ) # Headers @@ -30,6 +31,7 @@ set(${PROJECT_NAME}_HEADERS huffman.hpp math.hpp md5.hpp + mhash.hpp ) # Build Object Library diff --git a/src/atom/algorithm/hash.hpp b/src/atom/algorithm/hash.hpp index 932b33e1..a8f9a2d5 100644 --- a/src/atom/algorithm/hash.hpp +++ b/src/atom/algorithm/hash.hpp @@ -239,6 +239,29 @@ inline std::uint32_t jenkins_one_at_a_time_hash(const std::string& s) noexcept { return jenkins_one_at_a_time_hash(std::string_view{s}); } +inline uint32_t quickHash(const char* str) { + if (!str) + return 0; + + unsigned int h = 0; + for (; *str; str++) { + h = 31 * h + *str; + } + return h; +} + +inline uint32_t quickHash(const void* tmp, uint32_t size) { + if (!tmp) + return 0; + + const char* str = (const char*)tmp; + unsigned int h = 0; + for (uint32_t i = 0; i < size; ++i, ++str) { + h = 31 * h + *str; + } + return h; +} + } // namespace Atom::Algorithm #endif diff --git a/src/atom/utils/hash_util.cpp b/src/atom/algorithm/mhash.cpp similarity index 61% rename from src/atom/utils/hash_util.cpp rename to src/atom/algorithm/mhash.cpp index a1779714..4315b969 100644 --- a/src/atom/utils/hash_util.cpp +++ b/src/atom/algorithm/mhash.cpp @@ -1,5 +1,5 @@ /* - * hash_util.cpp + * mhash.cpp * * Copyright (C) 2023-2024 Max Qian */ @@ -12,7 +12,7 @@ Description: Implementation of murmur3 hash and quick hash **************************************************/ -#include "hash_util.hpp" +#include "mhash.hpp" #include #include @@ -91,29 +91,6 @@ uint32_t murmur3Hash(const void *data, const uint32_t &size, return fmix32(h ^ len); } -uint32_t quickHash(const char *str) { - if (!str) - return 0; - - unsigned int h = 0; - for (; *str; str++) { - h = 31 * h + *str; - } - return h; -} - -uint32_t quickHash(const void *tmp, uint32_t size) { - if (!tmp) - return 0; - - const char *str = (const char *)tmp; - unsigned int h = 0; - for (uint32_t i = 0; i < size; ++i, ++str) { - h = 31 * h + *str; - } - return h; -} - uint64_t murmur3Hash64(const void *str, const uint32_t &size, const uint32_t &seed = 1060627423, const uint32_t &seed2 = 1050126127) { @@ -126,71 +103,7 @@ uint64_t murmur3Hash64(const char *str, const uint32_t &seed = 1060627423, return (((uint64_t)murmur3Hash(str, seed)) << 32 | murmur3Hash(str, seed2)); } -std::string base64decode(const std::string &src) { - std::string result; - result.resize(src.size() * 3 / 4); - char *writeBuf = &result[0]; - - const char *ptr = src.c_str(); - const char *end = ptr + src.size(); - - while (ptr < end) { - int i = 0; - int padding = 0; - int packed = 0; - for (; i < 4 && ptr < end; ++i, ++ptr) { - if (*ptr == '=') { - ++padding; - packed <<= 6; - continue; - } - - // padding with "=" only - if (padding > 0) { - return ""; - } - - int val = 0; - if (*ptr >= 'A' && *ptr <= 'Z') { - val = *ptr - 'A'; - } else if (*ptr >= 'a' && *ptr <= 'z') { - val = *ptr - 'a' + 26; - } else if (*ptr >= '0' && *ptr <= '9') { - val = *ptr - '0' + 52; - } else if (*ptr == '+') { - val = 62; - } else if (*ptr == '/') { - val = 63; - } else { - return ""; // invalid character - } - - packed = (packed << 6) | val; - } - if (i != 4) { - return ""; - } - if (padding > 0 && ptr != end) { - return ""; - } - if (padding > 2) { - return ""; - } - - *writeBuf++ = (char)((packed >> 16) & 0xff); - if (padding != 2) { - *writeBuf++ = (char)((packed >> 8) & 0xff); - } - if (padding == 0) { - *writeBuf++ = (char)(packed & 0xff); - } - } - - result.resize(writeBuf - result.c_str()); - return result; -} - -void hexstring_from_data(const void *data, size_t len, char *output) { +void hexstringFromData(const void *data, size_t len, char *output) { const unsigned char *buf = (const unsigned char *)data; size_t i, j; for (i = j = 0; i < len; ++i) { @@ -204,25 +117,25 @@ void hexstring_from_data(const void *data, size_t len, char *output) { } } -std::string hexstring_from_data(const char *data, size_t len) { +std::string hexstringFromData(const char *data, size_t len) { if (len == 0) { return std::string(); } std::string result; result.resize(len * 2); - hexstring_from_data(data, len, &result[0]); + hexstringFromData(data, len, &result[0]); return result; } -std::string hexstring_from_data(const std::string &data) { - return hexstring_from_data(data.c_str(), data.size()); +std::string hexstringFromData(const std::string &data) { + return hexstringFromData(data.c_str(), data.size()); } -void data_from_hexstring(const char *hexstring, size_t length, void *output) { +void dataFromHexstring(const char *hexstring, size_t length, void *output) { unsigned char *buf = (unsigned char *)output; unsigned char byte; if (length % 2 != 0) { - throw std::invalid_argument("data_from_hexstring length % 2 != 0"); + throw std::invalid_argument("dataFromHexstring length % 2 != 0"); } for (size_t i = 0; i < length; ++i) { switch (hexstring[i]) { @@ -256,7 +169,7 @@ void data_from_hexstring(const char *hexstring, size_t length, void *output) { break; default: throw std::invalid_argument( - "data_from_hexstring invalid hexstring"); + "dataFromHexstring invalid hexstring"); } ++i; switch (hexstring[i]) { @@ -290,27 +203,27 @@ void data_from_hexstring(const char *hexstring, size_t length, void *output) { break; default: throw std::invalid_argument( - "data_from_hexstring invalid hexstring"); + "dataFromHexstring invalid hexstring"); } *buf++ = byte; } } -std::string data_from_hexstring(const char *hexstring, size_t length) { +std::string dataFromHexstring(const char *hexstring, size_t length) { if (length % 2 != 0) { - throw std::invalid_argument("data_from_hexstring length % 2 != 0"); + throw std::invalid_argument("dataFromHexstring length % 2 != 0"); } if (length == 0) { return std::string(); } std::string result; result.resize(length / 2); - data_from_hexstring(hexstring, length, &result[0]); + dataFromHexstring(hexstring, length, &result[0]); return result; } -std::string data_from_hexstring(const std::string &hexstring) { - return data_from_hexstring(hexstring.c_str(), hexstring.size()); +std::string dataFromHexstring(const std::string &hexstring) { + return dataFromHexstring(hexstring.c_str(), hexstring.size()); } } // namespace Atom::Utils diff --git a/src/atom/utils/hash_util.hpp b/src/atom/algorithm/mhash.hpp similarity index 80% rename from src/atom/utils/hash_util.hpp rename to src/atom/algorithm/mhash.hpp index 0954d213..39f38312 100644 --- a/src/atom/utils/hash_util.hpp +++ b/src/atom/algorithm/mhash.hpp @@ -66,23 +66,6 @@ namespace Atom::Utils { const uint32_t &seed, const uint32_t &seed2); -/** - * @brief Calculates the quick hash value for a given string. - * - * @param str The input string. - * @return uint32_t The calculated hash value. - */ -[[nodiscard]] uint32_t quickHash(const char *str); - -/** - * @brief Calculates the quick hash value for a given data buffer. - * - * @param str The input data buffer. - * @param size The size of the data buffer. - * @return uint32_t The calculated hash value. - */ -[[nodiscard]] uint32_t quickHash(const void *str, uint32_t size); - /** * @brief Converts binary data to a hexadecimal string representation. * @@ -91,7 +74,7 @@ namespace Atom::Utils { * @param output The output buffer to store the hexadecimal string (length must * be len * 2). */ -void hexstring_from_data(const void *data, size_t len, char *output); +void hexstringFromData(const void *data, size_t len, char *output); /** * @brief Converts binary data to a hexadecimal string representation. @@ -100,7 +83,7 @@ void hexstring_from_data(const void *data, size_t len, char *output); * @param len The length of the data buffer. * @return std::string The hexadecimal string representation. */ -[[nodiscard]] std::string hexstring_from_data(const void *data, size_t len); +[[nodiscard]] std::string hexstringFromData(const void *data, size_t len); /** * @brief Converts a string to a hexadecimal string representation. @@ -108,7 +91,7 @@ void hexstring_from_data(const void *data, size_t len, char *output); * @param data The input string. * @return std::string The hexadecimal string representation. */ -[[nodiscard]] std::string hexstring_from_data(const std::string &data); +[[nodiscard]] std::string hexstringFromData(const std::string &data); /** * @brief Converts a hexadecimal string representation to binary data. @@ -118,7 +101,7 @@ void hexstring_from_data(const void *data, size_t len, char *output); * @param output The output buffer to store the binary data (length must be * length / 2). */ -void data_from_hexstring(const char *hexstring, size_t length, void *output); +void dataFromHexstring(const char *hexstring, size_t length, void *output); /** * @brief Converts a hexadecimal string representation to binary data. @@ -129,7 +112,7 @@ void data_from_hexstring(const char *hexstring, size_t length, void *output); * @throw std::invalid_argument If the input hexstring is not a valid * hexadecimal string. */ -[[nodiscard]] std::string data_from_hexstring(const char *hexstring, +[[nodiscard]] std::string dataFromHexstring(const char *hexstring, size_t length); /** @@ -140,7 +123,7 @@ void data_from_hexstring(const char *hexstring, size_t length, void *output); * @throw std::invalid_argument If the input hexstring is not a valid * hexadecimal string. */ -[[nodiscard]] std::string data_from_hexstring(const std::string &data); +[[nodiscard]] std::string dataFromHexstring(const std::string &data); } // namespace Atom::Utils #endif \ No newline at end of file diff --git a/src/atom/async/pool.hpp b/src/atom/async/pool.hpp new file mode 100644 index 00000000..9c04dcb0 --- /dev/null +++ b/src/atom/async/pool.hpp @@ -0,0 +1,122 @@ +/* + * pool.hpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2024-2-13 + +Description: A very simple thread pool for preload + +**************************************************/ + +#ifndef ATOM_ASYNC_POOL_HPP +#define ATOM_ASYNC_POOL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Atom::Async { +/** + * @brief 线程池 + */ +class ThreadPool { +public: + /** + * @brief 构造函数,初始化线程池大小和停止标志位。 + * + * 构造函数会创建 n_threads 个线程,并等待来自任务队列的任务分配。 + * + * @param n_threads 线程池大小 + */ + ThreadPool(std::size_t n_threads) : stop(false) { + for (std::size_t i = 0; i < n_threads; ++i) { + threads.emplace_back([this] { + for (;;) { + std::function task; + { + std::unique_lock lock(queue_mutex); + condition.wait( + lock, [this] { return stop || !tasks.empty(); }); + if (stop && tasks.empty()) { + return; + } + task = std::move(tasks.front()); + tasks.pop(); + } + task(); + } + }); + } + } + + /** + * @brief 析构函数,销毁所有线程并退出。 + * + * 析构函数会向任务队列中插入空任务,并等待所有线程完成该任务并退出。 + */ + ~ThreadPool() { + { + std::unique_lock lock(queue_mutex); + stop = true; + } + condition.notify_all(); + for (std::thread &thread : threads) { + thread.join(); + } + } + + /** + * @brief 将指定任务添加到任务队列中,并返回该任务的 future 对象。 + * + * 该函数用于将函数 f 和其参数 args 添加到任务队列中等待执行,并返回一 + * 个 std::future 对象,以便查询任务完成情况。当任务队列已满或线程池被 + * 停止时,将会抛出 std::runtime_error 异常。 + * + * @tparam F 函数类型 + * @tparam Args 参数类型 + * @param f 要执行的函数对象 + * @param args 函数参数 + * @return 返回一个 std::future 对象,用于查询任务完成情况 + */ + template + auto enqueue(F &&f, Args &&...args) + -> std::future::type> { + using return_type = typename std::result_of::type; + + auto task = std::make_shared>( + std::bind(std::forward(f), std::forward(args)...)); + + std::future res = task->get_future(); + { + std::unique_lock lock(queue_mutex); + + if (stop) { + throw std::runtime_error("enqueue on stopped ThreadPool"); + } + + tasks.emplace([task] { (*task)(); }); + } + condition.notify_one(); + return res; + } + +private: + std::vector threads; ///< 线程池中的线程列表 + std::queue> tasks; ///< 任务队列 + + std::mutex queue_mutex; ///< 任务队列的互斥锁 + std::condition_variable condition; ///< 任务队列的条件变量 + bool stop; ///< 停止标志位 +}; +} // namespace Atom::Async + +#endif \ No newline at end of file diff --git a/src/atom/utils/CMakeLists.txt b/src/atom/utils/CMakeLists.txt index 0b76c16b..969743e0 100644 --- a/src/atom/utils/CMakeLists.txt +++ b/src/atom/utils/CMakeLists.txt @@ -13,7 +13,6 @@ project(atom-utils C CXX) set(${PROJECT_NAME}_SOURCES aes.cpp env.cpp - hash_util.cpp random.cpp string.cpp stopwatcher.cpp @@ -26,7 +25,6 @@ set(${PROJECT_NAME}_SOURCES set(${PROJECT_NAME}_HEADERS aes.hpp env.hpp - hash_util.hpp random.hpp refl.hpp string.hpp diff --git a/src/atom/utils/aes.cpp b/src/atom/utils/aes.cpp index b9a3c838..274adea6 100644 --- a/src/atom/utils/aes.cpp +++ b/src/atom/utils/aes.cpp @@ -14,29 +14,33 @@ Description: Simple implementation of AES encryption #include "aes.hpp" +#include +#include +#include + #include #include #include -#include -#include + +#include "atom/io/io.hpp" +#include "atom/log/loguru.hpp" const int AES_BLOCK_SIZE = 16; namespace Atom::Utils { -std::string encryptAES(const std::string &plaintext, const std::string &key) { +std::string encryptAES(std::string_view plaintext, std::string_view key) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, - reinterpret_cast(key.c_str()), + reinterpret_cast(key.data()), nullptr); int c_len = plaintext.length() + AES_BLOCK_SIZE; unsigned char *ciphertext = new unsigned char[c_len]; int len; - EVP_EncryptUpdate( - ctx, ciphertext, &len, - reinterpret_cast(plaintext.c_str()), - plaintext.length()); + EVP_EncryptUpdate(ctx, ciphertext, &len, + reinterpret_cast(plaintext.data()), + plaintext.length()); int ciphertext_len = len; EVP_EncryptFinal_ex(ctx, ciphertext + len, &len); @@ -50,10 +54,10 @@ std::string encryptAES(const std::string &plaintext, const std::string &key) { return result; } -std::string decryptAES(const std::string &ciphertext, const std::string &key) { +std::string decryptAES(std::string_view ciphertext, std::string_view key) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, - reinterpret_cast(key.c_str()), + reinterpret_cast(key.data()), nullptr); int p_len = ciphertext.length() + AES_BLOCK_SIZE; @@ -62,7 +66,7 @@ std::string decryptAES(const std::string &ciphertext, const std::string &key) { int len; EVP_DecryptUpdate( ctx, plaintext, &len, - reinterpret_cast(ciphertext.c_str()), + reinterpret_cast(ciphertext.data()), ciphertext.length()); int plaintext_len = len; @@ -77,7 +81,7 @@ std::string decryptAES(const std::string &ciphertext, const std::string &key) { return result; } -std::string compress(const std::string &data) { +std::string compress(std::string_view data) { z_stream zs; memset(&zs, 0, sizeof(zs)); @@ -107,7 +111,7 @@ std::string compress(const std::string &data) { return compressed; } -std::string decompress(const std::string &data) { +std::string decompress(std::string_view data) { z_stream zs; memset(&zs, 0, sizeof(zs)); @@ -136,4 +140,42 @@ std::string decompress(const std::string &data) { return decompressed; } + +std::string calculateSha256(std::string_view filename) { + if (!Atom::IO::isFileExists(std::string(filename))) { + LOG_F(ERROR, "File not exist: {}", filename); + return ""; + } + std::ifstream file(filename.data(), std::ios::binary); + if (!file || !file.good()) { + return ""; + } + + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); + + char buffer[1024]; + while (file.read(buffer, sizeof(buffer))) { + EVP_DigestUpdate(mdctx, buffer, sizeof(buffer)); + } + + if (file.gcount() > 0) { + EVP_DigestUpdate(mdctx, buffer, file.gcount()); + } + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = 0; + EVP_DigestFinal_ex(mdctx, hash, &hash_len); + EVP_MD_CTX_free(mdctx); + + // 转换为十六进制字符串 + std::string sha256_val; + for (unsigned int i = 0; i < hash_len; ++i) { + char hex_str[3]; + sprintf(hex_str, "%02x", hash[i]); + sha256_val += hex_str; + } + + return sha256_val; +} } // namespace Atom::Utils diff --git a/src/atom/utils/aes.hpp b/src/atom/utils/aes.hpp index 20063973..4489f632 100644 --- a/src/atom/utils/aes.hpp +++ b/src/atom/utils/aes.hpp @@ -25,8 +25,8 @@ namespace Atom::Utils { * @param key 加密密钥 * @return 加密后的密文数据 */ -[[maybe_unused]] [[nodiscard]] std::string encryptAES( - const std::string &plaintext, const std::string &key); +[[nodiscard]] std::string encryptAES( + std::string_view plaintext, std::string_view key); /** * @brief 使用AES算法对输入的密文进行解密。 @@ -35,8 +35,8 @@ namespace Atom::Utils { * @param key 解密密钥 * @return 解密后的明文数据 */ -[[maybe_unused]] [[nodiscard]] std::string decryptAES( - const std::string &ciphertext, const std::string &key); +[[nodiscard]] std::string decryptAES( + std::string_view ciphertext, std::string_view key); /** * @brief 使用Zlib库对输入的数据进行压缩。 @@ -44,7 +44,7 @@ namespace Atom::Utils { * @param data 待压缩的数据 * @return 压缩后的数据 */ -[[maybe_unused]] [[nodiscard]] std::string compress(const std::string &data); +[[nodiscard]] std::string compress(std::string_view data); /** * @brief 使用Zlib库对输入的数据进行解压。 @@ -52,7 +52,9 @@ namespace Atom::Utils { * @param data 待解压的数据 * @return 解压后的数据 */ -[[maybe_unused]] [[nodiscard]] std::string decompress(const std::string &data); +[[nodiscard]] std::string decompress(std::string_view data); + +[[nodiscard]]std::string calculateSha256(std::string_view filename); } // namespace Atom::Utils #endif diff --git a/src/atom/utils/switch.hpp b/src/atom/utils/switch.hpp index 25edae2b..f3e9ae43 100644 --- a/src/atom/utils/switch.hpp +++ b/src/atom/utils/switch.hpp @@ -43,6 +43,8 @@ class StringSwitch : public NonCopyable { using Func = std::function; using DefaultFunc = std::optional; + StringSwitch() = default; + // Register a case with the given string and function void registerCase(const std::string &str, Func func) { if (cases_.find(str) != cases_.end()) { diff --git a/src/preload.cpp b/src/preload.cpp new file mode 100644 index 00000000..52150710 --- /dev/null +++ b/src/preload.cpp @@ -0,0 +1,89 @@ +#include "preload.hpp" + +#include + +#include "atom/async/pool.hpp" +#include "atom/io/io.hpp" +#include "atom/log/loguru.hpp" +#include "atom/utils/aes.hpp" +#include "atom/utils/string.hpp" +#include "atom/web/httpclient.hpp" + +#include "utils/resource.hpp" + +bool checkResources() { + for (auto &[key, value] : resource::LITHIUM_RESOURCES) { + if (!Atom::IO::isFileExists(key.data())) { + LOG_F(ERROR, "Resource file '{}' is missing.", key); + return false; + } + auto sha256_val = Atom::Utils::calculateSha256(key); + if (!sha256_val.empty()) { + LOG_F(ERROR, "Failed to calculate SHA256 value of '{}'.", key); + value.second = true; + continue; + } + auto expected_sha256 = value.first; + if (sha256_val != expected_sha256) { + LOG_F(ERROR, "SHA256 check failed for '{}'", key); + return false; + } + value.second = true; + } + + DLOG_F(INFO, "All resource files are found."); + return true; +} + +void downloadResources() { + DLOG_F(INFO, "Downloading missing resources..."); + + // 创建线程池 + Atom::Async::ThreadPool pool(std::thread::hardware_concurrency()); + + // 创建任务列表 + std::vector> tasks; + + for (auto &[key, value] : resource::LITHIUM_RESOURCES) { + // 发送 HTTP GET 请求下载文件 + const auto url = Atom::Utils::joinStrings( + {resource::LITHIUM_RESOURCE_SERVER, key}, "/"); + + // 添加下载任务到线程池 + tasks.emplace_back(pool.enqueue([url] { + try { + auto client = Atom::Web::HttpClient( + resource::LITHIUM_RESOURCE_SERVER, 443, true); + json res_body; + std::string err; + auto res = client.sendGetRequest(url, {}, res_body, err); + + if (!res) { + LOG_F(ERROR, "Failed to download resource: {}", url); + return false; + } + + // 将下载的数据写入文件 + std::ofstream outfile( + std::string(Atom::Utils::splitString(url, '/').back())); + outfile.write(res_body.dump().c_str(), res_body.dump().size()); + + DLOG_F(INFO, "Resource file '{}' downloaded.", url); + return true; + } catch (const std::exception &e) { + LOG_F(ERROR, "Error occurred when downloading resource '{}: {}", + url, e.what()); + return false; + } + })); + } + for (auto &&task : tasks) { + task.wait(); + } + for (auto &&task : tasks) { + if (!task.get()) { + LOG_F(ERROR, "Failed to download some resources."); + } + } + DLOG_F(INFO, "Downloading finished."); +} \ No newline at end of file diff --git a/src/preload.hpp b/src/preload.hpp new file mode 100644 index 00000000..b734dd58 --- /dev/null +++ b/src/preload.hpp @@ -0,0 +1,7 @@ +#ifndef LITHIUM_PRELOAD_HPP +#define LITHIUM_PRELOAD_HPP + +bool checkResources(); +void downloadResources(); + +#endif diff --git a/src/server/App.cpp b/src/server/App.cpp index a32c4923..571e6d80 100644 --- a/src/server/App.cpp +++ b/src/server/App.cpp @@ -22,9 +22,9 @@ Description: Main #include -void run(const oatpp::base::CommandLineArguments& args) { +void run() { /* Register Components in scope of run() method */ - AppComponent components(args); + AppComponent components; Runner runner(OATPP_GET_COMPONENT(oatpp::Object), OATPP_GET_COMPONENT(std::shared_ptr)); @@ -34,10 +34,10 @@ void run(const oatpp::base::CommandLineArguments& args) { runner.join(); } -int runServer(int argc, const char* argv[]) { +int runServer() { oatpp::base::Environment::init(); - run(oatpp::base::CommandLineArguments(argc, argv)); + run(); oatpp::base::Environment::destroy(); diff --git a/src/server/App.hpp b/src/server/App.hpp index 69fee2f3..a2231778 100644 --- a/src/server/App.hpp +++ b/src/server/App.hpp @@ -1,6 +1,6 @@ #ifndef LITHIUM_SERVER_APP_HPP #define LITHIUM_SERVER_APP_HPP -int runServer(int argc, const char* argv[]); +int runServer(); #endif diff --git a/src/server/AppComponent.hpp b/src/server/AppComponent.hpp index b43228f9..39d5c4ab 100644 --- a/src/server/AppComponent.hpp +++ b/src/server/AppComponent.hpp @@ -15,8 +15,6 @@ Description: App Components #ifndef LITHIUM_APP_COMPONENT_HPP #define LITHIUM_APP_COMPONENT_HPP -#include "config.h" - #include "config/Config.hpp" #include "config/HubsConfig.hpp" @@ -28,7 +26,6 @@ Description: App Components #include "ErrorHandler.hpp" -#include "oatpp/core/base/CommandLineArguments.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/core/utils/ConversionUtils.hpp" #include "oatpp/network/monitor/ConnectionInactivityChecker.hpp" @@ -63,42 +60,45 @@ Description: App Components #include /** - * Class which creates and holds Application components and registers components in oatpp::base::Environment - * Order of components initialization is from top to bottom + * Class which creates and holds Application components and registers + * components in oatpp::base::Environment Order of components initialization is + * from top to bottom */ class AppComponent { -private: - oatpp::base::CommandLineArguments m_cmdArgs; public: - AppComponent(const oatpp::base::CommandLineArguments& cmdArgs) - : m_cmdArgs(cmdArgs) - {} + AppComponent() = default; + public: + /** + * Swagger component + */ + SwaggerComponent swaggerComponent; - /** - * Create config component - */ - OATPP_CREATE_COMPONENT(oatpp::Object, appConfig)([this] { - auto config = ConfigDto::createShared(); + /** + * Create config component + */ + OATPP_CREATE_COMPONENT(oatpp::Object, appConfig) + ([this] { + auto config = ConfigDto::createShared(); - auto hostServer = ServerConfigDto::createShared(); - hostServer->host = "0.0.0.0"; - hostServer->port = 8000; + auto hostServer = ServerConfigDto::createShared(); + hostServer->host = "0.0.0.0"; + hostServer->port = 8000; - auto clientServer = ServerConfigDto::createShared(); - clientServer->host = "0.0.0.0"; - clientServer->port = 8001; + auto clientServer = ServerConfigDto::createShared(); + clientServer->host = "0.0.0.0"; + clientServer->port = 8001; - config->hostAPIServer = hostServer; - config->clientAPIServer = clientServer; + config->hostAPIServer = hostServer; + config->clientAPIServer = clientServer; - return config; - }()); + return config; + }()); - /** - * Hub configs - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, hubConfig) + /** + * Hub configs + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, hubConfig) ([] { // We specify the default config here auto config = std::make_shared(nullptr); @@ -112,56 +112,95 @@ class AppComponent { return config; }()); - /** - * Create Async Executor - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, executor)([] { - return std::make_shared(); - }()); - - /** - * Create Router component - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { - return oatpp::web::server::HttpRouter::createShared(); - }()); - - /** - * Create ObjectMapper component to serialize/deserialize DTOs in Contoller's API - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)(Constants::COMPONENT_REST_API,[] { - auto mapper = oatpp::parser::json::mapping::ObjectMapper::createShared(); - mapper->getSerializer()->getConfig()->includeNullFields = false; - return mapper; - }()); - - /** - * Create ObjectMapper component to serialize/deserialize DTOs in WS communication - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, wsApiObjectMapper)(Constants::COMPONENT_WS_API,[] { - auto mapper = oatpp::parser::json::mapping::ObjectMapper::createShared(); - mapper->getSerializer()->getConfig()->includeNullFields = false; - return mapper; - }()); - - /** - * Create games sessions Registry component. - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, gamesSessionsRegistry)([] { - return std::make_shared(); - }()); - - /** - * Create websocket connection handler - */ - OATPP_CREATE_COMPONENT(std::shared_ptr, websocketConnectionHandler)(Constants::COMPONENT_WS_API, [] { - OATPP_COMPONENT(std::shared_ptr, executor); - OATPP_COMPONENT(std::shared_ptr, registry); - auto connectionHandler = oatpp::websocket::AsyncConnectionHandler::createShared(executor); - connectionHandler->setSocketInstanceListener(registry); - return connectionHandler; - }()); + /** + * Create Async Executor + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, executor) + ([] { return std::make_shared(); }()); + + /** + * Create Router component + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, + httpRouter) + ([] { return oatpp::web::server::HttpRouter::createShared(); }()); + + /** + * Create ObjectMapper component to serialize/deserialize DTOs in + * Contoller's API + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, + apiObjectMapper) + (Constants::COMPONENT_REST_API, [] { + /* create serializer and deserializer configurations */ + auto serializeConfig = + oatpp::parser::json::mapping::Serializer::Config::createShared(); + auto deserializeConfig = + oatpp::parser::json::mapping::Deserializer::Config::createShared(); + + /* enable beautifier */ + serializeConfig->useBeautifier = true; + + auto objectMapper = + oatpp::parser::json::mapping::ObjectMapper::createShared( + serializeConfig, deserializeConfig); + objectMapper->getDeserializer()->getConfig()->allowUnknownFields = + false; + + // objectMapper->getSerializer()->getConfig()->enabledInterpretations = + // { + // "system::memory"}; + // objectMapper->getDeserializer()->getConfig()->enabledInterpretations + // = { + // "system::memory"}; + return objectMapper; + }()); + + /** + * Create ObjectMapper component to serialize/deserialize DTOs in WS + * communication + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, + wsApiObjectMapper) + (Constants::COMPONENT_WS_API, [] { + auto mapper = + oatpp::parser::json::mapping::ObjectMapper::createShared(); + mapper->getSerializer()->getConfig()->includeNullFields = false; + return mapper; + }()); + /** + * Create games sessions Registry component. + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, gamesSessionsRegistry) + ([] { return std::make_shared(); }()); + + + + /** + * Create websocket connection handler + */ + OATPP_CREATE_COMPONENT(std::shared_ptr, + websocketConnectionHandler) + (Constants::COMPONENT_WS_API, [] { + OATPP_COMPONENT(std::shared_ptr, executor); + OATPP_COMPONENT(std::shared_ptr, registry); + auto connectionHandler = + oatpp::websocket::AsyncConnectionHandler::createShared(executor); + connectionHandler->setSocketInstanceListener(registry); + return connectionHandler; + }()); + + /** + * Create Debug virtual interface component + */ +#if ENABLE_DEBUG + OATPP_CREATE_COMPONENT(std::shared_ptr, + virtualInterface) + ([] { + return oatpp::network::virtual_::Interface::obtainShared("virtualhost"); + }()); +#endif }; #endif /* LITHIUM_APP_COMPONENT_HPP */ \ No newline at end of file diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index e69de29b..6f8ccca9 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -0,0 +1,38 @@ +# CMakeLists.txt for Lithium +# This project is licensed under the terms of the GPL3 license. +# +# Project Name: Lithium-WebServer +# Description: Oatpp http and websocket for Lithium +# Author: Max Qian +# License: GPL3 + +cmake_minimum_required(VERSION 3.20) + +project(lithium_webserver C CXX) + +set(server_websocket_module + websocket/Hub.cpp + websocket/Connection.cpp + websocket/Registry.cpp + websocket/Session.cpp +) + +set(server_module + App.cpp + AppComponent.hpp + ErrorHandler.cpp + Runner.cpp + + config/HubsConfig.cpp +) + +################################################################################# +# Main + +add_library(${PROJECT_NAME} STATIC ${server_websocket_module} ${server_module}) +target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR}/libs) + +target_link_libraries(${PROJECT_NAME} PRIVATE oatpp-websocket oatpp-swagger oatpp-openssl oatpp-zlib oatpp) +target_link_libraries(${PROJECT_NAME} PRIVATE loguru fmt::fmt) +target_link_libraries(${PROJECT_NAME} PRIVATE atomstatic) + diff --git a/src/server/Runner.cpp b/src/server/Runner.cpp index 2d4846b3..365721c0 100644 --- a/src/server/Runner.cpp +++ b/src/server/Runner.cpp @@ -14,15 +14,34 @@ Description: Lithium Server Runner #include "Runner.hpp" +#include "ErrorHandler.hpp" + #include "controller/AsyncClientController.hpp" +#include "controller/AsyncConfigController.hpp" +/* +#include "controller/AsyncDeviceController.hpp" +#include "controller/AsyncIOController.hpp" +#include "controller/AsyncStaticController.hpp" +#include "controller/AsyncSystemController.hpp" +*/ + +#include "oatpp-swagger/AsyncController.hpp" #include "oatpp-openssl/server/ConnectionProvider.hpp" #include "oatpp/network/tcp/server/ConnectionProvider.hpp" +#include "oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp" #include "oatpp/web/server/AsyncHttpConnectionHandler.hpp" #include "oatpp/network/Server.hpp" +#include "oatpp-zlib/EncoderProvider.hpp" + +#define ADD_CONTROLLER(controller, router) \ + auto controller##_ptr = controller::createShared(); \ + docEndpoints.append(controller##_ptr->getEndpoints()); \ + router->getRouter()->addController(controller##_ptr); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // APIServer @@ -49,9 +68,35 @@ APIServer::APIServer(const oatpp::Object& config, {config->host, config->port, oatpp::network::Address::IP_4}); } + auto components = + std::make_shared( + m_router); + /* Add content encoders */ + auto encoders = std::make_shared< + oatpp::web::protocol::http::encoding::ProviderCollection>(); + encoders->add(std::make_shared()); + encoders->add(std::make_shared()); + /* Set content encoders */ + components->contentEncodingProviders = encoders; + + auto decoders = std::make_shared< + oatpp::web::protocol::http::encoding::ProviderCollection>(); + decoders->add(std::make_shared()); + decoders->add(std::make_shared()); + /* Set Body Decoder */ + components->bodyDecoder = std::make_shared< + oatpp::web::protocol::http::incoming::SimpleBodyDecoder>(decoders); + m_connectionHandler = - oatpp::web::server::AsyncHttpConnectionHandler::createShared(m_router, + oatpp::web::server::AsyncHttpConnectionHandler::createShared(components, executor); + OATPP_COMPONENT( + std::shared_ptr, + + apiObjectMapper, + Constants::COMPONENT_REST_API); // get ObjectMapper component + m_connectionHandler->setErrorHandler( + std::make_shared(apiObjectMapper)); } std::shared_ptr APIServer::getRouter() { @@ -59,7 +104,7 @@ std::shared_ptr APIServer::getRouter() { } void APIServer::start() { - m_serverThread = std::thread([this] { + m_serverThread = std::jthread([this] { oatpp::network::Server server(m_connectionProvider, m_connectionHandler); server.run(); @@ -78,7 +123,20 @@ Runner::Runner(const oatpp::Object& config, auto hostServer = std::make_shared(config->hostAPIServer, executor); - hostServer->getRouter()->addController(std::make_shared()); + + oatpp::web::server::api::Endpoints docEndpoints; + ADD_CONTROLLER(ClientController, hostServer); + ADD_CONTROLLER(ConfigController, hostServer); + /* + ADD_CONTROLLER(DeviceController, hostServer); + ADD_CONTROLLER(IOController, hostServer); + ADD_CONTROLLER(StaticController, hostServer); + ADD_CONTROLLER(SystemController, hostServer); + */ + + hostServer->getRouter()->addController( + oatpp::swagger::AsyncController::createShared(docEndpoints)); + m_servers.push_back(hostServer); /* client API server */ @@ -86,16 +144,14 @@ Runner::Runner(const oatpp::Object& config, if (config->clientAPIServer->host == config->hostAPIServer->host && config->clientAPIServer->port == config->hostAPIServer->port) { - hostServer->getRouter()->addController( - std::make_shared()); + ADD_CONTROLLER(ClientController, hostServer); } else { assertServerConfig(config->clientAPIServer, "clientAPIServer", true); auto clientServer = std::make_shared(config->clientAPIServer, executor); - clientServer->getRouter()->addController( - std::make_shared()); + ADD_CONTROLLER(ClientController, clientServer); m_servers.push_back(clientServer); } } diff --git a/src/server/Runner.hpp b/src/server/Runner.hpp index aebb2975..de791a5b 100644 --- a/src/server/Runner.hpp +++ b/src/server/Runner.hpp @@ -22,6 +22,9 @@ Description: Lithium Server Runner #include "oatpp/network/ConnectionHandler.hpp" #include "oatpp/network/ConnectionProvider.hpp" +#include "oatpp-websocket/AsyncConnectionHandler.hpp" +#include "oatpp/web/server/AsyncHttpConnectionHandler.hpp" + #include "oatpp/core/async/Executor.hpp" class APIServer { @@ -29,7 +32,8 @@ class APIServer { std::shared_ptr m_router; std::shared_ptr m_connectionProvider; - std::shared_ptr m_connectionHandler; + std::shared_ptr + m_connectionHandler; private: #if __cplusplus >= 202002L diff --git a/src/server/auth/AuthHandler.cpp b/src/server/auth/AuthHandler.cpp deleted file mode 100644 index 0eb06a93..00000000 --- a/src/server/auth/AuthHandler.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -#include "AuthHandler.hpp" - -AuthHandler::AuthHandler(const std::shared_ptr& jwt) - : oatpp::web::server::handler::BearerAuthorizationHandler( - "API" /* Realm */), - m_jwt(jwt) {} - -std::shared_ptr AuthHandler::authorize( - const oatpp::String& token) { - return m_jwt->readAndVerifyToken(token); -} \ No newline at end of file diff --git a/src/server/auth/AuthHandler.hpp b/src/server/auth/AuthHandler.hpp deleted file mode 100644 index 91ffb28c..00000000 --- a/src/server/auth/AuthHandler.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -#ifndef HEAL_AUTH_JWT_AUTHHANDLER_HPP -#define HEAL_AUTH_JWT_AUTHHANDLER_HPP - -#include "JWT.hpp" - -class AuthHandler - : public oatpp::web::server::handler::BearerAuthorizationHandler { -private: - std::shared_ptr m_jwt; - -public: - AuthHandler(const std::shared_ptr& jwt); - - std::shared_ptr authorize( - const oatpp::String& token) override; -}; - -#endif // HEAL_AUTH_JWT_AUTHHANDLER_HPP diff --git a/src/server/auth/JWT.cpp b/src/server/auth/JWT.cpp deleted file mode 100644 index ece67ad4..00000000 --- a/src/server/auth/JWT.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -#include "JWT.hpp" - -JWT::JWT(const oatpp::String& secret, const oatpp::String& issuer) - : m_secret(secret), - m_issuer(issuer), - m_verifier(jwt::verify() - .allow_algorithm(jwt::algorithm::hs256{secret}) - .with_issuer(issuer)) {} - -oatpp::String JWT::createToken(const std::shared_ptr& payload) { - auto token = jwt::create() - .set_issuer(m_issuer) - .set_type("JWS") - - .set_payload_claim("userId", jwt::claim(payload->userId)) - - .sign(jwt::algorithm::hs256{m_secret}); - return token; -} - -std::shared_ptr JWT::readAndVerifyToken( - const oatpp::String& token) { - auto decoded = jwt::decode(token); - m_verifier.verify(decoded); - - auto payload = std::make_shared(); - payload->userId = - decoded.get_payload_claim("").to_json().get("userId").to_str(); - - return payload; -} \ No newline at end of file diff --git a/src/server/auth/JWT.hpp b/src/server/auth/JWT.hpp deleted file mode 100644 index 6e37e192..00000000 --- a/src/server/auth/JWT.hpp +++ /dev/null @@ -1,29 +0,0 @@ - -#ifndef HEAL_AUTH_JWT_HPP -#define HEAL_AUTH_JWT_HPP - -#include "oatpp/core/Types.hpp" -#include "oatpp/web/server/handler/AuthorizationHandler.hpp" - -#include - -class JWT { -public: - struct Payload : public oatpp::web::server::handler::AuthorizationObject { - oatpp::String userId; - }; - -private: - oatpp::String m_secret; - oatpp::String m_issuer; - jwt::verifier m_verifier; - -public: - JWT(const oatpp::String& secret, const oatpp::String& issuer); - - oatpp::String createToken(const std::shared_ptr& payload); - - std::shared_ptr readAndVerifyToken(const oatpp::String& token); -}; - -#endif // HEAL_AUTH_JWT_HPP diff --git a/src/server/controller/AsyncConfigController.hpp b/src/server/controller/AsyncConfigController.hpp index 8776668d..19ca78c8 100644 --- a/src/server/controller/AsyncConfigController.hpp +++ b/src/server/controller/AsyncConfigController.hpp @@ -15,8 +15,6 @@ Description: Async Config Controller #ifndef LITHIUM_ASYNC_SCRIPT_CONTROLLER_HPP #define LITHIUM_ASYNC_SCRIPT_CONTROLLER_HPP -#include "config.h" - #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp" @@ -32,11 +30,11 @@ Description: Async Config Controller class ConfigController : public oatpp::web::server::api::ApiController { public: - static std::shared_ptr m_configManager; + static std::weak_ptr m_configManager; ConfigController(const std::shared_ptr& objectMapper) : oatpp::web::server::api::ApiController(objectMapper) { - m_configManager = GetPtr("lithium.config"); + m_configManager = GetWeakPtr("lithium.config"); } // ---------------------------------------------------------------- @@ -73,16 +71,16 @@ class ConfigController : public oatpp::web::server::api::ApiController { auto res = ReturnConfigDTO::createShared(); res->status = "getConfig"; - if (!m_configManager) { + if (m_configManager.expired()) { res->status = "error"; res->code = 500; res->error = "ConfigManager is null"; } else { std::string path = body->path.getValue(""); - if (auto tmp = m_configManager->getValue(path); tmp) { + if (auto tmp = m_configManager.lock()->getValue(path); tmp) { res->status = "success"; res->code = 200; - res->value = tmp.dump(); + res->value = tmp.value().dump(); res->type = "string"; } else { res->status = "error"; @@ -119,14 +117,14 @@ class ConfigController : public oatpp::web::server::api::ApiController { auto res = StatusDto::createShared(); res->command = "setConfig"; - if (!m_configManager) { + if (m_configManager.expired()) { res->status = "error"; res->code = 500; res->error = "ConfigManager is null"; } else { std::string path = body->path.getValue(""); std::string value = body->value.getValue(""); - if (m_configManager->setValue(path, value)) { + if (m_configManager.lock()->setValue(path, value)) { res->status = "success"; res->code = 200; } else { @@ -162,13 +160,13 @@ class ConfigController : public oatpp::web::server::api::ApiController { auto res = StatusDto::createShared(); res->command = "deleteConfig"; - if (!m_configManager) { + if (m_configManager.expired()) { res->status = "error"; res->code = 500; res->error = "ConfigManager is null"; } else { std::string path = body->path.getValue(""); - if (m_configManager->deleteValue(path)) { + if (m_configManager.lock()->deleteValue(path)) { res->status = "success"; res->code = 200; } else { @@ -205,13 +203,13 @@ class ConfigController : public oatpp::web::server::api::ApiController { auto res = StatusDto::createShared(); res->command = "loadConfig"; - if (!m_configManager) { + if (m_configManager.expired()) { res->status = "error"; res->code = 500; res->error = "ConfigManager is null"; } else { std::string path = body->path.getValue(""); - if (m_configManager->loadFromFile(path)) { + if (m_configManager.lock()->loadFromFile(path)) { res->status = "success"; res->code = 200; } else { @@ -248,14 +246,14 @@ class ConfigController : public oatpp::web::server::api::ApiController { auto res = StatusDto::createShared(); res->command = "saveConfig"; - if (!m_configManager) { + if (m_configManager.expired()) { res->status = "error"; res->code = 500; res->error = "ConfigManager is null"; } else { std::string path = body->path.getValue(""); bool isAbsolute = body->isAbsolute.getValue(true); - if (m_configManager->saveToFile(path)) { + if (m_configManager.lock()->saveToFile(path)) { res->status = "success"; res->code = 200; } else { @@ -270,8 +268,7 @@ class ConfigController : public oatpp::web::server::api::ApiController { }; }; -std::shared_ptr ConfigController::m_configManager = - GetPtr("lithium.config"); +std::weak_ptr ConfigController::m_configManager = {}; #include OATPP_CODEGEN_END(ApiController) //<- End Codegen diff --git a/src/server/controller/AsyncDeviceController.hpp b/src/server/controller/AsyncDeviceController.hpp index d61fed05..4131f856 100644 --- a/src/server/controller/AsyncDeviceController.hpp +++ b/src/server/controller/AsyncDeviceController.hpp @@ -15,8 +15,6 @@ Description: Device Routes #ifndef LITHIUM_ASYNC_DEVICE_CONTROLLER_HPP #define LITHIUM_ASYNC_DEVICE_CONTROLLER_HPP -#include "config.h" - #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp" diff --git a/src/server/controller/AsyncIOController.hpp b/src/server/controller/AsyncIOController.hpp index f94858f3..388f782a 100644 --- a/src/server/controller/AsyncIOController.hpp +++ b/src/server/controller/AsyncIOController.hpp @@ -15,8 +15,6 @@ Description: IO Route #ifndef LITHIUM_ASYNC_IO_CONTROLLER_HPP #define LITHIUM_ASYNC_IO_CONTROLLER_HPP -#include "config.h" - #include "atom/io/compress.hpp" #include "atom/io/file.hpp" #include "atom/io/io.hpp" diff --git a/src/server/controller/AsyncPHD2Controller.hpp b/src/server/controller/AsyncPHD2Controller.hpp index 219ddd95..6c5ee817 100644 --- a/src/server/controller/AsyncPHD2Controller.hpp +++ b/src/server/controller/AsyncPHD2Controller.hpp @@ -17,8 +17,6 @@ Description: PHD2 Route #include "lithiumapp.hpp" -#include "config.h" - #include "data/PHD2Dto.hpp" #include "data/StatusDto.hpp" diff --git a/src/server/controller/AsyncProcessController.hpp b/src/server/controller/AsyncProcessController.hpp index e1fb2f13..968abb2c 100644 --- a/src/server/controller/AsyncProcessController.hpp +++ b/src/server/controller/AsyncProcessController.hpp @@ -15,8 +15,6 @@ Description: Process Route #ifndef LITHIUM_ASYNC_PROCESS_CONTROLLER_HPP #define LITHIUM_ASYNC_PROCESS_CONTROLLER_HPP -#include "config.h" - #include "data/ProcessDto.hpp" #include "data/StatusDto.hpp" diff --git a/src/server/controller/AsyncScriptController.hpp b/src/server/controller/AsyncScriptController.hpp index d8758120..cb91edd9 100644 --- a/src/server/controller/AsyncScriptController.hpp +++ b/src/server/controller/AsyncScriptController.hpp @@ -26,8 +26,6 @@ Description: Async Script Controller #ifndef Lithium_SCRIPTCONTROLLER_HPP #define Lithium_SCRIPTCONTROLLER_HPP -#include "config.h" - #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp" diff --git a/src/server/controller/AsyncStaticController.hpp b/src/server/controller/AsyncStaticController.hpp index a7c7a68b..6fa5f60c 100644 --- a/src/server/controller/AsyncStaticController.hpp +++ b/src/server/controller/AsyncStaticController.hpp @@ -20,8 +20,6 @@ Description: Static Route #include "oatpp/parser/json/mapping/ObjectMapper.hpp" #include "oatpp/web/server/api/ApiController.hpp" -#include "config.h" - #include #include #include diff --git a/src/server/controller/AsyncSystemController.hpp b/src/server/controller/AsyncSystemController.hpp index c5b8639a..986dab01 100644 --- a/src/server/controller/AsyncSystemController.hpp +++ b/src/server/controller/AsyncSystemController.hpp @@ -23,8 +23,6 @@ Description: System Route #include "atom/system/module/wifi.hpp" #include "atom/system/system.hpp" -#include "config.h" - #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp" diff --git a/src/server/controller/AuthController.hpp b/src/server/controller/AuthController.hpp deleted file mode 100644 index cf373f75..00000000 --- a/src/server/controller/AuthController.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef EXAMPLE_JWT_AUTHCONTROLLER_HPP -#define EXAMPLE_JWT_AUTHCONTROLLER_HPP - -#include "service/AuthService.hpp" - -#include "oatpp/core/macro/codegen.hpp" -#include "oatpp/parser/json/mapping/ObjectMapper.hpp" -#include "oatpp/web/server/api/ApiController.hpp" - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- Begin Codegen - -/** - * User REST controller. - */ -class AuthController : public oatpp::web::server::api::ApiController { -public: - AuthController(const std::shared_ptr& objectMapper) - : oatpp::web::server::api::ApiController(objectMapper) {} - -private: - AuthService m_userService; // Create user service. -public: - static std::shared_ptr createShared( - OATPP_COMPONENT(std::shared_ptr, - objectMapper) // Inject objectMapper component here as - // default parameter - ) { - return std::make_shared(objectMapper); - } - - ENDPOINT_INFO(signUp) { - info->summary = "Sign up"; - - info->addConsumes>("application/json"); - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - } - ENDPOINT("POST", "users/signup", signUp, BODY_DTO(Object, dto)) { - return createDtoResponse(Status::CODE_200, m_userService.signUp(dto)); - } - - ENDPOINT_INFO(signIn) { - info->summary = "Sign in"; - - info->addConsumes>("application/json"); - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - } - ENDPOINT("POST", "users/signin", signIn, BODY_DTO(Object, dto)) { - return createDtoResponse(Status::CODE_200, m_userService.signIn(dto)); - } - - ENDPOINT_INFO(deleteUser) { - info->summary = "Delete User"; - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - } - ENDPOINT("DELETE", "users", deleteUser, BUNDLE(String, userId)) { - return createDtoResponse(Status::CODE_200, - m_userService.deleteUserById(userId)); - } -}; - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- End Codegen - -#endif // EXAMPLE_JWT_AUTHCONTROLLER_HPP diff --git a/src/server/controller/StaticController.hpp b/src/server/controller/StaticController.hpp deleted file mode 100644 index 2e2d442f..00000000 --- a/src/server/controller/StaticController.hpp +++ /dev/null @@ -1,45 +0,0 @@ - -#ifndef EXAMPLE_JWT_STATICCONTROLLER_HPP -#define EXAMPLE_JWT_STATICCONTROLLER_HPP - -#include "oatpp/core/macro/codegen.hpp" -#include "oatpp/core/macro/component.hpp" -#include "oatpp/parser/json/mapping/ObjectMapper.hpp" -#include "oatpp/web/server/api/ApiController.hpp" - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- Begin Codegen - -class StaticController : public oatpp::web::server::api::ApiController { -public: - StaticController(const std::shared_ptr& objectMapper) - : oatpp::web::server::api::ApiController(objectMapper) {} - -public: - static std::shared_ptr createShared( - OATPP_COMPONENT(std::shared_ptr, - objectMapper) // Inject objectMapper component here as - // default parameter - ) { - return std::make_shared(objectMapper); - } - - ENDPOINT("GET", "/", root) { - const char* html = - "" - " " - " " - " " - " " - "

Hello CRUD example project!

" - " Checkout Swagger-UI page" - " " - ""; - auto response = createResponse(Status::CODE_200, html); - response->putHeader(Header::CONTENT_TYPE, "text/html"); - return response; - } -}; - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- End Codegen - -#endif // EXAMPLE_JWT_STATICCONTROLLER_HPP diff --git a/src/server/controller/StoryController.hpp b/src/server/controller/StoryController.hpp deleted file mode 100644 index f0b8c155..00000000 --- a/src/server/controller/StoryController.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef EXAMPLE_JWT_STORYCONTROLLER_HPP -#define EXAMPLE_JWT_STORYCONTROLLER_HPP - -#include "service/StoryService.hpp" - -#include "oatpp/core/macro/codegen.hpp" -#include "oatpp/parser/json/mapping/ObjectMapper.hpp" -#include "oatpp/web/server/api/ApiController.hpp" - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- Begin Codegen - -/** - * Story REST controller. - */ -class StoryController : public oatpp::web::server::api::ApiController { -public: - StoryController(const std::shared_ptr& objectMapper) - : oatpp::web::server::api::ApiController(objectMapper) {} - -private: - StoryService m_storyService; // Create story service. -public: - static std::shared_ptr createShared( - OATPP_COMPONENT(std::shared_ptr, - objectMapper) // Inject objectMapper component here as - // default parameter - ) { - return std::make_shared(objectMapper); - } - - ENDPOINT_INFO(createStory) { - info->summary = "Create new Story"; - - info->addConsumes>("application/json"); - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - } - ENDPOINT("POST", "stories", createStory, BUNDLE(String, userId), - BODY_DTO(Object, storyDto)) { - storyDto->id = nullptr; - return createDtoResponse(Status::CODE_200, - m_storyService.createStory(userId, storyDto)); - } - - ENDPOINT_INFO(putStory) { - info->summary = "Update Story by storyId"; - - info->addConsumes>("application/json"); - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_404, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - - info->pathParams["storyId"].description = "Story Identifier"; - } - ENDPOINT("PUT", "stories/{storyId}", putStory, BUNDLE(String, userId), - PATH(String, storyId), BODY_DTO(Object, storyDto)) { - storyDto->id = storyId; - return createDtoResponse(Status::CODE_200, - m_storyService.updateStory(userId, storyDto)); - } - - ENDPOINT_INFO(getStoryById) { - info->summary = "Get one Story by storyId"; - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_404, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - - info->pathParams["storyId"].description = "Story Identifier"; - } - ENDPOINT("GET", "stories/{storyId}", getStoryById, BUNDLE(String, userId), - PATH(String, storyId)) { - return createDtoResponse( - Status::CODE_200, - m_storyService.getStoryByUserIdAndId(userId, storyId)); - } - - ENDPOINT_INFO(getStories) { - info->summary = "Get All user stories"; - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - } - ENDPOINT("GET", "stories/offset/{offset}/limit/{limit}", getStories, - BUNDLE(String, userId), PATH(UInt32, offset), - PATH(UInt32, limit)) { - return createDtoResponse( - Status::CODE_200, - m_storyService.getAllUserStories(userId, offset, limit)); - } - - ENDPOINT_INFO(deleteStory) { - info->summary = "Delete story by storyId"; - - info->addResponse>(Status::CODE_200, - "application/json"); - info->addResponse>(Status::CODE_500, - "application/json"); - - info->pathParams["storyId"].description = "Story Identifier"; - } - ENDPOINT("DELETE", "stories/{userId}", deleteStory, BUNDLE(String, userId), - PATH(String, storyId)) { - return createDtoResponse( - Status::CODE_200, - m_storyService.deleteStoryByUserIdAndId(userId, storyId)); - } -}; - -#include OATPP_CODEGEN_BEGIN(ApiController) //<- End Codegen - -#endif /* EXAMPLE_JWT_STORYCONTROLLER_HPP */ diff --git a/src/server/database/StoryDb.hpp b/src/server/database/StoryDb.hpp deleted file mode 100644 index d416c133..00000000 --- a/src/server/database/StoryDb.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -#ifndef EXAMPLE_JWT_STORYDB_HPP -#define EXAMPLE_JWT_STORYDB_HPP - -#include "model/StoryModel.hpp" -#include "oatpp-sqlite/orm.hpp" - -#include OATPP_CODEGEN_BEGIN(DbClient) //<- Begin Codegen - -/** - * StoryDb client definitions. - */ -class StoryDb : public oatpp::orm::DbClient { -public: - StoryDb(const std::shared_ptr& executor) - : oatpp::orm::DbClient(executor) { - oatpp::orm::SchemaMigration migration(executor); - migration.addFile(1 /* start from version 1 */, "./sql/story.sql"); - // TODO - Add more migrations here. - migration - .migrate(); // <-- run migrations. This guy will throw on error. - - auto version = executor->getSchemaVersion(); - OATPP_LOGD("UserDb", "Migration - OK. Version=%lld.", version); - } - - QUERY(createStory, - "INSERT INTO Stories" - "(id, userid, content) VALUES " - "(uuid_generate_v4(), :story.userid, :story.content) " - "RETURNING *;", - PREPARE(true), // prepared statement! - PARAM(oatpp::Object, story)) - - QUERY(updateStory, - "UPDATE Stories " - "SET " - " content=:story.content, " - "WHERE " - " id=:story.id AND userid=:story.userid " - "RETURNING *;", - PREPARE(true), // prepared statement! - PARAM(oatpp::Object, story)) - - QUERY(getStoryByUserIdAndId, - "SELECT * FROM Stories WHERE id=:id AND userid=:userId;", - PREPARE(true), // prepared statement! - PARAM(oatpp::String, userId), PARAM(oatpp::String, id)) - - QUERY(getAllUserStories, - "SELECT * FROM Stories WHERE userid=:userId LIMIT :limit OFFSET " - ":offset;", - PREPARE(true), // prepared statement! - PARAM(oatpp::String, userId), PARAM(oatpp::UInt32, offset), - PARAM(oatpp::UInt32, limit)) - - QUERY(deleteStoryByUserIdAndId, - "DELETE FROM Stories WHERE id=:id AND userid=:userId;", - PREPARE(true), // prepared statement! - PARAM(oatpp::String, userId), PARAM(oatpp::String, id)) -}; - -#include OATPP_CODEGEN_END(DbClient) //<- End Codegen - -#endif // EXAMPLE_JWT_STORYDB_HPP diff --git a/src/server/database/UserDb.hpp b/src/server/database/UserDb.hpp deleted file mode 100644 index 9bf68c35..00000000 --- a/src/server/database/UserDb.hpp +++ /dev/null @@ -1,73 +0,0 @@ - -#ifndef EXAMPLE_JWT_USERDB_HPP -#define EXAMPLE_JWT_USERDB_HPP - -#include "data/UserDto.hpp" -#include "model/UserModel.hpp" -#include "oatpp-sqlite/orm.hpp" - -#include OATPP_CODEGEN_BEGIN(DbClient) //<- Begin Codegen - -/** - * UserDb client definitions. - */ -class UserDb : public oatpp::orm::DbClient { -public: - UserDb(const std::shared_ptr& executor) - : oatpp::orm::DbClient(executor) { - oatpp::orm::SchemaMigration migration(executor); - migration.addFile(1 /* start from version 1 */, "./sql/user.sql"); - // TODO - Add more migrations here. - migration - .migrate(); // <-- run migrations. This guy will throw on error. - - auto version = executor->getSchemaVersion(); - OATPP_LOGD("UserDb", "Migration - OK. Version=%lld.", version); - } - - QUERY(createUser, - "INSERT INTO AppUser" - "(username, email, password, role) VALUES " - "(:user.username, :user.email, :user.password, :user.role);", - PARAM(oatpp::Object, user)) - - QUERY(updateUser, - "UPDATE AppUser " - "SET " - " username=:user.username, " - " email=:user.email, " - " password=:user.password, " - " role=:user.role " - "WHERE " - " id=:user.id;", - PARAM(oatpp::Object, user)) - - QUERY(getUserById, "SELECT * FROM AppUser WHERE id=:id;", - PARAM(oatpp::Int32, id)) - - QUERY(getAllUsers, "SELECT * FROM AppUser LIMIT :limit OFFSET :offset;", - PARAM(oatpp::UInt32, offset), PARAM(oatpp::UInt32, limit)) - - QUERY(deleteUserById, "DELETE FROM AppUser WHERE id=:id;", - PARAM(oatpp::Int32, id)) - - QUERY(changeUserPassword, - "UPDATE users " - "SET " - " pswhash=crypt(:newPassword, gen_salt('bf', 8)) " - "WHERE " - " id=:id AND pswhash=crypt(:oldPassword, pswhash);", - PREPARE(true), // prepared statement! - PARAM(oatpp::String, userId, "id"), PARAM(oatpp::String, oldPassword), - PARAM(oatpp::String, newPassword)) - - QUERY(authenticateUser, - "SELECT id FROM users WHERE username=:username AND " - "pswhash=crypt(:password, pswhash);", - PREPARE(true), // prepared statement! - PARAM(oatpp::String, username), PARAM(oatpp::String, password)) -}; - -#include OATPP_CODEGEN_END(DbClient) //<- End Codegen - -#endif // EXAMPLE_JWT_USERDB_HPP diff --git a/src/server/database/model/StoryModel.hpp b/src/server/database/model/StoryModel.hpp deleted file mode 100644 index 75b57a4e..00000000 --- a/src/server/database/model/StoryModel.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EXAMPLE_JWT_STORYMODEL_HPP -#define EXAMPLE_JWT_STORYMODEL_HPP - -#include "oatpp/core/macro/codegen.hpp" -#include "oatpp/core/Types.hpp" - -#include OATPP_CODEGEN_BEGIN(DTO) - -class StoryModel : public oatpp::DTO { - - DTO_INIT(StoryModel, DTO) - - DTO_FIELD(String, id); - DTO_FIELD(String, userId, "userid"); - DTO_FIELD(String, content, "content"); - -}; - -#include OATPP_CODEGEN_END(DTO) - - -#endif //EXAMPLE_JWT_STORYMODEL_HPP diff --git a/src/server/database/model/UserModel.hpp b/src/server/database/model/UserModel.hpp deleted file mode 100644 index 013e9a94..00000000 --- a/src/server/database/model/UserModel.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EXAMPLE_JWT_DB_MODEL_USERMODEL_HPP -#define EXAMPLE_JWT_DB_MODEL_USERMODEL_HPP - -#include "oatpp/core/macro/codegen.hpp" -#include "oatpp/core/Types.hpp" - -#include OATPP_CODEGEN_BEGIN(DTO) - -class UserModel : public oatpp::DTO { - - DTO_INIT(UserModel, DTO) - - DTO_FIELD(String, id); - DTO_FIELD(String, userName, "username"); - DTO_FIELD(String, email, "email"); - DTO_FIELD(String, password, "password"); - -}; - -#include OATPP_CODEGEN_END(DTO) - -#endif /* EXAMPLE_JWT_DB_MODEL_USERMODEL_HPP */ diff --git a/src/server/interceptor/AuthInterceptor.cpp b/src/server/interceptor/AuthInterceptor.cpp deleted file mode 100644 index 30259671..00000000 --- a/src/server/interceptor/AuthInterceptor.cpp +++ /dev/null @@ -1,33 +0,0 @@ - -#include "AuthInterceptor.hpp" - -AuthInterceptor::AuthInterceptor(const std::shared_ptr& jwt) - : m_authHandler(jwt) { - authEndpoints.route("POST", "users/signup", false); - authEndpoints.route("POST", "users/signin", false); - - authEndpoints.route("GET", "swagger/*", false); - authEndpoints.route("GET", "api-docs/oas-3.0.0.json", false); -} - -std::shared_ptr AuthInterceptor::intercept( - const std::shared_ptr& request) { - auto r = authEndpoints.getRoute(request->getStartingLine().method, - request->getStartingLine().path); - if (r && !r.getEndpoint()) { - return nullptr; // Continue without Authorization - } - - auto authHeader = - request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); - - auto authObject = std::static_pointer_cast( - m_authHandler.handleAuthorization(authHeader)); - if (authObject) { - request->putBundleData("userId", authObject->userId); - return nullptr; // Continue - token is valid. - } - - throw oatpp::web::protocol::http::HttpError( - oatpp::web::protocol::http::Status::CODE_401, "Unauthorized", {}); -} \ No newline at end of file diff --git a/src/server/interceptor/AuthInterceptor.hpp b/src/server/interceptor/AuthInterceptor.hpp deleted file mode 100644 index a14c2c09..00000000 --- a/src/server/interceptor/AuthInterceptor.hpp +++ /dev/null @@ -1,25 +0,0 @@ - -#ifndef EXAMPLE_JWT_AUTHINTERCEPTOR_HPP -#define EXAMPLE_JWT_AUTHINTERCEPTOR_HPP - -#include "auth/AuthHandler.hpp" - -#include "oatpp/web/server/HttpConnectionHandler.hpp" -#include "oatpp/web/server/HttpRouter.hpp" -#include "oatpp/web/server/handler/AuthorizationHandler.hpp" -#include "oatpp/web/server/interceptor/RequestInterceptor.hpp" - -class AuthInterceptor - : public oatpp::web::server::interceptor::RequestInterceptor { -private: - AuthHandler m_authHandler; - oatpp::web::server::HttpRouterTemplate authEndpoints; - -public: - AuthInterceptor(const std::shared_ptr& jwt); - - std::shared_ptr intercept( - const std::shared_ptr& request) override; -}; - -#endif // EXAMPLE_JWT_AUTHINTERCEPTOR_HPP diff --git a/src/server/launcher/faq.cpp b/src/server/launcher/faq.cpp deleted file mode 100644 index 473dca12..00000000 --- a/src/server/launcher/faq.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * faq.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-4-13 - -Description: F&Q Manager for HEAL - -**************************************************/ - -#include "faq.hpp" - -#include -#include -#include -#include -#include -#include - -struct FAQ { - std::string question; - std::string description; - std::string category; - std::vector solutions; - int difficulty; - std::vector links; -}; - -void FAQManager::addFAQ(const FAQ &faq) { - std::lock_guard lock(mutex); - faqs.push_back(faq); -} - -void FAQManager::deleteFAQ(const std::string &question) { - std::lock_guard lock(mutex); - faqs.erase(std::remove_if( - faqs.begin(), faqs.end(), - [&](const FAQ &faq) { return faq.question == question; }), - faqs.end()); -} - -std::vector FAQManager::searchFAQs(const std::string &keyword) { - std::lock_guard lock(mutex); - - // 检查缓存中是否存在搜索结果 - if (cache.find(keyword) != cache.end()) { - return cache[keyword]; - } - - std::vector results; - for (const auto &faq : faqs) { - if (faq.question.find(keyword) != std::string::npos || - faq.description.find(keyword) != std::string::npos || - faq.category.find(keyword) != std::string::npos) { - results.push_back(faq); - } - } - - // 将搜索结果存入缓存 - cache[keyword] = results; - - return results; -} - -std::vector FAQManager::getFAQs() const { - std::lock_guard lock(mutex); - return faqs; -} - -std::vector FAQManager::getCategorizedFAQs(const std::string &category) { - std::lock_guard lock(mutex); - - // 检查缓存中是否存在分类结果 - if (categoryCache.find(category) != categoryCache.end()) { - return categoryCache[category]; - } - - std::vector results; - for (const auto &faq : faqs) { - if (faq.category == category) { - results.push_back(faq); - } - } - - // 将分类结果存入缓存 - categoryCache[category] = results; - - return results; -} - -void FAQManager::saveToFile(const std::string &filename) { - std::lock_guard lock(mutex); - json jsonData; - - for (const auto &faq : faqs) { - json jsonFAQ; - jsonFAQ["question"] = faq.question; - jsonFAQ["description"] = faq.description; - jsonFAQ["category"] = faq.category; - jsonFAQ["solutions"] = faq.solutions; - jsonFAQ["difficulty"] = faq.difficulty; - jsonFAQ["links"] = faq.links; - - jsonData.push_back(jsonFAQ); - } - - std::ofstream file(filename); - file << jsonData.dump(4); // 4-space indentation for pretty printing -} - -void FAQManager::loadFromFile(const std::string &filename) { - std::lock_guard lock(mutex); - std::ifstream file(filename); - json jsonData; - file >> jsonData; - - faqs.clear(); - cache.clear(); - categoryCache.clear(); - - for (const auto &jsonFAQ : jsonData) { - FAQ faq; - faq.question = jsonFAQ["question"]; - faq.description = jsonFAQ["description"]; - faq.category = jsonFAQ["category"]; - faq.solutions = jsonFAQ["solutions"]; - faq.difficulty = jsonFAQ["difficulty"]; - faq.links = jsonFAQ["links"]; - - faqs.push_back(faq); - } -} - -void FAQManager::printFAQs() const { - std::lock_guard lock(mutex); - json jsonData; - - for (const auto &faq : faqs) { - json jsonFAQ; - jsonFAQ["question"] = faq.question; - jsonFAQ["description"] = faq.description; - jsonFAQ["category"] = faq.category; - jsonFAQ["solutions"] = faq.solutions; - jsonFAQ["difficulty"] = faq.difficulty; - jsonFAQ["links"] = faq.links; - - jsonData.push_back(jsonFAQ); - } - - std::cout << jsonData.dump(4) << std::endl; -} \ No newline at end of file diff --git a/src/server/launcher/faq.hpp b/src/server/launcher/faq.hpp deleted file mode 100644 index 2a50f43f..00000000 --- a/src/server/launcher/faq.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * faq.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-4-13 - -Description: F&Q Manager for HEAL - -**************************************************/ - -#include -#include -#include - -#if ENABLE_FASTHASH -#include "emhash/hash_table8.hpp" -#else -#include -#endif - -#include "atom/type/json.hpp" -using json = nlohmann::json; - -struct FAQ { - std::string question; - std::string description; - std::string category; - std::vector solutions; - int difficulty; - std::vector links; -}; - -class FAQManager { -public: - void addFAQ(const FAQ &faq); - - void deleteFAQ(const std::string &question); - - std::vector searchFAQs(const std::string &keyword); - - std::vector getFAQs() const; - - std::vector getCategorizedFAQs(const std::string &category); - - void saveToFile(const std::string &filename); - - void loadFromFile(const std::string &filename); - - void printFAQs() const; - -private: - std::vector faqs; -#if ENABLE_FASTHASH - emhash8::HashMap> cache; - emhash8::HashMap> categoryCache; -#else - std::unordered_map> cache; - std::unordered_map> categoryCache; -#endif - mutable std::mutex mutex; -}; \ No newline at end of file diff --git a/src/server/service/AuthService.cpp b/src/server/service/AuthService.cpp deleted file mode 100644 index ddcf9c51..00000000 --- a/src/server/service/AuthService.cpp +++ /dev/null @@ -1,74 +0,0 @@ - -#include "AuthService.hpp" - -oatpp::Object AuthService::signUp( - const oatpp::Object& dto) { - auto user = UserModel::createShared(); - user->id = nullptr; - user->userName = dto->userName; - user->email = dto->email; - user->password = dto->password; - - auto userDto = UserDto::createShared(); - userDto->userName = user->userName; - userDto->email = user->email; - userDto->password = user->password; - userDto->role = Role::ADMIN; - - auto dbResult = m_database->createUser(userDto); - if (!dbResult->isSuccess()) { - OATPP_LOGE("AuthService", "DB-Error: '%s'", - dbResult->getErrorMessage()->c_str()); - } - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_401, "Unauthorized"); - - auto result = - dbResult->fetch>>(); - OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_401, "Unauthorized") - - auto newUserId = result[0][0]; - - auto payload = std::make_shared(); - payload->userId = newUserId; - - auto auth = AuthDto::createShared(); - auth->token = m_jwt->createToken(payload); - - return auth; -} - -oatpp::Object AuthService::signIn( - const oatpp::Object& dto) { - auto dbResult = m_database->authenticateUser(dto->userName, dto->password); - if (!dbResult->isSuccess()) { - OATPP_LOGE("AuthService", "DB-Error: '%s'", - dbResult->getErrorMessage()->c_str()); - } - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_401, "Unauthorized") - - auto result = - dbResult->fetch>>(); - OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_401, "Unauthorized") - - auto userId = result[0][0]; - - auto payload = std::make_shared(); - payload->userId = userId; - - auto auth = AuthDto::createShared(); - auth->token = m_jwt->createToken(payload); - - return auth; -} - -oatpp::Object AuthService::deleteUserById( - const oatpp::String& userId) { - auto dbResult = m_database->deleteUserById(1); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - auto status = StatusDto::createShared(); - status->status = "OK"; - status->code = 200; - status->message = "User was successfully deleted"; - return status; -} \ No newline at end of file diff --git a/src/server/service/AuthService.hpp b/src/server/service/AuthService.hpp deleted file mode 100644 index 10093d3e..00000000 --- a/src/server/service/AuthService.hpp +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef HEAL_SERVICE_JWT_AUTHSERVICE_HPP -#define HEAL_SERVICE_JWT_AUTHSERVICE_HPP - -#include "auth/JWT.hpp" - -#include "data/AuthDto.hpp" -#include "data/PageDto.hpp" -#include "data/SignInDto.hpp" -#include "data/SignUpDto.hpp" -#include "data/StatusDto.hpp" -#include "database/UserDb.hpp" - -#include "oatpp/core/macro/component.hpp" -#include "oatpp/web/protocol/http/Http.hpp" - -class AuthService { -private: - typedef oatpp::web::protocol::http::Status Status; - -private: - OATPP_COMPONENT(std::shared_ptr, - m_database); // Inject database component - OATPP_COMPONENT(std::shared_ptr, m_jwt); // Inject JWT component -public: - oatpp::Object signUp(const oatpp::Object& dto); - oatpp::Object signIn(const oatpp::Object& dto); - oatpp::Object deleteUserById(const oatpp::String& id); -}; - -#endif // HEAL_SERVICE_JWT_AUTHSERVICE_HPP diff --git a/src/server/service/StoryService.cpp b/src/server/service/StoryService.cpp deleted file mode 100644 index 5b358c22..00000000 --- a/src/server/service/StoryService.cpp +++ /dev/null @@ -1,95 +0,0 @@ - -#include "StoryService.hpp" - -oatpp::Object StoryService::storyDtoFromModel( - const oatpp::Object& model) { - auto dto = StoryDto::createShared(); - dto->id = model->id; - dto->content = model->content; - return dto; -} - -oatpp::Object StoryService::storyModelFromDto( - const oatpp::String& userId, const oatpp::Object& dto) { - auto model = StoryModel::createShared(); - model->userId = userId; - model->id = dto->id; - model->content = dto->content; - return model; -} - -oatpp::Object StoryService::createStory( - const oatpp::String& userId, const oatpp::Object& dto) { - auto dbResult = m_database->createStory(storyModelFromDto(userId, dto)); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - auto result = dbResult->fetch>>(); - OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown Error"); - return storyDtoFromModel(result[0]); -} - -oatpp::Object StoryService::updateStory( - const oatpp::String& userId, const oatpp::Object& dto) { - auto dbResult = m_database->updateStory(storyModelFromDto(userId, dto)); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - auto result = dbResult->fetch>>(); - OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown Error"); - return storyDtoFromModel(result[0]); -} - -oatpp::Object StoryService::getStoryByUserIdAndId( - const oatpp::String& userId, const oatpp::String& id, - const oatpp::provider::ResourceHandle& connection) { - auto dbResult = m_database->getStoryByUserIdAndId(userId, id, connection); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - OATPP_ASSERT_HTTP(dbResult->hasMoreToFetch(), Status::CODE_404, - "User story not found"); - - auto result = dbResult->fetch>>(); - OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown error"); - - return storyDtoFromModel(result[0]); -} - -oatpp::Object>> StoryService::getAllUserStories( - const oatpp::String& userId, const oatpp::UInt32& offset, - const oatpp::UInt32& limit) { - oatpp::UInt32 countToFetch = limit; - - if (limit > 10) { - countToFetch = 10; - } - - auto dbResult = m_database->getAllUserStories(userId, offset, countToFetch); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - - auto items = dbResult->fetch>>(); - - oatpp::Vector> stories({}); - for (auto& item : *items) { - stories->push_back(storyDtoFromModel(item)); - } - - auto page = PageDto>::createShared(); - page->offset = offset; - page->limit = countToFetch; - page->count = stories->size(); - page->items = stories; - - return page; -} - -oatpp::Object StoryService::deleteStoryByUserIdAndId( - const oatpp::String& userId, const oatpp::String& id) { - auto dbResult = m_database->deleteStoryByUserIdAndId(userId, id); - OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, - dbResult->getErrorMessage()); - auto status = StatusDto::createShared(); - status->status = "OK"; - status->code = 200; - status->message = "User story was successfully deleted"; - return status; -} \ No newline at end of file diff --git a/src/server/service/StoryService.hpp b/src/server/service/StoryService.hpp deleted file mode 100644 index d6c722fa..00000000 --- a/src/server/service/StoryService.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef HEAL_SERVICE_STORYSERVICE_HPP -#define HEAL_SERVICE_STORYSERVICE_HPP - -#include "database/StoryDb.hpp" -#include "database/model/StoryModel.hpp" - -#include "data/PageDto.hpp" -#include "data/StatusDto.hpp" -#include "data/StoryDto.hpp" - -#include "oatpp/core/macro/component.hpp" -#include "oatpp/web/protocol/http/Http.hpp" - -class StoryService { -private: - typedef oatpp::web::protocol::http::Status Status; - -private: - oatpp::Object storyDtoFromModel( - const oatpp::Object& model); - oatpp::Object storyModelFromDto( - const oatpp::String& userId, const oatpp::Object& dto); - -private: - OATPP_COMPONENT(std::shared_ptr, - m_database); // Inject database component -public: - oatpp::Object createStory(const oatpp::String& userId, - const oatpp::Object& dto); - oatpp::Object updateStory(const oatpp::String& userId, - const oatpp::Object& dto); - oatpp::Object getStoryByUserIdAndId( - const oatpp::String& userId, const oatpp::String& id, - const oatpp::provider::ResourceHandle& - connection = nullptr); - oatpp::Object>> getAllUserStories( - const oatpp::String& userId, const oatpp::UInt32& offset, - const oatpp::UInt32& limit); - oatpp::Object deleteStoryByUserIdAndId( - const oatpp::String& userId, const oatpp::String& id); -}; - -#endif // HEAL_SERVICE_STORYSERVICE_HPP diff --git a/src/utils/constant.hpp b/src/utils/constant.hpp index 86f10e34..5acda270 100644 --- a/src/utils/constant.hpp +++ b/src/utils/constant.hpp @@ -78,6 +78,9 @@ class constants { static constexpr const char* LITHIUM_MODULE_LOADER = "lithium.addon.loader"; static constexpr const char* LITHIUM_ADDON_MANAGER = "lithium.addon.addon"; static constexpr const char* LITHIUM_UTILS_ENV = "lithium.utils.env"; + + static std::vector LITHIUM_RESOURCES; + static std::vector LITHIUM_RESOURCES_SHA256; }; #ifdef _WIN32 @@ -102,4 +105,6 @@ std::vector constants::COMPILER_PATHS = {"/usr/bin", "/usr/local/bin"}; #endif + + #endif // LITHIUM_UTILS_CONSTANTS_HPP diff --git a/src/utils/resource.hpp b/src/utils/resource.hpp new file mode 100644 index 00000000..e9595e3a --- /dev/null +++ b/src/utils/resource.hpp @@ -0,0 +1,41 @@ +/* + * resource.hpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2024-3-16 + +Description: Resource List for Lithium + +**************************************************/ + +#ifndef LITHIUM_UTILS_RESOURCE_HPP +#define LITHIUM_UTILS_RESOURCE_HPP + +#include +#include + +class resource { +public: + static std::unordered_map> + LITHIUM_RESOURCES; + + static constexpr const char* LITHIUM_RESOURCE_SERVER = + "https://github/ElementAstro/LithiumPackage"; +}; + +std::unordered_map> + resource::LITHIUM_RESOURCES = {{ +#ifdef _WIN32 + "lithium_server.exe" +#else + "lithium_server" +#endif + , + {"", false}}}; + +#endif \ No newline at end of file