diff --git a/CMakeLists.txt b/CMakeLists.txt index 68766d0..2472855 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,17 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.14) SET(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake) +SET(VCPKG_TARGET_TRIPLET "x86-windows-static" CACHE STRING "") -PROJECT(vACDM VERSION "1.3.3") +PROJECT(vACDM VERSION "1.4.0") SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) SET(CMAKE_CXX_STANDARD 20) SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) + +# Use static runtime libraries +SET(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + IF (MSVC) IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") @@ -22,6 +27,12 @@ IF (MSVC) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /sdl /permissive- /DNOMINMAX") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFESTUAC:NO /ignore:4099") ADD_DEFINITIONS(/D_USRDLL) + + FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF() + ENDFOREACH() ENDIF () if(DEV_BUILD) @@ -53,6 +64,7 @@ ADD_DEFINITIONS( -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=0 -DSQLITE_WIN32_MALLOC -DSQLITE_THREADSAFE=0 + -DWIN32_LEAN_AND_MEAN ) SET(SOURCE_FILES @@ -73,17 +85,23 @@ SET(SOURCE_FILES ) -FIND_PACKAGE(CURL CONFIG REQUIRED) +FIND_PACKAGE(OpenSSL CONFIG REQUIRED) +FIND_PACKAGE(httplib CONFIG REQUIRED) FIND_PACKAGE(nlohmann_json CONFIG REQUIRED) -FIND_PACKAGE(GeographicLib CONFIG REQUIRED) ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCE_FILES}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/external/lib/EuroScopePlugInDLL.lib crypt32.lib ws2_32.lib Shlwapi.lib) TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE - CURL::libcurl + ${CMAKE_SOURCE_DIR}/external/lib/EuroScopePlugInDLL.lib + OpenSSL::SSL OpenSSL::Crypto + httplib::httplib nlohmann_json::nlohmann_json - ${GeographicLib_LIBRARIES} + crypt32.lib ws2_32.lib Shlwapi.lib +) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE + debug ${CMAKE_SOURCE_DIR}/external/lib/GeographicLib_d.lib + optimized ${CMAKE_SOURCE_DIR}/external/lib/GeographicLib.lib ) # move config file to output dir, allows loading of DLL from output dir diff --git a/external/lib/GeographicLib.lib b/external/lib/GeographicLib.lib new file mode 100644 index 0000000..6f3a171 Binary files /dev/null and b/external/lib/GeographicLib.lib differ diff --git a/external/lib/GeographicLib_d.lib b/external/lib/GeographicLib_d.lib new file mode 100644 index 0000000..c7650c4 Binary files /dev/null and b/external/lib/GeographicLib_d.lib differ diff --git a/src/core/Server.cpp b/src/core/Server.cpp index 99cae5b..1edcdf7 100644 --- a/src/core/Server.cpp +++ b/src/core/Server.cpp @@ -10,116 +10,43 @@ using namespace vacdm; using namespace vacdm::com; using namespace vacdm::logging; -static std::string __receivedDeleteData; -static std::string __receivedGetData; -static std::string __receivedPatchData; -static std::string __receivedPostData; - -static std::size_t receiveCurlDelete(void* ptr, std::size_t size, std::size_t nmemb, void* stream) { - (void)stream; - - std::string serverResult = static_cast(ptr); - __receivedDeleteData += serverResult; - return size * nmemb; -} - -static std::size_t receiveCurlGet(void* ptr, std::size_t size, std::size_t nmemb, void* stream) { - (void)stream; - - std::string serverResult = static_cast(ptr); - __receivedGetData += serverResult; - return size * nmemb; -} - -static std::size_t receiveCurlPatch(void* ptr, std::size_t size, std::size_t nmemb, void* stream) { - (void)stream; - - std::string serverResult = static_cast(ptr); - __receivedPatchData += serverResult; - return size * nmemb; -} - -static std::size_t receiveCurlPost(void* ptr, std::size_t size, std::size_t nmemb, void* stream) { - (void)stream; - - std::string serverResult = static_cast(ptr); - __receivedPostData += serverResult; - return size * nmemb; -} - Server::Server() : m_authToken(), - m_getRequest(), - m_postRequest(), - m_patchRequest(), - m_deleteRequest(), + m_clientMutex(), + m_client(nullptr), m_apiIsChecked(false), m_apiIsValid(false), m_baseUrl("https://app.vacdm.net"), m_clientIsMaster(false), m_errorCode() { - /* configure the get request */ - curl_easy_setopt(m_getRequest.socket, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(m_getRequest.socket, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(m_getRequest.socket, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); - curl_easy_setopt(m_getRequest.socket, CURLOPT_HTTPGET, 1L); - curl_easy_setopt(m_getRequest.socket, CURLOPT_WRITEFUNCTION, receiveCurlGet); - curl_easy_setopt(m_getRequest.socket, CURLOPT_TIMEOUT, 2L); - - /* configure the post request */ - curl_easy_setopt(m_postRequest.socket, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(m_postRequest.socket, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(m_postRequest.socket, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); - curl_easy_setopt(m_postRequest.socket, CURLOPT_WRITEFUNCTION, receiveCurlPost); - curl_easy_setopt(m_postRequest.socket, CURLOPT_CUSTOMREQUEST, "POST"); - curl_easy_setopt(m_postRequest.socket, CURLOPT_VERBOSE, 1); - struct curl_slist* headers = nullptr; - headers = curl_slist_append(headers, "Accept: application/json"); - headers = curl_slist_append(headers, ("Authorization: Bearer " + this->m_authToken).c_str()); - headers = curl_slist_append(headers, "Content-Type: application/json"); - curl_easy_setopt(m_postRequest.socket, CURLOPT_HTTPHEADER, headers); - - /* configure the patch request */ - curl_easy_setopt(m_patchRequest.socket, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_WRITEFUNCTION, receiveCurlPatch); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_CUSTOMREQUEST, "PATCH"); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_VERBOSE, 1); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_HTTPHEADER, headers); - - /* configure the delete request */ - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_CUSTOMREQUEST, "DELETE"); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_WRITEFUNCTION, receiveCurlDelete); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_TIMEOUT, 2L); + initClient(); } Server::~Server() { - if (nullptr != m_getRequest.socket) { - std::lock_guard guard(m_getRequest.lock); - curl_easy_cleanup(m_getRequest.socket); - m_getRequest.socket = nullptr; - } + std::lock_guard guard(m_clientMutex); + m_client.reset(); +} - if (nullptr != m_postRequest.socket) { - std::lock_guard guard(m_postRequest.lock); - curl_easy_cleanup(m_postRequest.socket); - m_postRequest.socket = nullptr; - } +void Server::initClient() { + std::lock_guard guard(m_clientMutex); - if (nullptr != m_patchRequest.socket) { - std::lock_guard guard(m_patchRequest.lock); - curl_easy_cleanup(m_patchRequest.socket); - m_patchRequest.socket = nullptr; - } + // Create a new client with the current base URL + m_client = std::make_unique(m_baseUrl); + + // Configure client settings similar to curl options + m_client->set_connection_timeout(2); + m_client->set_read_timeout(5); + m_client->set_write_timeout(5); + + m_client->enable_server_certificate_verification(false); + m_client->enable_server_hostname_verification(false); + + // Set default headers + m_client->set_default_headers({{"Accept", "application/json"}, {"Content-Type", "application/json"}}); - if (nullptr != m_deleteRequest.socket) { - std::lock_guard guard(m_deleteRequest.lock); - curl_easy_cleanup(m_deleteRequest.socket); - m_deleteRequest.socket = nullptr; + // Add authorization if token is available + if (!m_authToken.empty()) { + m_client->set_bearer_token_auth(m_authToken); } } @@ -127,48 +54,51 @@ void Server::changeServerAddress(const std::string& url) { this->m_baseUrl = url; this->m_apiIsChecked = false; this->m_apiIsValid = false; + + // Re-initialize client with new URL + initClient(); } bool Server::checkWebApi() { if (this->m_apiIsChecked == true) return this->m_apiIsValid; - std::lock_guard guard(m_getRequest.lock); - if (m_getRequest.socket == nullptr) { + std::lock_guard guard(m_clientMutex); + if (!m_client) { this->m_apiIsValid = false; return m_apiIsValid; } - __receivedGetData.clear(); - - std::string url = m_baseUrl + "/api/v1/version"; - curl_easy_setopt(m_getRequest.socket, CURLOPT_URL, url.c_str()); + std::string url = "/api/v1/version"; - // send the GET request - CURLcode result = curl_easy_perform(m_getRequest.socket); - if (result != CURLE_OK) { + // Send GET request + auto result = m_client->Get(url); + if (!result || result->status != 200) { + Logger::instance().log( + Logger::LogSender::Server, + "Failed to connect to API: " + (result ? std::to_string(result->status) : "connection error"), + Logger::LogLevel::Info); this->m_apiIsValid = false; return m_apiIsValid; } - std::string errors; - nlohmann::json root; - Logger::instance().log(Logger::LogSender::Server, "Received API-version-message: " + __receivedGetData, + std::string response = result->body; + Logger::instance().log(Logger::LogSender::Server, "Received API-version-message: " + response, Logger::LogLevel::Info); try { - root = nlohmann::json::parse(__receivedGetData.c_str()); + auto root = nlohmann::json::parse(response); if (PLUGIN_VERSION_MAJOR != root["major"].get()) { this->m_errorCode = "Backend-version is incompatible. Please update the plugin."; this->m_apiIsValid = false; } else { this->m_apiIsValid = true; } - } catch (const std::exception& e) { Logger::instance().log(Logger::LogSender::Server, "Failed to parse response JSON: " + std::string(e.what()), Logger::LogLevel::Info); - this->m_errorCode = "Invalid backend-version response: " + __receivedGetData; + this->m_errorCode = "Invalid backend-version response: " + response; this->m_apiIsValid = false; } + m_apiIsChecked = true; return this->m_apiIsValid; } @@ -176,23 +106,19 @@ bool Server::checkWebApi() { Server::ServerConfiguration Server::getServerConfig() { if (false == this->m_apiIsChecked || false == this->m_apiIsValid) return Server::ServerConfiguration(); - std::lock_guard guard(m_getRequest.lock); - if (nullptr != m_getRequest.socket) { - __receivedGetData.clear(); - - std::string url = m_baseUrl + "/api/v1/config"; - curl_easy_setopt(m_getRequest.socket, CURLOPT_URL, url.c_str()); + std::lock_guard guard(m_clientMutex); + if (m_client) { + std::string url = "/api/v1/config"; + auto result = m_client->Get(url); - /* send the command */ - CURLcode result = curl_easy_perform(m_getRequest.socket); - if (CURLE_OK == result) { - std::string errors; + if (result && result->status == 200) { nlohmann::json root; - Logger::instance().log(Logger::LogSender::Server, "Received configuration: " + __receivedGetData, + Logger::instance().log(Logger::LogSender::Server, "Received configuration: " + result->body, Logger::LogLevel::Info); + try { - root = nlohmann::json::parse(__receivedGetData.c_str()); + root = nlohmann::json::parse(result->body); ServerConfiguration_t config; config.name = root["serverName"].get(); config.allowMasterInSweatbox = root["allowSimSession"].get(); @@ -210,92 +136,88 @@ Server::ServerConfiguration Server::getServerConfig() { } std::list Server::getPilots(const std::list airports) { - std::lock_guard guard(m_getRequest.lock); - if (nullptr != m_getRequest.socket) { - __receivedGetData.clear(); - - std::string url = m_baseUrl + "/api/v1/pilots"; - if (airports.size() != 0) { - url += "?adep=" + - std::accumulate(std::next(airports.begin()), airports.end(), airports.front(), - [](const std::string& acc, const std::string& str) { return acc + "&adep=" + str; }); - } - Logger::instance().log(Logger::LogSender::Server, url, Logger::LogLevel::Info); + std::lock_guard guard(m_clientMutex); + if (!m_client) { + return {}; + } - curl_easy_setopt(m_getRequest.socket, CURLOPT_URL, url.c_str()); + std::string url = "/api/v1/pilots"; - // send GET request - CURLcode result = curl_easy_perform(m_getRequest.socket); - if (result == CURLE_OK) { - std::string errors; - nlohmann::json root; + // Add airport filter if specified + if (!airports.empty()) { + url += "?airports="; + url += std::accumulate(std::next(airports.begin()), airports.end(), *airports.begin(), + [](const std::string& a, const std::string& b) { return a + "," + b; }); + } - // Logger::instance().log(Logger::LogSender::Server, "Received data" + __receivedGetData, - // Logger::LogLevel::Debug); - try { - root = nlohmann::json::parse(__receivedGetData.c_str()); - std::list pilots; - - for (const auto& pilot : std::as_const(root)) { - pilots.push_back(types::Pilot()); - - pilots.back().callsign = pilot["callsign"].get(); - pilots.back().lastUpdate = utils::Date::isoStringToTimestamp(pilot["updatedAt"].get()); - pilots.back().inactive = pilot["inactive"].get(); - - // position data - pilots.back().latitude = pilot["position"]["lat"].get(); - pilots.back().longitude = pilot["position"]["lon"].get(); - pilots.back().taxizoneIsTaxiout = pilot["vacdm"]["taxizoneIsTaxiout"].get(); - - // flightplan & clearance data - pilots.back().origin = pilot["flightplan"]["departure"].get(); - pilots.back().destination = pilot["flightplan"]["arrival"].get(); - pilots.back().runway = pilot["clearance"]["dep_rwy"].get(); - pilots.back().sid = pilot["clearance"]["sid"].get(); - - // ACDM procedure data - pilots.back().eobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["eobt"].get()); - pilots.back().tobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tobt"].get()); - pilots.back().tobt_state = pilot["vacdm"]["tobt_state"].get(); - pilots.back().ctot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ctot"].get()); - pilots.back().ttot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ttot"].get()); - pilots.back().tsat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tsat"].get()); - pilots.back().exot = std::chrono::utc_clock::time_point( - std::chrono::minutes(pilot["vacdm"]["exot"].get())); - pilots.back().asat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asat"].get()); - pilots.back().aobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aobt"].get()); - pilots.back().atot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["atot"].get()); - pilots.back().asrt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asrt"].get()); - pilots.back().aort = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aort"].get()); - - // ECFMP measures - nlohmann::json measuresArray = pilot["measures"]; - std::vector parsedMeasures; - for (const auto& measureObject : std::as_const(measuresArray)) { - vacdm::types::EcfmpMeasure measure; - - measure.ident = measureObject["ident"].get(); - measure.value = measureObject["value"].get(); - - parsedMeasures.push_back(measure); - } - pilots.back().measures = parsedMeasures; - - // event booking data - pilots.back().hasBooking = pilot["hasBooking"].get(); + Logger::instance().log(Logger::LogSender::Server, url, Logger::LogLevel::Info); + + auto result = m_client->Get(url); + if (result && result->status == 200) { + nlohmann::json root; + + try { + root = nlohmann::json::parse(result->body); + std::list pilots; + + for (const auto& pilot : std::as_const(root)) { + pilots.push_back(types::Pilot()); + + pilots.back().callsign = pilot["callsign"].get(); + pilots.back().lastUpdate = utils::Date::isoStringToTimestamp(pilot["updatedAt"].get()); + pilots.back().inactive = pilot["inactive"].get(); + + // position data + pilots.back().latitude = pilot["position"]["lat"].get(); + pilots.back().longitude = pilot["position"]["lon"].get(); + pilots.back().taxizoneIsTaxiout = pilot["vacdm"]["taxizoneIsTaxiout"].get(); + + // flightplan & clearance data + pilots.back().origin = pilot["flightplan"]["departure"].get(); + pilots.back().destination = pilot["flightplan"]["arrival"].get(); + pilots.back().runway = pilot["clearance"]["dep_rwy"].get(); + pilots.back().sid = pilot["clearance"]["sid"].get(); + + // ACDM procedure data + pilots.back().eobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["eobt"].get()); + pilots.back().tobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tobt"].get()); + pilots.back().tobt_state = pilot["vacdm"]["tobt_state"].get(); + pilots.back().ctot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ctot"].get()); + pilots.back().ttot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["ttot"].get()); + pilots.back().tsat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["tsat"].get()); + pilots.back().exot = + std::chrono::utc_clock::time_point(std::chrono::minutes(pilot["vacdm"]["exot"].get())); + pilots.back().asat = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asat"].get()); + pilots.back().aobt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aobt"].get()); + pilots.back().atot = utils::Date::isoStringToTimestamp(pilot["vacdm"]["atot"].get()); + pilots.back().asrt = utils::Date::isoStringToTimestamp(pilot["vacdm"]["asrt"].get()); + pilots.back().aort = utils::Date::isoStringToTimestamp(pilot["vacdm"]["aort"].get()); + + // ECFMP measures + nlohmann::json measuresArray = pilot["measures"]; + std::vector parsedMeasures; + for (const auto& measureObject : std::as_const(measuresArray)) { + vacdm::types::EcfmpMeasure measure; + + measure.ident = measureObject["ident"].get(); + measure.value = measureObject["value"].get(); + + parsedMeasures.push_back(measure); } - Logger::instance().log(Logger::LogSender::Server, "Pilots size: " + std::to_string(pilots.size()), - Logger::LogLevel::Info); - return pilots; - } catch (const std::exception& e) { - Logger::instance().log(Logger::LogSender::Server, - "Failed to parse response JSON: " + std::string(e.what()), - Logger::LogLevel::Info); + pilots.back().measures = parsedMeasures; + + // event booking data + pilots.back().hasBooking = pilot["hasBooking"].get(); } + Logger::instance().log(Logger::LogSender::Server, "Pilots size: " + std::to_string(pilots.size()), + Logger::LogLevel::Info); + return pilots; + + } catch (const std::exception& e) { + Logger::instance().log(Logger::LogSender::Server, "Failed to parse response JSON: " + std::string(e.what()), + Logger::LogLevel::Info); } } - return {}; } @@ -304,22 +226,21 @@ void Server::sendPostMessage(const std::string& endpointUrl, const nlohmann::jso const auto message = root.dump(); - Logger::instance().log(Logger::LogSender::Server, - "Posting " + root["callsign"].get() + " with message: " + message, - Logger::LogLevel::Debug); - - std::lock_guard guard(this->m_postRequest.lock); - if (m_postRequest.socket != nullptr) { - std::string url = m_baseUrl + endpointUrl; - curl_easy_setopt(m_postRequest.socket, CURLOPT_URL, url.c_str()); - curl_easy_setopt(m_postRequest.socket, CURLOPT_POSTFIELDS, message.c_str()); - - curl_easy_perform(m_postRequest.socket); - + if (root.contains("callsign")) { Logger::instance().log(Logger::LogSender::Server, - "Posted " + root["callsign"].get() + " response: " + __receivedPostData, + "Posting " + root["callsign"].get() + " with message: " + message, Logger::LogLevel::Debug); - __receivedPostData.clear(); + } + + std::lock_guard guard(m_clientMutex); + if (m_client) { + auto result = m_client->Post(endpointUrl, message, "application/json"); + + if (result && root.contains("callsign")) { + Logger::instance().log(Logger::LogSender::Server, + "Posted " + root["callsign"].get() + " response: " + result->body, + Logger::LogLevel::Debug); + } } } @@ -328,36 +249,31 @@ void Server::sendPatchMessage(const std::string& endpointUrl, const nlohmann::js const auto message = root.dump(); - Logger::instance().log(Logger::LogSender::Server, - "Patching " + root["callsign"].get() + " with message: " + message, - Logger::LogLevel::Debug); - - std::lock_guard guard(this->m_patchRequest.lock); - if (m_patchRequest.socket != nullptr) { - std::string url = m_baseUrl + endpointUrl; - curl_easy_setopt(m_patchRequest.socket, CURLOPT_URL, url.c_str()); - curl_easy_setopt(m_patchRequest.socket, CURLOPT_POSTFIELDS, message.c_str()); - - curl_easy_perform(m_patchRequest.socket); - + if (root.contains("callsign")) { Logger::instance().log(Logger::LogSender::Server, - "Patched " + root["callsign"].get() + " response: " + __receivedPatchData, + "Patching " + root["callsign"].get() + " with message: " + message, Logger::LogLevel::Debug); - __receivedPatchData.clear(); } -} -void Server::sendDeleteMessage(const std::string& endpointUrl) { - if (this->m_apiIsChecked == false || this->m_apiIsValid == false || this->m_clientIsMaster == false) return; - - std::lock_guard guard(this->m_deleteRequest.lock); - if (m_deleteRequest.socket != nullptr) { - std::string url = m_baseUrl + endpointUrl; + std::lock_guard guard(m_clientMutex); + if (m_client) { + auto result = m_client->Patch(endpointUrl, message, "application/json"); - curl_easy_setopt(m_deleteRequest.socket, CURLOPT_URL, url.c_str()); + if (result && root.contains("callsign")) { + Logger::instance().log(Logger::LogSender::Server, + "Patched " + root["callsign"].get() + " response: " + result->body, + Logger::LogLevel::Debug); + } + } +} - curl_easy_perform(m_deleteRequest.socket); - __receivedDeleteData.clear(); +void Server::sendDeleteMessage(const std::string& endpointUrl) { + if (this->m_apiIsChecked == false || this->m_apiIsValid == false || this->m_clientIsMaster == false) { + return; + } + std::lock_guard guard(m_clientMutex); + if (m_client) { + m_client->Delete(endpointUrl); } } diff --git a/src/core/Server.h b/src/core/Server.h index ef83b55..7298d6b 100644 --- a/src/core/Server.h +++ b/src/core/Server.h @@ -1,11 +1,12 @@ #pragma once #include +#include #include #include -#define CURL_STATICLIB 1 -#include +#define CPPHTTPLIB_OPENSSL_SUPPORT +#include #include @@ -22,18 +23,10 @@ class Server { private: Server(); - struct Communication { - std::mutex lock; - CURL* socket; - - Communication() : lock(), socket(curl_easy_init()) {} - }; std::string m_authToken; - Communication m_getRequest; - Communication m_postRequest; - Communication m_patchRequest; - Communication m_deleteRequest; + std::mutex m_clientMutex; + std::unique_ptr m_client; bool m_apiIsChecked; bool m_apiIsValid; @@ -84,5 +77,9 @@ class Server { const std::string& errorMessage() const; void setMaster(bool master); bool getMaster(); + + private: + // Helper method to initialize/reinitialize the HTTP client + void initClient(); }; } // namespace vacdm::com \ No newline at end of file diff --git a/src/vACDM.cpp b/src/vACDM.cpp index af56bcf..e552de0 100644 --- a/src/vACDM.cpp +++ b/src/vACDM.cpp @@ -32,8 +32,6 @@ vACDM::vACDM() Logger::instance().log(Logger::LogSender::vACDM, "Version " + std::string(PLUGIN_VERSION) + " loaded", Logger::LogLevel::System); - if (0 != curl_global_init(CURL_GLOBAL_ALL)) DisplayMessage("Unable to initialize the network stack!"); - // get the dll-path char path[MAX_PATH + 1] = {0}; GetModuleFileNameA((HINSTANCE)&__ImageBase, path, MAX_PATH); diff --git a/vcpkg.json b/vcpkg.json index 1d051b1..9debe7b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "dependencies": [ - "curl", - "nlohmann-json", - "geographiclib" + "openssl", + "cpp-httplib", + "nlohmann-json" ] }