From 39197a697c400665834fad7989325e9b64f94bd6 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Mon, 13 Jul 2026 18:10:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=8A=9B=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.json | 18 +- main.cmake | 44 +- .../Data_Source/Data_Source_Handler.cpp | 19 +- module/Local_Server/server/Config.cpp | 17 +- module/Local_Server/server/With_Loop_Coro.cpp | 2 +- module/Local_Server/server/io_coro.cpp | 82 +- module/Local_Server/server/io_coro.h | 20 +- module/Local_Server/server/server.cpp | 807 +++++++++--------- module/Local_Server_main.cpp | 42 +- module/dll_source/main.cpp | 80 +- 10 files changed, 603 insertions(+), 528 deletions(-) diff --git a/config/config.json b/config/config.json index 49d2622..3478a56 100644 --- a/config/config.json +++ b/config/config.json @@ -79,9 +79,9 @@ "tcp_server_default_connect_system_buffer_size": 409600, "list": [ { - "key": "Port_10003", - "enable": false, "type": "Data_Feed_TCP_Server", + "key": "Port_10003", + "enable": true, "output_format": { "type": "BIN", "use_status": true, @@ -94,9 +94,9 @@ "connect_system_buffer_size": 409600 }, { + "type": "Data_Feed_UDP_Server", "key": "22333", "enable": false, - "type": "Data_Feed_UDP_Server", "output_format": { "type": "BIN", "use_status": false, @@ -107,9 +107,9 @@ "port": 50001 }, { + "type": "Data_Feed_UDP_Client", "key": "Port_10004", "enable": false, - "type": "Data_Feed_UDP_Client", "output_format": { "type": "AVR", "use_status": false, @@ -121,9 +121,9 @@ "url": "192.168.1.75" }, { + "type": "Data_Feed_TCP_Client", "key": "Port_10005", "enable": false, - "type": "Data_Feed_TCP_Client", "output_format": { "type": "BIN", "use_status": true, @@ -135,9 +135,9 @@ "port": 10005 }, { + "type": "Data_Feed_TCP_Server", "key": "Port_30003", "enable": false, - "type": "Data_Feed_TCP_Server", "output_format": { "type": "SBS", "use_status": false, @@ -154,9 +154,9 @@ "data_source": { "list": [ { - "key": "lzy_dll", - "enable": false, "type": "Dll_Data_Source", + "key": "lzy_dll", + "enable": true, "base_station_show": true, "aircraft_show": true, "color": "#454641", @@ -175,9 +175,9 @@ "buffer_size": 200000 }, { + "type": "File_Data_Source", "key": "aaaa", "enable": false, - "type": "File_Data_Source", "base_station_show": true, "aircraft_show": true, "color": "#d1a54c", diff --git a/main.cmake b/main.cmake index 5877e00..5d0059c 100644 --- a/main.cmake +++ b/main.cmake @@ -15,6 +15,7 @@ if (1) else () set(cfg_dir ${CMAKE_CURRENT_LIST_DIR}/config) endif () + set(data_dir ${CMAKE_CURRENT_LIST_DIR}/data) _create("dll" dll_source) _create("exe" data_process) _attach_include_dir(dll_source "${md}") @@ -23,7 +24,9 @@ if (1) _attach_source_dir(data_process "${md}/dll_source") _depend(dll_source ${Core}) _depend(data_process ${Core}) - _attach_post_build_file(dll_source ${cfg_dir}/data_progress_config.json + _attach_post_build_file(dll_source + ${cfg_dir}/data_progress_config.json + ${data_dir}/BIN_Blank_Text/ADS-B_195_0205.txt # "${CMAKE_CURRENT_LIST_DIR}/data/BIN_Blank_Text/ADS-B_195_0205.txt" ) _create("dll" mlat_source) @@ -54,19 +57,36 @@ if (1) _attach_source_file(ecap_server "${md}/Local_Server_main.cpp") _attach_post_build_file(ecap_server ${cfg_dir}/config.json) - if (MSVC) - target_compile_options(ecap_server PRIVATE /fsanitize=address /Zi) - target_link_options(ecap_server PRIVATE /INCREMENTAL:NO /DEBUG) - - else () - - # target_compile_options(ecap_server PRIVATE -fsanitize=address -fno-omit-frame-pointer -g) - # - # target_link_options(ecap_server PRIVATE -fsanitize=address) - - endif () + # if (MSVC) + # + # target_compile_options(ecap_server PRIVATE /fsanitize=address /Zi) + # + # target_link_options(ecap_server PRIVATE /INCREMENTAL:NO /DEBUG) + # get_filename_component(_msvc_bin_dir "${CMAKE_CXX_COMPILER}" DIRECTORY) + # find_file(ASAN_RUNTIME_DLL + # NAMES clang_rt.asan_dbg_dynamic-x86_64.dll + # PATHS "${_msvc_bin_dir}" + # NO_DEFAULT_PATH + # REQUIRED + # ) + # if (NOT ASAN_RUNTIME_DLL) + # message(FATAL_ERROR "找不到 ASan 运行库: clang_rt.asan_dbg_dynamic-x86_64.dll,搜索目录: ${_msvc_bin_dir}") + # endif () + # add_custom_command(TARGET ecap_server POST_BUILD + # COMMAND "${CMAKE_COMMAND}" -E copy_if_different + # "${ASAN_RUNTIME_DLL}" + # "$" + # VERBATIM + # ) + # else () + # + # # target_compile_options(ecap_server PRIVATE -fsanitize=address -fno-omit-frame-pointer -g) + # # + # # target_link_options(ecap_server PRIVATE -fsanitize=address) + # + # endif () if (UNIX AND NOT APPLE) diff --git a/module/Local_Server/Data_Source/Data_Source_Handler.cpp b/module/Local_Server/Data_Source/Data_Source_Handler.cpp index 07fd2bf..9dbf100 100644 --- a/module/Local_Server/Data_Source/Data_Source_Handler.cpp +++ b/module/Local_Server/Data_Source/Data_Source_Handler.cpp @@ -93,12 +93,29 @@ std::shared_ptr Data_Source_Handler::create_msg(std::string_view packe return nullptr; } +extern bool data_source_debug; + size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data) { // 先读取原始数据 注意多复制了一遍 std::string mode_data(origin_data); + + std::string name = type + "_" + key; + if (data_source_debug) { + std::cout << "before origin_data_transform_mode_data " << VAR_STR_2(name, mode_data.size()) << std::endl; + } + origin_data_transform_mode_data(mode_data); + + if (data_source_debug) { + std::cout << " after origin_data_transform_mode_data " << VAR_STR_2(name, mode_data.size()) << + key << std::endl; + } static Value_Growth_Multi_T mt; auto t = key; + + if (data_source_debug) { + std::cout << name << " 读取到:" << VAR_STR_2(key, mode_data.size()) << " " << std::endl; + } if (mt.test(key, mode_data.size())) { std::cout << VAR_STR_2(key, mode_data.size()) << " 数据增长过快,可能内存积压" << std::endl; } @@ -124,8 +141,6 @@ size_t Data_Source_Handler::process_mode_acs_data(std::string_view origin_data) } - - SSR::Binary_Format_handle_buffer( source->buffer, mode_data, [this, source, &ret](std::string &packet) { ret++; diff --git a/module/Local_Server/server/Config.cpp b/module/Local_Server/server/Config.cpp index f097942..615ac1a 100644 --- a/module/Local_Server/server/Config.cpp +++ b/module/Local_Server/server/Config.cpp @@ -9,9 +9,10 @@ std::string default_config_path; std::string get_config_path() { -#ifdef WIN32 - return "D:/ae/proj/projects/ECAP_Server/config/config.json"; -#endif + // #ifdef WIN32 + // get_exe_dir() + // return "D:/ae/proj/projects/ECAP_Server/config/config.json"; + // #endif static bool first = true; if (!default_config_path.empty()) return default_config_path; @@ -55,7 +56,7 @@ void Device_Config::server(Global *g) { svr.Post(api + "get_net_adapter_list", [this](HTTP_Param) { JSON ret = JSON::object(); auto arr = JSON::array(); - for (auto &it : Psc::get_net_adapter_info_map()) { + for (auto &it: Psc::get_net_adapter_info_map()) { arr.append(it.second.to_Json()); } ret.append({"list", arr}); @@ -66,14 +67,13 @@ void Device_Config::server(Global *g) { CHECK_JSON_PARAM JSON old_device_config; { - old_device_config = to_base_json(); } HTTP_REQUIRE_PTR(net, params.get("net")) Net_Config device, wifi; bool has_device = false; bool has_wifi = false; - for (const auto &it : net->children) { + for (const auto &it: net->children) { HTTP_REQUIRE_VALUE(net_key, it.try_get_string("key")) if (net_key == "device") { device.from_base_json(&it); @@ -94,7 +94,7 @@ void Device_Config::server(Global *g) { if (!it1 || !it2 || !p1 || !p2) { server_logger->error("", {}, LOG_POS + " ip port! " + device.ip + ":" + - std::to_string(device.port)); + std::to_string(device.port)); res->setBody(warp(old_device_config).to_json_string()); return; } @@ -102,10 +102,9 @@ void Device_Config::server(Global *g) { #if WIN32 bool use = false; #else - bool use = true; + bool use = true; #endif { - auto &w = *this; *w.list.get("device").value() = device; *w.list.get("wifi").value() = wifi; diff --git a/module/Local_Server/server/With_Loop_Coro.cpp b/module/Local_Server/server/With_Loop_Coro.cpp index 4606689..5b81ec6 100644 --- a/module/Local_Server/server/With_Loop_Coro.cpp +++ b/module/Local_Server/server/With_Loop_Coro.cpp @@ -30,7 +30,7 @@ bool With_Loop_Coro::running() const { void With_Loop_Coro::set_state(State state, std::string_view action) { if (!action.empty()) { std::string name = type + "_" + key; - std::cout << std::format("{} {} {} ==> {} \n", name, action, Psc::to_string(this->state), + std::cout << std::format("协程状态机 {} {} {} ==> {} \n", name, action, Psc::to_string(this->state), Psc::to_string(state)); } this->state = state; diff --git a/module/Local_Server/server/io_coro.cpp b/module/Local_Server/server/io_coro.cpp index 0cc241d..f5e80c4 100644 --- a/module/Local_Server/server/io_coro.cpp +++ b/module/Local_Server/server/io_coro.cpp @@ -45,15 +45,28 @@ bool Coro::has_running_loop_tasks() { return false; } +bool data_feed_debug = false; +bool data_source_debug = false; +// 不开启wait 性能巨差 数据积压 +bool wait = true; + void Coro::start() { - std::cout << "start_io_coro" << std::endl; + std::cout << "1================ start_io_coro" << std::endl; running.store(true, std::memory_order_release); io.restart(); io_work = std::make_unique >(io.get_executor()); io_thread = std::thread([this] { - std::cout << std::format("协程io:{} 协程启动!\n", thread_id_str()); - io.run(); - std::cout << std::format("协程io:{} 销毁!\n", thread_id_str()); + try { + std::cout << std::format("协程io:{} 协程启动!\n", thread_id_str()); + io.run(); + std::cout << std::format("协程io:{} 销毁!\n", thread_id_str()); + } catch (const std::exception &e) { + std::cerr << std::format("协程io异常: {}\n", e.what()); + std::terminate(); + } catch (...) { + std::cerr << "协程io未知异常\n"; + std::terminate(); + } }); auto n = std::max(1, std::thread::hardware_concurrency()); auto other_need = std::max(2, n / 2); @@ -65,7 +78,17 @@ void Coro::start() { n = std::max(1, n); process_data = std::make_unique(n); std::cout << std::format("协程已经启动 process_data concurrency: 在n个线程上{}\n", n); - data_feed_thread_task = std::make_unique >(asio::co_spawn(io, coro_thread(), asio::use_future)); + + auto promise = std::make_shared >(); + loop_task = std::make_unique >(promise->get_future()); + asio::co_spawn(io, coro_thread(), [promise](std::exception_ptr ep) { + if (ep) { + promise->set_exception(ep); + std::rethrow_exception(ep); + } + promise->set_value(); + }); + std::cout << std::flush; } asio::awaitable Coro::sleep_for(std::chrono::milliseconds ms) { @@ -92,10 +115,10 @@ void Coro::stop() { running = false; asio::post(io, [] { }); - if (data_feed_thread_task) { + if (loop_task) { std::cout << "等待 coro_thread 退出" << std::endl; - data_feed_thread_task->get(); - data_feed_thread_task.reset(); + loop_task->get(); + loop_task.reset(); std::cout << "coro_thread 已退出" << std::endl; } // 清理资源 @@ -125,7 +148,6 @@ asio::awaitable Coro::coro_thread() { co_return; } -bool data_feed_debug = false; asio::awaitable Data_Feed::loop_coro() { auto feed = this; @@ -191,9 +213,6 @@ asio::awaitable Data_Feed::loop_coro() { co_return; } -bool data_source_debug = false; -// 不开启wait 性能巨差 数据积压 -bool wait = true; asio::awaitable Data_Source::loop_coro() { auto source = this; @@ -202,43 +221,49 @@ asio::awaitable Data_Source::loop_coro() { co->process_data->get_executor()); while (source->running()) { if (data_source_debug) { - std::cout << std::format("{} source loop begin {}\n", key, thread_id_str()); + std::cout << std::format("[1] ds:{} source loop begin {}\n", key, thread_id_str()) << std::flush;; } if (!source->running() || !source->registered()) { break; } if (data_source_debug) { - std::cout << std::format("{} before handle {}\n", key, thread_id_str()); + std::cout << std::format("[2] ds:{} before handle thread:{}\n", key, thread_id_str()) << std::flush;; } co_await source->handle_in_loop_coro(); if (!enable || !source->running() || !source->registered()) { break; } if (data_source_debug) { - std::cout << std::format("{} before read {}\n", key, thread_id_str()); + std::cout << std::format("[3] ds:{} before read thread:{}\n", key, thread_id_str()) << std::flush;; } auto mode_data = co_await source->read_coro(); if (data_source_debug) { - std::cout << std::format("{} after read {}\n", key, thread_id_str()); + std::cout << std::format("[4] ds:{} after read thread:{}\n", key, thread_id_str()) << std::flush;; } if (wait) { co_await resume_on(co->process_data->get_executor()); if (data_source_debug) { - std::cout << std::format("{} before process {}\n", key, thread_id_str()); + std::cout << std::format("wait [5] ds:{} before process {} thread:{} \n", key, thread_id_str(), + mode_data.size()) << + std::flush;; } auto num = source->process_mode_acs_data(mode_data); if (data_source_debug) { - std::cout << std::format("{} after process {} {}\n", key, num, thread_id_str()); + std::cout << std::format("[6] ds:{} after process {} {}\n", key, num, thread_id_str()) << std::flush;; } co_await resume_on(co->io.get_executor()); static Frequency_Limit_Multi mt(0.1); auto name = type + ":" + key; if (mt.test(name)) { if (num == 0) { - std::cout << std::format("{} 没解析到数据睡眠10ms {} {}\n", name, num, thread_id_str()); + if (data_source_debug) + std::cout << std::format("[7] {} 没解析到数据睡眠10ms {} {}\n", name, num, + thread_id_str()) << std::flush;; ask_sleep = true; } else { - std::cout << std::format("{} 解析到数据 {} {}\n", name, num, thread_id_str()); + if (data_source_debug) + std::cout << std::format("[7] {} 解析到数据 {} {}\n", name, num, + thread_id_str()) << std::flush;; } } if (num == 0) { @@ -246,29 +271,31 @@ asio::awaitable Data_Source::loop_coro() { ask_sleep = false; } } else { - asio::post(*process_strand, [this, source, process_strand, mode_data = std::move(mode_data)]() mutable { + asio::post(*process_strand, [this, source, mode_data = std::move(mode_data)]() mutable { try { if (data_source_debug) { - std::cout << std::format("{} before process {}\n", source->key, thread_id_str()); + std::cout << std::format("no wait [5] ds:{} before process {} size:{}\n", source->key, + thread_id_str(), + mode_data.size()); } auto num = source->process_mode_acs_data(mode_data); if (data_source_debug) { - std::cout << std::format("{} after process {} {}\n", source->key, num, thread_id_str()); + std::cout << std::format("[6] ds:{} after process {} {}\n", source->key, num, thread_id_str()); } static Frequency_Limit_Multi mt(0.1); auto name = source->type + ":" + source->key; if (mt.test(name)) { if (num == 0) { - std::cout << std::format("{} 没解析到数据 {} {}\n", name, num, thread_id_str()); + std::cout << std::format("[7] {} 没解析到数据 {} {}\n", name, num, thread_id_str()); ask_sleep = true; } else { - std::cout << std::format("{} 解析到数据 {} {}\n", name, num, thread_id_str()); + std::cout << std::format("[8] {} 解析到数据 {} {}\n", name, num, thread_id_str()); } } } catch (const std::exception &e) { - std::cout << std::format("{} process exception: {}\n", source->key, e.what()); + std::cout << std::format("[9] {} process exception: {}\n", source->key, e.what()); } catch (...) { - std::cout << std::format("{} process unknown exception\n", source->key); + std::cout << std::format("[9] {} process unknown exception\n", source->key); } }); co_await asio::post(co->io, asio::use_awaitable); @@ -277,6 +304,7 @@ asio::awaitable Data_Source::loop_coro() { ask_sleep = false; } } + std::cout << std::flush; } std::cout << std::format("{} source loop exit {}\n", key, thread_id_str()); co_return; diff --git a/module/Local_Server/server/io_coro.h b/module/Local_Server/server/io_coro.h index 30082de..61875f2 100644 --- a/module/Local_Server/server/io_coro.h +++ b/module/Local_Server/server/io_coro.h @@ -13,29 +13,39 @@ #include #include "asio/bind_executor.hpp" #include "psc_global_include/Singleton.hpp" + class Coro : public Psc::Singleton { public: void start(); + void stop(); + asio::awaitable sleep_for(std::chrono::milliseconds ms); + asio::io_context io; std::unique_ptr process_data; - template - std::shared_ptr> spawn(Awaitable&& awaitable) { + + template + std::shared_ptr > spawn(Awaitable &&awaitable) { auto future = asio::co_spawn(io, std::forward(awaitable), asio::use_future); - return std::make_shared>(std::move(future)); + return std::make_shared >(std::move(future)); } + private: asio::awaitable coro_thread(); + bool has_running_loop_tasks(); - std::unique_ptr> io_work; + + std::unique_ptr > io_work; std::thread io_thread; - std::unique_ptr> data_feed_thread_task; + std::unique_ptr > loop_task; std::atomic running = false; }; + inline asio::awaitable resume_on(asio::any_io_executor ex) { co_await asio::post(asio::bind_executor(ex, asio::deferred)); } + inline asio::awaitable dispatch_on(asio::any_io_executor ex) { co_await asio::dispatch(asio::bind_executor(ex, asio::deferred)); } diff --git a/module/Local_Server/server/server.cpp b/module/Local_Server/server/server.cpp index b738f3c..aa1563b 100644 --- a/module/Local_Server/server/server.cpp +++ b/module/Local_Server/server/server.cpp @@ -7,151 +7,153 @@ #include namespace { + constexpr std::size_t kMaxLogRequestBodySize = 8 * 1024; -constexpr std::size_t kMaxLogRequestBodySize = 8 * 1024; + void Log_Request_Body_If_Small(const drogon::HttpRequestPtr &request) { + const auto &body = request->getBody(); + if (body.empty()) { + return; + } -void Log_Request_Body_If_Small(const drogon::HttpRequestPtr &request) { - const auto &body = request->getBody(); - if (body.empty()) { - return; - } - - if (body.size() <= kMaxLogRequestBodySize) { - LOG_INFO << "[request body] " + if (body.size() <= kMaxLogRequestBodySize) { + LOG_INFO << "[request body] " << "path=" << request->path() << ", size=" << body.size() << ", body=" << std::string(body.data(), body.size()); - } else { - LOG_INFO << "[request body skipped] " + } else { + LOG_INFO << "[request body skipped] " << "path=" << request->path() << ", size=" << body.size() << ", max=" << kMaxLogRequestBodySize; + } } -} -bool Is_Invalid_Http_Param(const std::exception &e) { - return dynamic_cast(&e) != nullptr || - dynamic_cast(&e) != nullptr || - dynamic_cast(&e) != nullptr; -} - -bool Is_Safe_Version_Directory_Name(std::string_view name) { - if (name.empty() || name == "." || name == "..") { - return false; + bool Is_Invalid_Http_Param(const std::exception &e) { + return dynamic_cast(&e) != nullptr || + dynamic_cast(&e) != nullptr || + dynamic_cast(&e) != nullptr; } - return std::ranges::all_of(name, [](unsigned char ch) { - return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; - }); -} -bool Is_Safe_Archive_Extension(std::string_view extension) { - if (extension.empty() || extension.front() == '.' || - extension.back() == '.') { - return false; + bool Is_Safe_Version_Directory_Name(std::string_view name) { + if (name.empty() || name == "." || name == "..") { + return false; + } + return std::ranges::all_of(name, [](unsigned char ch) { + return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; + }); } - return std::ranges::all_of(extension, [](unsigned char ch) { - return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; - }); -} -std::string Normalize_Archive_Extension(std::string_view extension, - std::string_view fallback = "zip") { - auto normalized = std::string(extension); - while (!normalized.empty() && normalized.front() == '.') { - normalized.erase(normalized.begin()); + bool Is_Safe_Archive_Extension(std::string_view extension) { + if (extension.empty() || extension.front() == '.' || + extension.back() == '.') { + return false; + } + return std::ranges::all_of(extension, [](unsigned char ch) { + return std::isalnum(ch) != 0 || ch == '.' || ch == '_' || ch == '-'; + }); } - if (normalized.empty()) { - normalized = std::string(fallback); - } - if (!Is_Safe_Archive_Extension(normalized)) { - throw std::invalid_argument("invalid archive extension: " + normalized); - } - return normalized; -} -std::optional Try_Get_String_Field(const JSON &object, - std::string_view key) { - const JSON *value = object.get(key); - if (value == nullptr) { - return std::nullopt; + std::string Normalize_Archive_Extension(std::string_view extension, + std::string_view fallback = "zip") { + auto normalized = std::string(extension); + while (!normalized.empty() && normalized.front() == '.') { + normalized.erase(normalized.begin()); + } + if (normalized.empty()) { + normalized = std::string(fallback); + } + if (!Is_Safe_Archive_Extension(normalized)) { + throw std::invalid_argument("invalid archive extension: " + normalized); + } + return normalized; } - if (value->valueType != Psc::String) { - throw std::invalid_argument(std::string(key) + " must be a string"); + + std::optional Try_Get_String_Field(const JSON &object, + std::string_view key) { + const JSON *value = object.get(key); + if (value == nullptr) { + return std::nullopt; + } + if (value->valueType != Psc::String) { + throw std::invalid_argument(std::string(key) + " must be a string"); + } + return value->val; } - return value->val; -} -struct Archive_Export_Request { - std::string version; - Archive_Write_Options archive; -}; + struct Archive_Export_Request { + std::string version; + Archive_Write_Options archive; + }; -Archive_Export_Request -Parse_Archive_Export_Request(const drogon::HttpRequestPtr &req, - std::string_view default_version) { - Archive_Export_Request result; - result.version = std::move(default_version); + Archive_Export_Request + Parse_Archive_Export_Request(const drogon::HttpRequestPtr &req, + std::string_view default_version) { + Archive_Export_Request result; + result.version = std::move(default_version); + + const auto &body = req->getBody(); + if (body.empty()) { + return result; + } + + auto parsed = Psc::try_parse_json(body.data()); + if (!parsed.has_value()) { + throw_invalid_http_param("request body is not valid JSON"); + } + + const JSON ¶ms = parsed.value(); + if (auto version = Try_Get_String_Field(params, "version")) { + if (!version->empty()) { + result.version = *version; + } + } + if (!Is_Safe_Version_Directory_Name(result.version)) { + throw std::invalid_argument("invalid version name: " + result.version); + } + + if (auto format = Try_Get_String_Field(params, "format")) { + if (!format->empty()) { + result.archive.format = *format; + } + } + if (auto filter = Try_Get_String_Field(params, "filter")) { + result.archive.filter = *filter; + } + if (auto extension = Try_Get_String_Field(params, "extension")) { + if (!extension->empty()) { + result.archive.extension = Normalize_Archive_Extension(*extension); + } + } else { + result.archive.extension = + Normalize_Archive_Extension(result.archive.extension); + } - const auto &body = req->getBody(); - if (body.empty()) { return result; } - auto parsed = Psc::try_parse_json(body.data()); - if (!parsed.has_value()) { - throw_invalid_http_param("request body is not valid JSON"); + const Archive_Layout_Rules &Upgrade_Zip_Layout_Rules() { + static const Archive_Layout_Rules rules = [] { + Archive_Layout_Rules value; + value.directories = { + { + "", + {"adsb_cfg.ini", "config.json", "ecap_server", "lib9002config.json"}, + {"lib9002", "wwwroot"}, + {}, + {} + }, + {"lib9002", {"lib9002.so", "testserver"}, {"env"}, {}, {}} + }; + return value; + }(); + return rules; } - - const JSON ¶ms = parsed.value(); - if (auto version = Try_Get_String_Field(params, "version")) { - if (!version->empty()) { - result.version = *version; - } - } - if (!Is_Safe_Version_Directory_Name(result.version)) { - throw std::invalid_argument("invalid version name: " + result.version); - } - - if (auto format = Try_Get_String_Field(params, "format")) { - if (!format->empty()) { - result.archive.format = *format; - } - } - if (auto filter = Try_Get_String_Field(params, "filter")) { - result.archive.filter = *filter; - } - if (auto extension = Try_Get_String_Field(params, "extension")) { - if (!extension->empty()) { - result.archive.extension = Normalize_Archive_Extension(*extension); - } - } else { - result.archive.extension = - Normalize_Archive_Extension(result.archive.extension); - } - - return result; -} - -const Archive_Layout_Rules &Upgrade_Zip_Layout_Rules() { - static const Archive_Layout_Rules rules = [] { - Archive_Layout_Rules value; - value.directories = { - {"", - {"adsb_cfg.ini", "config.json", "ecap_server", "lib9002config.json"}, - {"lib9002", "wwwroot"}, - {}, - {}}, - {"lib9002", {"lib9002.so", "testserver"}, {"env"}, {}, {}}}; - return value; - }(); - return rules; -} - } // namespace void setupCors(); + void Global::init_web_server() { register_http_performance_monitor( - http_monitor_config.access_log, - http_monitor_config.slow_request_threshold_ms); + http_monitor_config.access_log, + http_monitor_config.slow_request_threshold_ms); setupCors(); static auto &web_server = web_server_config; Web_Server &svr = this->svr; @@ -162,7 +164,7 @@ void Global::init_web_server() { std::string content; httplib::detail::read_file(path, content); auto content_type = httplib::detail::find_content_type( - path, {}, "application/octet-stream"); + path, {}, "application/octet-stream"); res->setContentTypeString(content_type); res->setBody(content); // res.set_file_content(path); @@ -178,61 +180,61 @@ void Global::init_web_server() { }; auto add_path = [return_file](std::string_view path) { drogon::app().registerHandlerViaRegex( - std::string(path), - [return_file]( - const drogon::HttpRequestPtr &req, - std::function &&callback) { - callback(return_file(web_server.get_true_webapp() + "/index.html")); - }, - {drogon::Get}); - }; - - drogon::app().registerHandlerViaRegex( - R"(^/tiles/.*$)", + std::string(path), [return_file]( - const drogon::HttpRequestPtr &req, - std::function &&callback) { - auto path = web_server.get_true_tiles() + req->getPath().substr(6); - callback(return_file(path)); - }, - {drogon::Get}); - - drogon::app().registerHandlerViaRegex( - "/", - [return_file]( - const drogon::HttpRequestPtr &req, - std::function &&callback) { + const drogon::HttpRequestPtr &req, + std::function &&callback) { callback(return_file(web_server.get_true_webapp() + "/index.html")); }, {drogon::Get}); + }; + + drogon::app().registerHandlerViaRegex( + R"(^/tiles/.*$)", + [return_file]( + const drogon::HttpRequestPtr &req, + std::function &&callback) { + auto path = web_server.get_true_tiles() + req->getPath().substr(6); + callback(return_file(path)); + }, + {drogon::Get}); + + drogon::app().registerHandlerViaRegex( + "/", + [return_file]( + const drogon::HttpRequestPtr &req, + std::function &&callback) { + callback(return_file(web_server.get_true_webapp() + "/index.html")); + }, + {drogon::Get}); add_path(R"(^/settings)"); add_path(R"(^/map)"); add_path(R"(^/dsp)"); add_path(R"(^/aircraftlist)"); drogon::app().registerHandlerViaRegex( - R"(^/ui(/.*)?$)", - [return_file]( - const drogon::HttpRequestPtr &req, - std::function &&callback) { - std::cout << req->path() << std::endl; - auto res = drogon::HttpResponse::newHttpResponse(); - auto path = web_server.get_true_webapp(); - auto rp = "/" + req->path().substr(3); - if (rp == "/") { - path += "/index.html"; - } else { - path += rp; - } - callback(return_file(path)); - }); + R"(^/ui(/.*)?$)", + [return_file]( + const drogon::HttpRequestPtr &req, + std::function &&callback) { + std::cout << req->path() << std::endl; + auto res = drogon::HttpResponse::newHttpResponse(); + auto path = web_server.get_true_webapp(); + auto rp = "/" + req->path().substr(3); + if (rp == "/") { + path += "/index.html"; + } else { + path += rp; + } + callback(return_file(path)); + }); State_Report::instance(); svr.Get(R"(/get_debug_info)", [](HTTP_Param) { JSON arr = JSON::array(); auto &sp = Global::instance()->mode_acs.data_feed_config.pool_; arr.append(JSON::object( - {{"remain_size", sp.remain_size()}, {"free_size", sp.free_size()}})); + {{"remain_size", sp.remain_size()}, {"free_size", sp.free_size()}})); res->setBody(arr.to_json_string("", "\n", "")); }); @@ -243,97 +245,97 @@ void Global::init_web_server() { mode_acs.server(this); dsp_config.server(this); + // s.w.init(); drogon::app().registerHandler( - api + "export_logs", - [](const drogon::HttpRequestPtr &req, - std::function &&cb) { - try { - auto export_request = - Parse_Archive_Export_Request(req, Global::instance()->version); - std::string name = export_request.version; - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - std::string data = archive_directory_to_memory( - version_dir / name / "logs", {}, export_request.archive); - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setBody(data); - resp->setContentTypeString("application/octet-stream"); - resp->addHeader("Content-Disposition", - "attachment; filename*=UTF-8''" + name + "_logs." + - std::string(export_request.archive.extension)); - resp->addHeader("ok", "true"); - cb(resp); - } - - catch (const std::exception &e) { - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->addHeader("ok", "false"); - Psc::JSON json = - JSON::object({{"message", Psc::platform_2_utf8(e.what())}}); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(json.to_json_string()); - cb(resp); - } - }); + api + "export_logs", + [](const drogon::HttpRequestPtr &req, + std::function &&cb) { + try { + auto export_request = + Parse_Archive_Export_Request(req, Global::instance()->version); + std::string name = export_request.version; + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + std::string data = archive_directory_to_memory( + version_dir / name / "logs", {}, export_request.archive); + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setBody(data); + resp->setContentTypeString("application/octet-stream"); + resp->addHeader("Content-Disposition", + "attachment; filename*=UTF-8''" + name + "_logs." + + std::string(export_request.archive.extension)); + resp->addHeader("ok", "true"); + cb(resp); + } catch (const std::exception &e) { + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->addHeader("ok", "false"); + Psc::JSON json = + JSON::object({{"message", Psc::platform_2_utf8(e.what())}}); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(json.to_json_string()); + cb(resp); + } + }); drogon::app().registerHandler( - api + "export_version", - [](const drogon::HttpRequestPtr &req, - std::function &&cb) { - try { - auto export_request = - Parse_Archive_Export_Request(req, Global::instance()->version); - std::string name = export_request.version; - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + api + "export_version", + [](const drogon::HttpRequestPtr &req, + std::function &&cb) { + try { + auto export_request = + Parse_Archive_Export_Request(req, Global::instance()->version); + std::string name = export_request.version; + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - std::cout << "准备压缩:" << std::endl; - std::string data = archive_directory_to_memory( - version_dir / name, - {"logs/", "uploads/", "drogon_uploads/", - "backups/", // ghw的什么文件路径 - "stack_trace.txt", "pt.log", "ecap_server.log", "Core", "core", - name + ".zip", name + "." + std::string(export_request.archive.extension)}, - export_request.archive); - std::cout << "压缩成功:" << data.size() << std::endl; - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setBody(data); - resp->setContentTypeString("application/octet-stream"); - resp->addHeader("Content-Disposition", - "attachment; filename*=UTF-8''" + name + "." + - std::string(export_request.archive.extension)); - resp->addHeader("ok", "true"); - cb(resp); - } catch (const std::exception &e) { - auto message = Psc::platform_2_utf8(e.what()); - std::cout << "导出异常触发:" << message << " " << LOG_POS - << std::endl; - auto resp = drogon::HttpResponse::newHttpResponse(); + std::cout << "准备压缩:" << std::endl; + std::string data = archive_directory_to_memory( + version_dir / name, + { + "logs/", "uploads/", "drogon_uploads/", + "backups/", // ghw的什么文件路径 + "stack_trace.txt", "pt.log", "ecap_server.log", "Core", "core", + name + ".zip", name + "." + std::string(export_request.archive.extension) + }, + export_request.archive); + std::cout << "压缩成功:" << data.size() << std::endl; + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setBody(data); + resp->setContentTypeString("application/octet-stream"); + resp->addHeader("Content-Disposition", + "attachment; filename*=UTF-8''" + name + "." + + std::string(export_request.archive.extension)); + resp->addHeader("ok", "true"); + cb(resp); + } catch (const std::exception &e) { + auto message = Psc::platform_2_utf8(e.what()); + std::cout << "导出异常触发:" << message << " " << LOG_POS + << std::endl; + auto resp = drogon::HttpResponse::newHttpResponse(); - Psc::JSON json = JSON::object({{"message", message}}); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(json.to_json_string()); - resp->addHeader("ok", "false"); - cb(resp); - } - }); + Psc::JSON json = JSON::object({{"message", message}}); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(json.to_json_string()); + resp->addHeader("ok", "false"); + cb(resp); + } + }); drogon::app().registerHandler(api + "restart_device", [](const drogon:: - HttpRequestPtr - &req, + HttpRequestPtr + &req, std::function - &&cb) { - + const drogon:: + HttpResponsePtr + &)> + &&cb) { #ifdef __linux__ std::string root_dir = Psc::get_exe_dir() + "/.."; std::string log_file = fmt::format("{}/restart_device.log", root_dir); std::string cmd = fmt::format( - R"(systemd-run --scope --slice=system.slice sudo bash "{}/restart_device.bash" > {} 2>&1 &)", - root_dir, log_file); + R"(systemd-run --scope --slice=system.slice sudo bash "{}/restart_device.bash" > {} 2>&1 &)", + root_dir, log_file); std::cout << "Generated Command: " << cmd << std::endl; std::system(cmd.c_str()); #endif @@ -344,111 +346,112 @@ void Global::init_web_server() { }); drogon::app().registerHandler( - api + "import_version", - [](const drogon::HttpRequestPtr &req, - std::function &&cb) { - try { - // ---------- 参数校验 ---------- - auto dir = req->getHeader("dir"); - if (!Is_Safe_Version_Directory_Name(dir)) { - throw std::invalid_argument("invalid or missing header: dir"); - } + api + "import_version", + [](const drogon::HttpRequestPtr &req, + std::function &&cb) { + try { + // ---------- 参数校验 ---------- + auto dir = req->getHeader("dir"); + if (!Is_Safe_Version_Directory_Name(dir)) { + throw std::invalid_argument("invalid or missing header: dir"); + } - const auto &body = req->getBody(); - auto archive_layout_result = validate_archive_layout_from_memory( - body.data(), body.size(), Upgrade_Zip_Layout_Rules()); - if (!archive_layout_result) { - throw Invalid_Archive_Error(archive_layout_result.error()); - } + const auto &body = req->getBody(); + auto archive_layout_result = validate_archive_layout_from_memory( + body.data(), body.size(), Upgrade_Zip_Layout_Rules()); + if (!archive_layout_result) { + throw Invalid_Archive_Error(archive_layout_result.error()); + } - auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); - // ---------- 路径准备 ---------- - auto targetDir = version_dir / dir; + auto version_dir = std::filesystem::path(get_exe_dir() + "/.."); + // ---------- 路径准备 ---------- + auto targetDir = version_dir / dir; - std::cout << "========dir====" << dir << std::endl; - std::cout << "========version_dir====" << version_dir << std::endl; - std::cout << "========targetDir====" << targetDir << std::endl; + std::cout << "========dir====" << dir << std::endl; + std::cout << "========version_dir====" << version_dir << std::endl; + std::cout << "========targetDir====" << targetDir << std::endl; - std::filesystem::create_directories(targetDir); + std::filesystem::create_directories(targetDir); - const auto archive_extension = - Normalize_Archive_Extension(req->getHeader("archive-extension")); - auto archivePath = targetDir / (dir + "." + archive_extension); + const auto archive_extension = + Normalize_Archive_Extension(req->getHeader("archive-extension")); + auto archivePath = targetDir / (dir + "." + archive_extension); - // ---------- 写 zip ---------- - std::ofstream ofs(archivePath, std::ios::binary); - if (!ofs) { - throw std::runtime_error("open archive failed: " + - archivePath.string()); - } + // ---------- 写 zip ---------- + std::ofstream ofs(archivePath, std::ios::binary); + if (!ofs) { + throw std::runtime_error("open archive failed: " + + archivePath.string()); + } - ofs.write(body.data(), body.size()); - if (!ofs) { - throw std::runtime_error("write archive failed: " + - archivePath.string()); - } - ofs.close(); - if (!ofs) { - throw std::runtime_error("close archive failed: " + - archivePath.string()); - } + ofs.write(body.data(), body.size()); + if (!ofs) { + throw std::runtime_error("write archive failed: " + + archivePath.string()); + } + ofs.close(); + if (!ofs) { + throw std::runtime_error("close archive failed: " + + archivePath.string()); + } #ifdef _WIN32 - std::string root_dir = version_dir.string(); - std::string old_version = - Global::instance()->version; // Global version info - std::string new_version = dir; - std::string log_file = fmt::format( - "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); - std::string cmd = fmt::format( - R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {{ . '{}/upgrade.legacy' '{}' '{}' > '{}' 2>&1 }}" )", - root_dir, old_version, new_version, log_file); + std::string root_dir = version_dir.string(); + std::string old_version = + Global::instance()->version; // Global version info + std::string new_version = dir; + std::string log_file = fmt::format( + "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); + std::string cmd = fmt::format( + R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {{ . '{}/upgrade.legacy' '{}' '{}' > '{}' 2>&1 }}" )", + root_dir, old_version, new_version, log_file); #else - std::string root_dir = version_dir.string(); - std::string old_version = - Global::instance()->version; // Global version info - std::string new_version = dir; - std::string log_file = fmt::format( - "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); - std::string cmd = fmt::format( - R"(systemd-run --scope --slice=system.slice sudo bash "{}/upgrade.bash" "{}" "{}" > {} 2>&1 &)", - root_dir, old_version, new_version, log_file); + std::string root_dir = version_dir.string(); + std::string old_version = + Global::instance()->version; // Global version info + std::string new_version = dir; + std::string log_file = fmt::format( + "{}/upgrade_{}_to_{}.log", root_dir, old_version, new_version); + std::string cmd = fmt::format( + R"(systemd-run --scope --slice=system.slice sudo bash "{}/upgrade.bash" "{}" "{}" > {} 2>&1 &)", + root_dir, old_version, new_version, log_file); #endif - std::cout << "Generated Command: " << cmd << std::endl; - std::system(cmd.c_str()); - // ---------- 成功响应 ---------- - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - resp->setBody(R"({"ok":true})"); - cb(resp); - } catch (const std::exception &e) { - auto resp = drogon::HttpResponse::newHttpResponse(); - const bool invalid_input = - dynamic_cast(&e) != nullptr || - dynamic_cast(&e) != nullptr; - resp->setStatusCode(invalid_input ? drogon::k400BadRequest - : drogon::k500InternalServerError); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - auto reason = Psc::platform_2_utf8(e.what()); - std::cout << "异常" << reason << std::endl; - Psc::JSON json = JSON::object({{"ok", false}, {"error", reason}}); - resp->setBody(json.to_json_string()); - cb(resp); - } - }, - {drogon::Post}); + std::cout << "Generated Command: " << cmd << std::endl; + std::system(cmd.c_str()); + // ---------- 成功响应 ---------- + auto resp = drogon::HttpResponse::newHttpResponse(); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + resp->setBody(R"({"ok":true})"); + cb(resp); + } catch (const std::exception &e) { + auto resp = drogon::HttpResponse::newHttpResponse(); + const bool invalid_input = + dynamic_cast(&e) != nullptr || + dynamic_cast(&e) != nullptr; + resp->setStatusCode(invalid_input + ? drogon::k400BadRequest + : drogon::k500InternalServerError); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + auto reason = Psc::platform_2_utf8(e.what()); + std::cout << "异常" << reason << std::endl; + Psc::JSON json = JSON::object({{"ok", false}, {"error", reason}}); + resp->setBody(json.to_json_string()); + cb(resp); + } + }, + {drogon::Post}); svr.Post(api + "get_debug_log", [](HTTP_Param) { CHECK_JSON_PARAM HTTP_REQUIRE_VALUE( - start_serial_number, - params.try_get_number("serial_number")) + start_serial_number, + params.try_get_number("serial_number")) auto log = base64_encode(debug_logger_info_manager.get_info(start_serial_number)); JSON ret = JSON::object(); ret.append({"log", log}); ret.append( - {"serial_number", debug_logger_info_manager.get_cur_serial_number()}); + {"serial_number", debug_logger_info_manager.get_cur_serial_number()}); ret.append({"start_serial_number", start_serial_number}); res->setBody(warp(ret).to_json_string()); }); @@ -461,7 +464,7 @@ void Global::init_web_server() { // ret.append({"飞机总数", db.get_aircraft_num()}); // ret.append({"解出位置的数量", db.have_pos_aircraft_num}); JSON arr = JSON::object(); - for (auto &ds : g->mode_acs.data_source_config.map.list()) { + for (auto &ds: g->mode_acs.data_source_config.map.list()) { if (!ds->enable) continue; arr.append({ds->key, ds->statistic_json()}); @@ -486,60 +489,60 @@ void Global::init_web_server() { }); da.setDefaultHandler( - [](const drogon::HttpRequestPtr &req, - std::function &&callback) { - LOG_WARN << "[http route not found] " - << "path=" << req->path(); + [](const drogon::HttpRequestPtr &req, + std::function &&callback) { + LOG_WARN << "[http route not found] " + << "path=" << req->path(); - auto res = drogon::HttpResponse::newHttpResponse(); + auto res = drogon::HttpResponse::newHttpResponse(); - res->setStatusCode(drogon::k404NotFound); - res->setBody("not found"); - res->addHeader("Content-Type", "text/plain; charset=utf-8"); + res->setStatusCode(drogon::k404NotFound); + res->setBody("not found"); + res->addHeader("Content-Type", "text/plain; charset=utf-8"); - callback(res); - }); + callback(res); + }); da.setCustomErrorHandler( - [](drogon::HttpStatusCode status, - const drogon::HttpRequestPtr &req) -> drogon::HttpResponsePtr { - LOG_WARN << "[http error] " - << "path=" << req->path() - << ", status=" << static_cast(status); + [](drogon::HttpStatusCode status, + const drogon::HttpRequestPtr &req) -> drogon::HttpResponsePtr { + LOG_WARN << "[http error] " + << "path=" << req->path() + << ", status=" << static_cast(status); - auto res = drogon::HttpResponse::newHttpResponse(); + auto res = drogon::HttpResponse::newHttpResponse(); - res->setStatusCode(status); - res->setBody("http error"); - res->addHeader("Content-Type", "text/plain; charset=utf-8"); + res->setStatusCode(status); + res->setBody("http error"); + res->addHeader("Content-Type", "text/plain; charset=utf-8"); - return res; - }); + return res; + }); da.setExceptionHandler( - [](const std::exception &e, const drogon::HttpRequestPtr &req, - std::function &&callback) { - auto res = drogon::HttpResponse::newHttpResponse(); + [](const std::exception &e, const drogon::HttpRequestPtr &req, + std::function &&callback) { + auto res = drogon::HttpResponse::newHttpResponse(); - if (Is_Invalid_Http_Param(e)) { - LOG_WARN << "[invalid http parameters] " - << "path=" << req->path() << ", detail=" << e.what(); - Log_Request_Body_If_Small(req); + if (Is_Invalid_Http_Param(e)) { + LOG_WARN << "[invalid http parameters] " + << "path=" << req->path() << ", detail=" << e.what(); + Log_Request_Body_If_Small(req); - res->setStatusCode(drogon::k400BadRequest); - res->setContentTypeCode(drogon::CT_APPLICATION_JSON); - res->setBody(R"({"code":400,"message":"invalid http parameters"})"); - } else { - LOG_ERROR << "[handler exception] " - << "path=" << req->path() << ", what=" << e.what(); + res->setStatusCode(drogon::k400BadRequest); + res->setContentTypeCode(drogon::CT_APPLICATION_JSON); + res->setBody(R"({"code":400,"message":"invalid http parameters"})"); + } else { + LOG_ERROR << "[handler exception] " + << "path=" << req->path() << ", what=" << e.what(); - res->setStatusCode(drogon::k500InternalServerError); - res->setContentTypeCode(drogon::CT_APPLICATION_JSON); - res->setBody(R"({"code":500,"message":"internal server error"})"); - } + res->setStatusCode(drogon::k500InternalServerError); + res->setContentTypeCode(drogon::CT_APPLICATION_JSON); + res->setBody(R"({"code":500,"message":"internal server error"})"); + } - callback(res); - }); + callback(res); + }); da.setUploadPath(get_exe_dir() + "/drogon_uploads"); std::cout << "上传路径: " << da.getUploadPath() << std::endl; @@ -550,53 +553,18 @@ void Global::init_web_server() { void setupCors() { // Register sync advice to handle CORS preflight (OPTIONS) requests drogon::app().registerSyncAdvice( - [](const drogon::HttpRequestPtr &req) -> drogon::HttpResponsePtr { - if (req->method() == drogon::HttpMethod::Options) { - auto resp = drogon::HttpResponse::newHttpResponse(); + [](const drogon::HttpRequestPtr &req) -> drogon::HttpResponsePtr { + if (req->method() == drogon::HttpMethod::Options) { + auto resp = drogon::HttpResponse::newHttpResponse(); - // Set Access-Control-Allow-Origin header based on the Origin - // request header - const auto &origin = req->getHeader("Origin"); - if (!origin.empty()) { - resp->addHeader("Access-Control-Allow-Origin", origin); - } - - // Set Access-Control-Allow-Methods based on the requested method - const auto &requestMethod = - req->getHeader("Access-Control-Request-Method"); - if (!requestMethod.empty()) { - resp->addHeader("Access-Control-Allow-Methods", requestMethod); - } - - // Allow credentials to be included in cross-origin requests - resp->addHeader("Access-Control-Allow-Credentials", "true"); - - // Set allowed headers from the Access-Control-Request-Headers - // header - const auto &requestHeaders = - req->getHeader("Access-Control-Request-Headers"); - if (!requestHeaders.empty()) { - resp->addHeader("Access-Control-Allow-Headers", requestHeaders); - } - - return std::move(resp); - } - return {}; - }); - - // Register post-handling advice to add CORS headers to all responses - drogon::app().registerPostHandlingAdvice( - [](const drogon::HttpRequestPtr &req, - const drogon::HttpResponsePtr &resp) -> void { - // Set Access-Control-Allow-Origin based on the Origin request - // header + // Set Access-Control-Allow-Origin header based on the Origin + // request header const auto &origin = req->getHeader("Origin"); if (!origin.empty()) { resp->addHeader("Access-Control-Allow-Origin", origin); } - // Reflect the requested Access-Control-Request-Method back in the - // response + // Set Access-Control-Allow-Methods based on the requested method const auto &requestMethod = req->getHeader("Access-Control-Request-Method"); if (!requestMethod.empty()) { @@ -606,11 +574,46 @@ void setupCors() { // Allow credentials to be included in cross-origin requests resp->addHeader("Access-Control-Allow-Credentials", "true"); - // Reflect the requested Access-Control-Request-Headers back + // Set allowed headers from the Access-Control-Request-Headers + // header const auto &requestHeaders = req->getHeader("Access-Control-Request-Headers"); if (!requestHeaders.empty()) { resp->addHeader("Access-Control-Allow-Headers", requestHeaders); } - }); + + return std::move(resp); + } + return {}; + }); + + // Register post-handling advice to add CORS headers to all responses + drogon::app().registerPostHandlingAdvice( + [](const drogon::HttpRequestPtr &req, + const drogon::HttpResponsePtr &resp) -> void { + // Set Access-Control-Allow-Origin based on the Origin request + // header + const auto &origin = req->getHeader("Origin"); + if (!origin.empty()) { + resp->addHeader("Access-Control-Allow-Origin", origin); + } + + // Reflect the requested Access-Control-Request-Method back in the + // response + const auto &requestMethod = + req->getHeader("Access-Control-Request-Method"); + if (!requestMethod.empty()) { + resp->addHeader("Access-Control-Allow-Methods", requestMethod); + } + + // Allow credentials to be included in cross-origin requests + resp->addHeader("Access-Control-Allow-Credentials", "true"); + + // Reflect the requested Access-Control-Request-Headers back + const auto &requestHeaders = + req->getHeader("Access-Control-Request-Headers"); + if (!requestHeaders.empty()) { + resp->addHeader("Access-Control-Allow-Headers", requestHeaders); + } + }); } diff --git a/module/Local_Server_main.cpp b/module/Local_Server_main.cpp index 9e6d6bd..abde734 100644 --- a/module/Local_Server_main.cpp +++ b/module/Local_Server_main.cpp @@ -17,23 +17,23 @@ #endif struct Catch_Memory { Catch_Memory() { - sm = (std::int64_t)get_system_memory(); - cur = (std::int64_t)get_process_memory(); + sm = (std::int64_t) get_system_memory(); + cur = (std::int64_t) get_process_memory(); } std::int64_t MB = 1024 * 1024; bool catch_ok() { auto old_memory = cur; - cur = (std::int64_t)get_process_memory(); + cur = (std::int64_t) get_process_memory(); auto change_mb = (cur - old_memory) / MB; auto cur_mb = cur / MB; // std::cout << get_current_date_string() << " 时内存" << cur_mb << "MB " // << " 变更" << change_mb << "MB" << std::endl; if (cur > memory_max) { - auto rate = (double)cur / (double)sm; + auto rate = (double) cur / (double) sm; std::cout << get_current_date_string() + " 抓住内存暴涨:" << cur_mb - << "MB" << " 变更" << change_mb << "MB" << std::endl; + << "MB" << " 变更" << change_mb << "MB" << std::endl; std::cout << "\t内存占用" << rate << "%" << std::endl; stop_program = SIGINT; #if WIN32 @@ -53,7 +53,7 @@ struct Catch_Memory { std::int64_t sm; }; -int psc_main(int argc, char* argv[]) { +int psc_main(int argc, char *argv[]) { std::cout << "wyc_main" << std::endl; if (argc >= 2) { std::string config_path = argv[1]; @@ -95,7 +95,7 @@ int psc_main(int argc, char* argv[]) { std::cout << "shutdown" << LOG_POS << std::endl; auto id = std::this_thread::get_id(); std::cout << "id: " << id << std::endl; - Detach_Thread* dt = g->thread_manager.get_thread(id); + Detach_Thread *dt = g->thread_manager.get_thread(id); if (!dt) { std::cout << VAR_STR_1((void*)dt) << std::endl; std::terminate(); @@ -118,30 +118,30 @@ int psc_main(int argc, char* argv[]) { std::exit(75); std::cout << "std::exit(75) 完成:" << name << std::endl; }); - Detach_Thread_Manager& manager = g->thread_manager; + Detach_Thread_Manager &manager = g->thread_manager; std::cout << "[主线程:" << std::this_thread::get_id() << "]" << " \n" - << std::flush; + << std::flush; manager.test_and_start_thread( - "web服务器线程", [g](std::atomic& running) { - auto& c = Global::instance()->device_config; + "web服务器线程", [g](std::atomic &running) { + auto &c = Global::instance()->device_config; std::string ip = "0.0.0.0"; #ifdef WIN32 ip = "127.0.0.1"; #endif - Net_Config* device = c.list.get("device").value(); + Net_Config *device = c.list.get("device").value(); std::cout << "http://" + ip + ":" + std::to_string(device->port) + "\n" - << std::flush; + << std::flush; std::cout << "http://" + device->ip + ":" + - std::to_string(device->port) + "\n" - << std::flush; + std::to_string(device->port) + "\n" + << std::flush; if (!g->svr.listen("0.0.0.0", device->port)) { if (running.load(std::memory_order_acquire)) { std::cout << "http://" + ip + ":" + std::to_string(device->port) + - "启动失败 退出!\n" - << std::flush; + "启动失败 退出!\n" + << std::flush; std::cout << "http://" + device->ip + ":" + - std::to_string(device->port) + "启动失败 退出!\n" - << std::flush; + std::to_string(device->port) + "启动失败 退出!\n" + << std::flush; std::exit(0); } } @@ -154,7 +154,7 @@ int psc_main(int argc, char* argv[]) { coro->start(); // Catch_Memory cm; while (stop_program == 0) { - for (auto& ds : g->mode_acs.data_source_config.map.list()) { + for (auto &ds: g->mode_acs.data_source_config.map.list()) { ds->delete_timeout_aircraft(); } if (enable) { @@ -179,6 +179,6 @@ int psc_main(int argc, char* argv[]) { return 0; } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { return redict_main_with_gtest(argc, argv, psc_main); } diff --git a/module/dll_source/main.cpp b/module/dll_source/main.cpp index ba771fc..c705ff4 100644 --- a/module/dll_source/main.cpp +++ b/module/dll_source/main.cpp @@ -11,7 +11,7 @@ #include #include #include - +#include #include "Core/Base/JSON.h" #include "Core/Base/ThreadManager.h" #include "Core/Base/global_include.h" @@ -25,21 +25,21 @@ std::vector ddd = { - "1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41", - "1A 33 1A 1A F1 D9 13 EA E7 11 8D 78 1D 40 58 BF 41 E2 45 49 09 7B C8 24", - "1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41", - "1A 33 1A 1A F1 DA D4 35 F9 69 A0 00 15 BC C2 9E 14 F0 A8 00 00 DE E7 37", - "1A 33 1A 1A F1 DB 45 5D 1C 68 A0 00 15 BC FF DD 11 2B 60 04 DB 2F 06 E2", - "1A 33 1A 1A F1 DD 0F 74 3E 20 A0 00 15 BC EE 0A 13 30 20 37 FF A9 CE DC", - "1A 33 1A 1A F1 DD 50 97 59 30 8D 78 00 6C E1 1F 2E 00 00 00 00 09 43 55", - "1A 33 1A 1A F1 DD 73 6B 25 2B 8D 78 16 2D F8 33 00 06 00 49 B8 CF B0 D7", - "1A 33 1A 1A F1 DD F1 C2 C2 1D A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8", - "1A 33 1A 1A F1 DE 62 E9 B6 2A A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8", - "1A 33 1A 1A F1 DE B4 E1 1E 23 8D 79 A0 53 EA 3E C8 66 57 3C 08 71 74 65", - "1A 33 1A 1A F1 DF 17 8E 3F 5D 8D 78 00 6C 58 63 44 5B 32 CB 60 C5 DD 2E", - "1A 33 1A 1A F1 DF 3E 49 FD 76 A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88", - "1A 33 1A 1A F1 DF AF 71 5F 6C A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88", - "1A 33 1A 1A F1 E2 0A DD 76 2A A0 00 11 B1 B5 E8 00 30 AA 00 00 D5 D0 A3", + "1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41", + "1A 33 1A 1A F1 D9 13 EA E7 11 8D 78 1D 40 58 BF 41 E2 45 49 09 7B C8 24", + "1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41", + "1A 33 1A 1A F1 DA D4 35 F9 69 A0 00 15 BC C2 9E 14 F0 A8 00 00 DE E7 37", + "1A 33 1A 1A F1 DB 45 5D 1C 68 A0 00 15 BC FF DD 11 2B 60 04 DB 2F 06 E2", + "1A 33 1A 1A F1 DD 0F 74 3E 20 A0 00 15 BC EE 0A 13 30 20 37 FF A9 CE DC", + "1A 33 1A 1A F1 DD 50 97 59 30 8D 78 00 6C E1 1F 2E 00 00 00 00 09 43 55", + "1A 33 1A 1A F1 DD 73 6B 25 2B 8D 78 16 2D F8 33 00 06 00 49 B8 CF B0 D7", + "1A 33 1A 1A F1 DD F1 C2 C2 1D A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8", + "1A 33 1A 1A F1 DE 62 E9 B6 2A A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8", + "1A 33 1A 1A F1 DE B4 E1 1E 23 8D 79 A0 53 EA 3E C8 66 57 3C 08 71 74 65", + "1A 33 1A 1A F1 DF 17 8E 3F 5D 8D 78 00 6C 58 63 44 5B 32 CB 60 C5 DD 2E", + "1A 33 1A 1A F1 DF 3E 49 FD 76 A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88", + "1A 33 1A 1A F1 DF AF 71 5F 6C A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88", + "1A 33 1A 1A F1 E2 0A DD 76 2A A0 00 11 B1 B5 E8 00 30 AA 00 00 D5 D0 A3", }; @@ -61,7 +61,7 @@ public: // 每调用一次,返回一行 // 返回 true 表示成功取到一行 // 返回 false 表示已经没有更多行 - bool get(std::string& ret_line) { + bool get(std::string &ret_line) { if (index_ >= lines_.size()) { return false; } @@ -90,7 +90,10 @@ private: void load(std::string_view file_path) { std::ifstream file{std::string(file_path)}; if (!file.is_open()) { - throw std::runtime_error("Failed to open file: " + std::string(file_path)); + auto err = "Failed to open file: " + std::string(file_path); + std::cout << err << std::endl; + std::exit(895); + throw std::runtime_error(err); } std::string line; @@ -107,16 +110,17 @@ private: }; - - std::size_t adsb_read(char *buf, std::size_t len) { - - static TextLineReader reader(get_exe_dir() + "/ADS-B_195_0205.txt"); std::string line; reader.get(line); auto l = line.size(); std::memcpy(buf, line.c_str(), l); + + /*static Frequency_Limit fl; + if (fl.test()) { + std::cout << "adsb_read" << VAR_STR_2(l, len) << std::endl; + }*/ return l; } @@ -126,10 +130,10 @@ int adsb_set_iq_cbk(iq_cbk_t recv_cbk, void *pusr) { dg->puser = pusr; - dg->init_when_dll(); return 0; } + int adsb_set_less_30Mhz_ddc_param(uint64_t cf_hz, uint64_t sf_hz, uint64_t bw_hz, int8_t sw) { auto dg = Dll_Global::instance(); dg->center_freq = cf_hz; @@ -137,45 +141,44 @@ int adsb_set_less_30Mhz_ddc_param(uint64_t cf_hz, uint64_t sf_hz, uint64_t bw_hz dg->band_width = bw_hz; return 0; } + int adsb_set_less_30Mhz_fft_param(uint64_t fftWin, uint64_t fftLen, int fftPeriod_ms, int8_t sw) { auto dg = Dll_Global::instance(); dg->fft_point_number = fftLen; dg->fft_period_ms = fftPeriod_ms; - dg->fft_win_type = (UHD_FFTWin)fftWin; + dg->fft_win_type = (UHD_FFTWin) fftWin; return 0; } - - - int main() { init_signal_config(); auto dg = Dll_Global::instance(); - + dg->init_when_exe(); bool debug = false; - auto mb = get_system_memory()/(1024*1024); - auto gb = mb/(1024); + auto mb = get_system_memory() / (1024 * 1024); + auto gb = mb / (1024); std::cout << "当前系统的物理内存大小" << mb << " MB" << std::endl; std::cout << "当前系统的物理内存大小" << gb << " GB" << std::endl; - dg->dtm.test_and_start_thread("dsp共享内存数据推送", [dg](std::atomic & running) { + dg->dtm.test_and_start_thread("dsp共享内存数据推送", [dg](std::atomic &running) { bool debug = true; while (running) { - auto list = dg->iq_memory_buffer.get_all(); + auto list = dg->iq_memory_buffer.get_all(); // 释放内存池 Pool_Guard pg(&dg->iq_memory_buffer.pool, list); if (debug && list.size() > 1000) { - static Frequency_Limit fl(1.0/60.0); + static Frequency_Limit fl(1.0 / 60.0); std::ostringstream oss; - oss << get_current_millisecond_timestamp() << " 警告: dsp共享内存数据推送数据过多 当前数据队列长度:" << list.size() << std::endl; + oss << get_current_millisecond_timestamp() << " 警告: dsp共享内存数据推送数据过多 当前数据队列长度:" << list.size() << + std::endl; if (fl.test()) { - std::cout << oss.str() << std::endl; - } + std::cout << oss.str() << std::endl; + } } if (list.empty()) { std::this_thread::sleep_for(std::chrono::microseconds(1)); @@ -184,8 +187,7 @@ int main() { auto frame_number = list.size(); static Frequency_Limit fl(freq); if (fl.test()) { - - std::cout << dg->rb->state_str() << " dsp数据推送" << frame_number << "条" << std::endl; + std::cout << dg->rb->state_str() << " dsp数据推送" << frame_number << "条" << std::endl; } for (int i = 0; i < frame_number; i++) { @@ -196,11 +198,9 @@ int main() { }); while (!stop_program) { dg->handle_json_call(); - } if (stop_program == SIGINT) { std::cout << "开始关闭所有子线程!" << std::endl; - } return 0; }