Files
ECAP_Server/module/Local_Server/server/Global.cpp
T
2026-06-23 14:01:23 +08:00

356 lines
14 KiB
C++

#include "Global.h"
#include <drogon/HttpAppFramework.h>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <string>
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.init(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*>(aircraft_info);
f->add_msg_limit(mode_s_msg);
};
#endif
SSR::cpr_cb = [](SSR::CPR_Error_Type t, const std::string& log, SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(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,
const std::string& field_name, std::vector<std::string> bds_list, void*, SSR::P_S msg) {
auto src = std::dynamic_pointer_cast<Data_Source>(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, const std::string& findStr, const std::string& 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 str) {
replace(str, "\n", "[n]");
return str;
}
bool isHexadecimal(const std::string& 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, const std::string& data, const std::set<std::string>& prefix_list,
const std::function<void(std::string&)>& 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 (const std::string& 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, const std::string& data, const std::string& prefix,
const std::string& suffix, const std::function<void(std::string&)>& 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<bool>& 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 str) {
// 定义允许的合法字符
auto is_valid_char = [](char c) {
return std::isalnum(c) || c == '_' || c == '-' || c == '.'; // 允许字母、数字、下划线、连字符、点
};
// 替换非法字符为下划线 '_'
std::transform(str.begin(), str.end(), str.begin(), [&](char c) { return is_valid_char(c) ? c : '_'; });
// 检查结果字符串是否全是替换字符,防止生成全是下划线的文件名
if (str.find_first_not_of('_') == std::string::npos) {
return "default_file_name"; // 返回一个默认文件名
}
return str;
}
void Debug_Logger_Info_Manager::push_info(const std::string& c) {
std::lock_guard g(mtx);
std::string content = std::to_string(cur_serial_number) + ": " + 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(const std::string &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(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<const struct sockaddr_in*>(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<const struct sockaddr_in6*>(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);
}
}