From a65aa445fac37d3db1a3d42e3db7420d6591b266 Mon Sep 17 00:00:00 2001 From: Sven Czarnian Date: Thu, 18 Nov 2021 15:55:37 +0100 Subject: [PATCH] compare the backend's version with the plugin's version --- src/CMakeLists.txt | 6 ++- src/PlugIn.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++- src/PlugIn.h | 4 ++ 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 33f0e79..98193d8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,8 @@ # Brief: # Creates the plug-in which is used by Euroscope +ADD_DEFINITIONS(-DCURL_STATICLIB) + # define the Google Protobuf-files SET(PROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/com/protobuf/Aircraft.proto @@ -86,8 +88,8 @@ ADD_LIBRARY( # define the dependencies TARGET_INCLUDE_DIRECTORIES(ArrivalMANager INTERFACE EuroScope) -TARGET_LINK_LIBRARIES(ArrivalMANager EuroScope GSL Shlwapi) -TARGET_LINK_LIBRARIES(ArrivalMANager cppzmq protobuf) +TARGET_LINK_LIBRARIES(ArrivalMANager EuroScope libcurl GSL Shlwapi) +TARGET_LINK_LIBRARIES(ArrivalMANager cppzmq protobuf jsoncpp) # configure the debugger and update the linker flags IF(MSVC) diff --git a/src/PlugIn.cpp b/src/PlugIn.cpp index b8c5b4f..6a5eca8 100644 --- a/src/PlugIn.cpp +++ b/src/PlugIn.cpp @@ -17,6 +17,9 @@ #include #include +#include +#include + #include #include #include @@ -28,6 +31,16 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase; using namespace aman; +static std::string __receivedAmanData; + +static std::size_t receiveCurl(void* ptr, std::size_t size, std::size_t nmemb, void* stream) { + (void)stream; + + std::string serverResult = static_cast(ptr); + __receivedAmanData += serverResult; + return size * nmemb; +} + PlugIn::PlugIn() : EuroScopePlugIn::CPlugIn(EuroScopePlugIn::COMPATIBILITY_CODE, PLUGIN_NAME, @@ -37,7 +50,10 @@ PlugIn::PlugIn() : m_configuration(), m_screen(), m_updateQueueLock(), - m_updateQueue() { + m_updateQueue(), + m_compatible(false), + m_airportsLock(), + m_airports() { GOOGLE_PROTOBUF_VERIFY_VERSION; this->DisplayUserMessage(PLUGIN_NAME, "INFO", (std::string("Loaded ") + PLUGIN_NAME + " " + PLUGIN_VERSION).c_str(), true, true, false, false, false); @@ -75,6 +91,7 @@ PlugIn::PlugIn() : BackendNotification::instance().deinitialize(); return; } + this->validateBackendData(); } PlugIn::~PlugIn() noexcept { @@ -84,6 +101,78 @@ PlugIn::~PlugIn() noexcept { google::protobuf::ShutdownProtobufLibrary(); } +void PlugIn::validateBackendData() { + std::string url = "http://" + this->m_configuration.address + ":5000/aman/airports"; + CURL* curl = curl_easy_init(); + CURLcode result; + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, static_cast(CURL_HTTP_VERSION_1_1)); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receiveCurl); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L); + + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Accept: */*"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + __receivedAmanData.clear(); + + result = curl_easy_perform(curl); + std::lock_guard guard(this->m_airportsLock); + this->m_airports.clear(); + this->m_compatible = false; + + if (CURLE_OK != result) { + MessageBoxA(nullptr, "Unable to receive backend information", "AMAN-Error", MB_OK); + return; + } + + /* validate the json data */ + Json::Value root; + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + if (false == reader->parse(__receivedAmanData.c_str(), __receivedAmanData.c_str() + __receivedAmanData.length(), &root, nullptr)) { + MessageBoxA(nullptr, "Received invalid backend data", "AMAN-Error", MB_OK); + return; + } + + std::vector airports; + std::string version; + for (auto it = root.begin(); root.end() != it; ++it) { + if ("version" == it.key().asString()) { + version = it->asString(); + } + else if ("airports" == it.key().asString() && true == it->isArray()) { + auto airportArray = *it; + + airports.reserve(airportArray.size()); + for (auto i = 0; i < airportArray.size(); ++i) + airports.push_back(airportArray[i].asString()); + } + } + + /* invalid version or airports info */ + auto entries = String::splitString(version, "."); + if (3 != entries.size() || 0 == airports.size()) { + MessageBoxA(nullptr, "Unable to receive backend information", "AMAN-Error", MB_OK); + return; + } + + /* incompatible communication version */ + if (PLUGIN_MAJOR_VERSION != std::atoi(entries[0].c_str()) || PLUGIN_MINOR_VERSION != std::atoi(entries[1].c_str())) { + MessageBoxA(nullptr, "Plugin version is outdated. An update is required", "AMAN-Error", MB_OK); + return; + } + + this->m_airports = airports; + this->m_compatible = true; +} + EuroScopePlugIn::CRadarScreen* PlugIn::OnRadarScreenCreated(const char* displayName, bool needsRadarContent, bool geoReferenced, bool canBeSaved, bool canBeCreated) { std::ignore = needsRadarContent; diff --git a/src/PlugIn.h b/src/PlugIn.h index bda4a27..c94ab19 100644 --- a/src/PlugIn.h +++ b/src/PlugIn.h @@ -41,6 +41,7 @@ namespace aman { enum class TagItemElement { }; + void validateBackendData(); aman::Aircraft* generateAircraftMessage(const EuroScopePlugIn::CRadarTarget& target); void generateAircraftReportMessage(const EuroScopePlugIn::CRadarTarget& radarTarget, aman::AircraftReport* report); @@ -48,6 +49,9 @@ namespace aman { std::shared_ptr m_screen; std::mutex m_updateQueueLock; std::list m_updateQueue; + bool m_compatible; + std::mutex m_airportsLock; + std::vector m_airports; public: /**