Browse Source

compare the backend's version with the plugin's version

Sven Czarnian 3 years ago
parent
commit
a65aa445fa
3 changed files with 98 additions and 3 deletions
  1. 4 2
      src/CMakeLists.txt
  2. 90 1
      src/PlugIn.cpp
  3. 4 0
      src/PlugIn.h

+ 4 - 2
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)

+ 90 - 1
src/PlugIn.cpp

@@ -17,6 +17,9 @@
 
 #include <aman/com/BackendReceiver.h>
 #include <aman/com/BackendNotification.h>
+#include <curl/curl.h>
+#include <json/json.h>
+
 #include <aman/config/CommunicationFileFormat.h>
 #include <aman/config/IdentifierFileFormat.h>
 #include <aman/helper/String.h>
@@ -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<char*>(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<long>(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<Json::CharReader> 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<std::string> 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;

+ 4 - 0
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<RadarScreen> m_screen;
         std::mutex                   m_updateQueueLock;
         std::list<std::string>       m_updateQueue;
+        bool                         m_compatible;
+        std::mutex                   m_airportsLock;
+        std::vector<std::string>     m_airports;
 
     public:
         /**