#include "Global.h" #include #include #include #include #include #include BaseLogger *server_logger = nullptr; Debug_Logger_Info_Manager debug_logger_info_manager; void Global::handle_old_logs() { auto mode = log_config.open_mode; std::string dirPath = get_exe_dir() + "/" + "logs"; namespace fs = std::filesystem; try { switch (mode) { case Log_Config::Open_Mode::Rename: { auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); std::ostringstream oss; oss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d_%H-%M-%S"); fs::path newDirPath = dirPath + "_" + oss.str(); if (fs::exists(newDirPath)) { std::cout << "New directory name already exists!" << std::endl; return; } fs::rename(dirPath, newDirPath); std::cout << "Directory renamed to: " << newDirPath << std::endl; break; } case Log_Config::Open_Mode::Delete: { if (fs::exists(dirPath)) { fs::remove_all(dirPath); // 删除目录及其所有内容 std::cout << "Directory and its contents deleted: " << dirPath << std::endl; } if (fs::create_directories(dirPath)) { std::cout << "Directory created: " << dirPath << std::endl; } else { std::cout << "创建目录失败: " << dirPath << std::endl; Psc::fail_fast(); } fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all); break; } case Log_Config::Open_Mode::Append: break; default: std::cerr << "未知的打开模式!" << std::endl; break; } } catch (const std::exception &ex) { std::cerr << "Error: " + Psc::platform_2_utf8(ex.what()) + "\n"; } } Global::Global() { auto j = load(); log_config.from_base_json(j.get("log")); handle_old_logs(); Base_Logger_Manager::instance() ->set_thread_num(1) .set_flush_seconds(3) .init(); int piece_num = log_config.piece_num; int size_MB = log_config.size_MB; int MB = 1024 * 1024; asio_socket::socket_logger = new BaseLogger("@/logs/socket", MB * size_MB, piece_num); serial::serial_logger = new BaseLogger("@/logs/serial", MB * size_MB, piece_num); SSR::mode_s_logger = new BaseLogger("@/logs/mode_s", MB * size_MB * 10, piece_num); dsp_logger = new BaseLogger("@/logs/dsp", MB * size_MB, piece_num); // libais::libais_logger = new BaseLogger("@/logs/libais", MB * size_MB, // piece_num); server_logger = new BaseLogger("@/logs/server", MB * size_MB, piece_num); asio_socket::socket_logger->set_redirect( [](const BaseLogger::Log_Info &log_info) { auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() + log_info.content; debug_logger_info_manager.push_info(msg); }); serial::serial_logger->set_redirect([](const BaseLogger::Log_Info &log_info) { auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() + log_info.content; debug_logger_info_manager.push_info(msg); }); fromJson(&j); #ifdef Cache_Some_Mode_S auto old_parse_ok_json = SSR::parse_ok_json; SSR::parse_ok_json = [old_parse_ok_json](Aircraft_Info *aircraft_info, SSR::P_S mode_s_msg, Psc::JSON json) { old_parse_ok_json(aircraft_info, mode_s_msg, json); auto f = static_cast(aircraft_info); f->add_msg_limit(mode_s_msg); }; #endif SSR::cpr_cb = [](SSR::CPR_Error_Type t, std::string_view log, SSR::P_S msg) { auto src = std::dynamic_pointer_cast(msg->source); Mode_S_Statistic_Data *ss = &src->mode_s_statistic; if (t != SSR::CPR_Error_Type::Normal) { ss->add_cpr_error(t); } SSR::mode_s_logger->debug("CPR/" + to_string(t), {}, log); }; // 处理错误 SSR::parse_call_back = [this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info *info, std::string_view field_name, std::vector bds_list, void *, SSR::P_S msg) { auto src = std::dynamic_pointer_cast(msg->source); Mode_S_Statistic_Data *ss = &src->mode_s_statistic; if (type == SSR::Parse_Call_Back_Type::Unknown_DF) { // std::cout << "Unknown DF type!" << (int)(msg->df) << std::endl; return; } DF_Statistic_Data *dfs = ss->get_create_df_statistic_data(msg->df); dfs->add(); if (type == SSR::Parse_Call_Back_Type::Normal_Block) { dfs->add_sub_part(field_name); info->update(msg); } else if (type == SSR::Parse_Call_Back_Type::CRC_Error) { dfs->add_crc_error(); // std::cout << field_name << " :crc_error msg:" << msg->msg_hex << // " df:" << (int)msg->df << std::endl; } else if (type == SSR::Parse_Call_Back_Type::Length_Error) { ss->add_length_error(field_name); // std::cout << field_name << " :length_error msg:" << msg->msg_hex // << " df:" << (int)msg->df << std::endl; } // else if (type == Mode_S::Parse_Call_Back_Type::UNKNOWN_ERROR) {} else // {} }; auto str = toJson().to_json_string(); server_logger->debug("启动", {}, str); SSR::mode_s_logger->debug("启动", {}, str); // libais::libais_logger->debug("启动", {}, str); std::cout << str << std::endl; // libais::log = normal_log; // libais::log = ais_log; // mode_s_log_info = mode_s_log; init_web_server(); } Global::~Global() { std::cout << "Global::~Global()" << std::endl; } void replace(std::string &originalStr, std::string_view findStr, std::string_view replaceStr) { size_t pos = originalStr.find(findStr); while (pos != std::string::npos) { originalStr.replace(pos, findStr.length(), replaceStr); pos = originalStr.find(findStr, pos + replaceStr.length()); } } std::string oneLine(std::string_view str) { auto ret = std::string(str); replace(ret, "\n", "[n]"); return ret; } bool isHexadecimal(std::string_view str) { return std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }); } void handle_buffer_muti_start( std::string &buffer, std::string_view data, const std::set &prefix_list, const std::function &callback) { if (!data.empty()) { buffer += data; // std::cout << "[data]:" + data + "\n"; // std::cout << "[buffer]:" + buffer + "\n"; while (!buffer.empty() && buffer.back() == '\n') { buffer.pop_back(); } while (true) { std::string c; size_t pos = 0, n = buffer.size(); for (; pos < n; pos++) { bool find = false; for (std::string_view prefix : prefix_list) { if (pos + prefix.size() <= n) { if (buffer.substr(pos, prefix.size()) == prefix) { c = prefix; find = true; break; } } } if (find) break; } if (pos == n) break; std::string line = c + buffer.substr(0, pos); // 截取从开头到!之前的数据 buffer = buffer.substr(pos + 1); // 更新buffer为剩余数据 // std::cout << "[line]:" + line + "\n"; if (pos != 0) callback(line); } } } void handle_buffer_head_tail( std::string &buffer, std::string_view data, std::string_view prefix, std::string_view suffix, const std::function &callback) { // 只在数据可用时进行读取 if (!data.empty()) { buffer += data; size_t pos; while ((pos = buffer.find_first_of(suffix)) != std::string::npos) { size_t start = buffer.find_first_of(prefix); if (start == std::string::npos) break; std::string packet = buffer.substr(start + 1, pos - start - 1); buffer.erase(0, pos + 1); // 处理尾部空格 while (!buffer.empty() && buffer.back() == '\n') { buffer.pop_back(); } if (!packet.empty()) { callback(packet); } } } } void read_ais_serial_data(std::atomic &running) { // static int t = config.ais.read_serial_milliseconds; // static bool ais_log = config.console_config.ais_serial; // static bool use_ais_serial = !config.ais_mock.enable || // config.ais_mock.use_real_serial; static auto lm = // Light_Manager::instance(); serial::Serial* ais_serial{}; if // (use_ais_serial) ais_serial = create_serial(config.ais.port_name, // config.ais.baud_rate); libais::VdmStream stream; std::string ais_buffer; // while (running.load(std::memory_order_acquire) == true) // { // std::string ais_data = use_ais_serial ? ais_serial->read() : // mock_ais_serial.read(); if (!ais_data.empty()) // { // if (ais_log && !ais_data.empty()) // { // std::cout << "read:[ais_serial]:" << ais_data << std::endl; // } // libais::libais_logger->debug("ais_serial_read/ais_serial_read", {}, // ais_data + "\n"); handle_buffer_muti_start(ais_buffer, ais_data, // {"!", "$"}, [&](std::string& line) { // lm->light_control(Light_Type::AIS, true); // stream.AddLine(line); // while (auto msg = stream.PopOldestMessage()) // { // parse_ais(msg.get()); // } // lm->light_control(Light_Type::AIS, false); // }); // } // std::this_thread::sleep_for(std::chrono::milliseconds(t)); // } // delete ais_serial; } bool is_10004(SSR::Mode_S_Msg &msg) { bool DF_11_17_18 = msg.df == SSR::Downlink_Format::All_Call_Reply_11 || msg.df == SSR::Downlink_Format::Extended_Squitter_17 || msg.df == SSR::Downlink_Format::Extended_Squitter_Non_Transponder_18; return DF_11_17_18; } std::string to_file_name(std::string_view str) { auto ret = std::string(str); // 定义允许的合法字符 auto is_valid_char = [](char c) { return std::isalnum(c) || c == '_' || c == '-' || c == '.'; // 允许字母、数字、下划线、连字符、点 }; // 替换非法字符为下划线 '_' std::transform(ret.begin(), ret.end(), ret.begin(), [&](char c) { return is_valid_char(c) ? c : '_'; }); // 检查结果字符串是否全是替换字符,防止生成全是下划线的文件名 if (ret.find_first_not_of('_') == std::string::npos) { return "default_file_name"; // 返回一个默认文件名 } return ret; } void Debug_Logger_Info_Manager::push_info(std::string_view c) { std::lock_guard g(mtx); std::string content = std::to_string(cur_serial_number) + ": " + std::string(c); size_t content_length = content.size(); info_list.push_back({cur_serial_number, content}); current_total_length += content_length; while (current_total_length > max_length && !info_list.empty()) { current_total_length -= info_list.front().content.size(); info_list.pop_front(); // 删除最早的记录 } cur_serial_number++; } Serial_Number_Type Debug_Logger_Info_Manager::get_cur_serial_number() { std::lock_guard g(mtx); return cur_serial_number; } JSON Debug_Logger_Info_Manager::to_json() { JSON ret = JSON::object(); ret.append({"cur_serial_number", cur_serial_number}); return ret; } bool Web_Server::listen(std::string_view host, int port) { drogon::HttpAppFramework *app = &drogon::app(); auto g = Global::instance(); Json::Value drogon_config; { auto jsonStr = g->drogon_config.to_json_string(); std::cout << "drogon::app().run(); " << jsonStr << std::endl; Json::CharReaderBuilder builder; std::string errs; auto reader = builder.newCharReader(); if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), &drogon_config, &errs)) { // 解析失败 std::cout << "drogon 配置文件加载失败!json格式解析失败!" << jsonStr << std::endl; Psc::fail_fast(); } delete reader; } app->loadConfigJson(drogon_config); app->disableSigtermHandling(); // 关闭服务器信号处理 app->addListener(std::string(host), port); auto base_dir = get_exe_dir(); // app->setLogPath(base_dir + "/logs/drogon.log"); app->setUploadPath(base_dir + "/drogon_uploads"); app->run(); return true; } std::string Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) { std::lock_guard g(mtx); std::string result; if (serial_number == cur_serial_number) { return ""; } // 从后向前遍历 data 列表 for (auto it = info_list.rbegin(); it != info_list.rend(); ++it) { // std::cout << "max_length: " << max_length << " size: " << // info_list.size() << " serial_number " << serial_number << "cur_sequence" // << it->sequence << " content.size" << it->content.size() << std::endl; if (it->sequence >= serial_number) { result = it->content + result; // 叠加 content } else { break; } } return result; } std::string inet_address_to_string(const trantor::InetAddress &addr) { char buf[INET6_ADDRSTRLEN] = {0}; if (!addr.isIpV6()) { // IPv4 auto sa = reinterpret_cast(addr.getSockAddr()); inet_ntop(AF_INET, &(sa->sin_addr), buf, sizeof(buf)); uint16_t port = ntohs(sa->sin_port); return std::string(buf) + ":" + std::to_string(port); } else { // IPv6 auto sa6 = reinterpret_cast(addr.getSockAddr()); inet_ntop(AF_INET6, &(sa6->sin6_addr), buf, sizeof(buf)); uint16_t port = ntohs(sa6->sin6_port); return "[" + std::string(buf) + "]:" + std::to_string(port); } }