303 lines
9.8 KiB
C++
303 lines
9.8 KiB
C++
#pragma once
|
|
|
|
|
|
|
|
#include "Core/Base/ThreadManager.h"
|
|
#include "../Data_Source/export.h"
|
|
#include "../State_Report/State_Report.h"
|
|
#include "../global_include.h"
|
|
#include "Ucoro_Drogon_Glue.h"
|
|
#include "Config.h"
|
|
#include <drogon/drogon.h>
|
|
|
|
#include "Config.h"
|
|
|
|
#include "../../Radarcape_Core/cpp-httplib/httplib.h"
|
|
#include "../Data_Source/export.h"
|
|
#include "Core/Net_Adapter/Net_Adapter.h"
|
|
#include "libarchive.h"
|
|
#include <filesystem>
|
|
#include <list>
|
|
#include <utility>
|
|
|
|
// 集中 管理日志
|
|
using namespace Psc;
|
|
extern BaseLogger* server_logger;
|
|
std::string to_file_name(std::string str);
|
|
std::string inet_address_to_string(const trantor::InetAddress &addr);
|
|
|
|
using Serial_Number_Type = unsigned int;
|
|
struct Debug_Logger_Info_Manager {
|
|
void push_info(const std::string& content);
|
|
std::string get_info(Serial_Number_Type serial_number);
|
|
Serial_Number_Type get_cur_serial_number();
|
|
struct Info {
|
|
Serial_Number_Type sequence;
|
|
std::string content;
|
|
};
|
|
std::list<Info> info_list;
|
|
JSON to_json();
|
|
private:
|
|
// 最大总长度
|
|
static constexpr size_t max_length = 1000 * 300;
|
|
// 当前总长度
|
|
size_t current_total_length = 0;
|
|
Serial_Number_Type cur_serial_number = 0;
|
|
std::mutex mtx;
|
|
};
|
|
extern Debug_Logger_Info_Manager debug_logger_info_manager;
|
|
|
|
|
|
|
|
#define RET_OK \
|
|
res.status = StatusCode::OK_200; \
|
|
res.set_content("{\"status\": 200}", "application/json");
|
|
inline JSON warp(const JSON& data) {
|
|
// Json ret = Json::object();
|
|
// ret.append({"status", 200});
|
|
// ret.append({"data", data});
|
|
// return ret;
|
|
return data;
|
|
}
|
|
|
|
|
|
|
|
#define HTTP_Param const drogon::HttpRequestPtr& req, const drogon::HttpResponsePtr& res
|
|
|
|
class Web_Server {
|
|
public:
|
|
std::string update = "update_";
|
|
std::string insert = "insert_";
|
|
std::string remove = "remove_";
|
|
std::string search = "search_";
|
|
std::string rise = "rise_";
|
|
std::string fall = "fall_";
|
|
using Handler = std::function<void(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
|
|
using CoroHandler = std::function<drogon::Task<>(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
|
|
bool listen(const std::string& host, int port);
|
|
|
|
~Web_Server() = default;
|
|
|
|
|
|
|
|
|
|
|
|
static void stop() {
|
|
std::cout << "开始停止web服务" << std::endl;
|
|
drogon::app().quit();
|
|
}
|
|
|
|
Web_Server& Post(const std::string& pattern, Handler handler) {
|
|
drogon::app().registerHandler(
|
|
pattern,
|
|
[handler](const drogon::HttpRequestPtr& request,
|
|
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
|
|
auto resp = drogon::HttpResponse::newHttpResponse();
|
|
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
|
|
|
handler(request, resp);
|
|
|
|
callback(resp);
|
|
},
|
|
{drogon::Post}
|
|
);
|
|
|
|
return *this;
|
|
}
|
|
|
|
Web_Server& PostCoro(const std::string& pattern, CoroHandler handler) {
|
|
drogon::app().registerHandler(
|
|
pattern,
|
|
[handler = std::move(handler)](
|
|
const drogon::HttpRequestPtr& request,
|
|
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
|
|
auto resp = drogon::HttpResponse::newHttpResponse();
|
|
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
|
|
|
drogon::async_run(
|
|
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
|
|
try {
|
|
co_await handler(request, resp);
|
|
} catch (const std::exception& error) {
|
|
resp->setStatusCode(drogon::k500InternalServerError);
|
|
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
|
|
} catch (...) {
|
|
resp->setStatusCode(drogon::k500InternalServerError);
|
|
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
|
|
}
|
|
callback(resp);
|
|
co_return;
|
|
});
|
|
},
|
|
{drogon::Post}
|
|
);
|
|
|
|
return *this;
|
|
}
|
|
|
|
Web_Server& Get(const std::string& pattern, Handler handler) {
|
|
drogon::app().registerHandlerViaRegex(
|
|
pattern,
|
|
[handler](const drogon::HttpRequestPtr& request,
|
|
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
|
|
auto resp = drogon::HttpResponse::newHttpResponse();
|
|
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
|
|
|
handler(request, resp);
|
|
|
|
callback(resp);
|
|
},
|
|
{drogon::Get}
|
|
);
|
|
|
|
return *this;
|
|
}
|
|
|
|
Web_Server& GetCoro(const std::string& pattern, CoroHandler handler) {
|
|
drogon::app().registerHandlerViaRegex(
|
|
pattern,
|
|
[handler = std::move(handler)](
|
|
const drogon::HttpRequestPtr& request,
|
|
std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
|
|
auto resp = drogon::HttpResponse::newHttpResponse();
|
|
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
|
|
|
drogon::async_run(
|
|
[handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
|
|
try {
|
|
co_await handler(request, resp);
|
|
} catch (const std::exception& error) {
|
|
resp->setStatusCode(drogon::k500InternalServerError);
|
|
resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
|
|
} catch (...) {
|
|
resp->setStatusCode(drogon::k500InternalServerError);
|
|
resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
|
|
}
|
|
callback(resp);
|
|
co_return;
|
|
});
|
|
},
|
|
{drogon::Get}
|
|
);
|
|
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
|
|
// 这个对象不释放
|
|
|
|
|
|
|
|
|
|
|
|
class Mlat_MSG {
|
|
public:
|
|
explicit Mlat_MSG(const std::shared_ptr<SSR::Mode_Msg>& first) { list.push_back(first);}
|
|
[[nodiscard]] std::optional<std::string> icao() const {
|
|
auto a = list[0];
|
|
auto t = a->type;
|
|
if (t == SSR::Mode_Msg::T::S7 || t == SSR::Mode_Msg::T::S14) {
|
|
return dynamic_cast<SSR::Mode_S_Msg*>(a.get())->icao;
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
[[nodiscard]] std::string msg_hex() const { return list[0]->msg_hex;}
|
|
[[nodiscard]] SSR::Mode_Msg::T type() const { return static_cast<SSR::Mode_Msg::T>(list[0]->type);}
|
|
[[nodiscard]] SSR::MLAT_timestamp& timestamp() const { return list[0]->mlat_timestamp;}
|
|
[[nodiscard]] std::shared_ptr<SSR::Data_Source_Interface> data_source() const { return list[0]->source;}
|
|
void add(const std::shared_ptr<SSR::Mode_Msg>& t) {
|
|
list.push_back(t);
|
|
}
|
|
[[nodiscard]] size_t size() const { return list.size(); }
|
|
std::vector<std::shared_ptr<SSR::Mode_Msg>> list;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Mlat_Handler {
|
|
public:
|
|
std::list<Mlat_MSG> get_all() {
|
|
std::lock_guard<std::mutex> gg(ok_mtx);
|
|
if (ok_list.empty()) return {};
|
|
std::list<Mlat_MSG> ret;
|
|
std::swap(ok_list, ret);
|
|
return ret;
|
|
}
|
|
|
|
void push(const std::shared_ptr<SSR::Mode_Msg>& msg) {
|
|
std::lock_guard<std::mutex> g(mtx);
|
|
|
|
if (list.empty()) {
|
|
list.emplace_back(msg);
|
|
return;
|
|
}
|
|
|
|
auto time = msg->mlat_timestamp;
|
|
auto p = list.rbegin();
|
|
|
|
while (p != list.rend()) {
|
|
auto cur_time = p->timestamp();
|
|
// 往前最多找3秒
|
|
if (cur_time.daysec + 3 < time.daysec) {
|
|
std::lock_guard<std::mutex> gg(ok_mtx);
|
|
ok_list.splice(ok_list.end(), list, list.begin(), p.base());
|
|
return;
|
|
}
|
|
if (p->msg_hex() == msg->msg_hex) {
|
|
p->add(msg);
|
|
return;
|
|
}
|
|
++p;
|
|
}
|
|
list.insert(p.base(), Mlat_MSG(msg));
|
|
}
|
|
protected:
|
|
std::list<Mlat_MSG> ok_list;
|
|
std::list<Mlat_MSG> list;
|
|
std::mutex ok_mtx;
|
|
std::mutex mtx;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Global : public Config, public Singleton<Global>{
|
|
public:
|
|
// asio::io_context ctx;
|
|
std::atomic<bool> init_ok{false};
|
|
Global();
|
|
~Global();
|
|
Detach_Thread_Manager thread_manager;
|
|
std::shared_ptr<Data_Source> source(const std::string& data_source_key) {
|
|
return mode_acs.data_source_config.map.get(data_source_key).value_or(nullptr);
|
|
}
|
|
std::shared_ptr<Data_Source> total_source() {
|
|
for (auto i : mode_acs.data_source_config.map.list())
|
|
{
|
|
if (i->enable) return i;
|
|
}
|
|
return mode_acs.data_source_config.map.list().at(0);
|
|
}
|
|
Web_Server svr;
|
|
std::string api = "/api/";
|
|
Mlat_Handler mlat_handler;
|
|
void init_web_server();
|
|
void handle_old_logs();
|
|
std::time_t start_server_time;
|
|
DELETE_COPY(Global)
|
|
};
|
|
|
|
void wake_data_feed_thread();
|
|
void io_coro(std::atomic<bool>& running);
|
|
|
|
|
|
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);
|
|
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);
|
|
|