diff --git a/include/aman/com/BackendNotification.h b/include/aman/com/Backend.h similarity index 68% rename from include/aman/com/BackendNotification.h rename to include/aman/com/Backend.h index 6cf7ec5..2002faa 100644 --- a/include/aman/com/BackendNotification.h +++ b/include/aman/com/Backend.h @@ -1,6 +1,6 @@ /* - * @brief Defines the backend notification module to communicate with the backend - * @file aman/com/BackendNotification.h + * @brief Defines the backend module to communicate with the backend + * @file aman/com/Backend.h * @author Sven Czarnian * @copyright Copyright 2021 Sven Czarnian * @license This project is published under the GNU General Public License v3 (GPLv3) @@ -18,14 +18,14 @@ namespace aman { /** - * @brief Defines the bakcend notification class which sends aircraft information to the backend + * @brief Defines the bakcend class which sends and receives aircraft information to and from the backend * @ingroup com */ - class BackendNotification { + class Backend { private: std::unique_ptr m_socket; - BackendNotification() noexcept; + Backend() noexcept; template bool setSocketKey(const std::string& key, T entry) { @@ -38,11 +38,13 @@ namespace aman { } } + std::shared_ptr receiveSequence(); + public: - BackendNotification(const BackendNotification&) = delete; - BackendNotification(BackendNotification&&) = delete; - BackendNotification& operator=(const BackendNotification&) = delete; - BackendNotification& operator=(BackendNotification&&) = delete; + Backend(const Backend&) = delete; + Backend(Backend&&) = delete; + Backend& operator=(const Backend&) = delete; + Backend& operator=(Backend&&) = delete; /** * @brief Initializes the aircraft reporter @@ -62,13 +64,13 @@ namespace aman { /** * @brief Sends a new message to the backend * @param[in] report The new aircraft update - * @return True if the report is sent, else false + * @return Receives the current sequence of the airport */ - bool send(aman::AircraftUpdate& report); + std::shared_ptr update(aman::AircraftUpdate& report); /** * @brief Returns the reporter instance * @return The system-wide instance */ - static BackendNotification& instance() noexcept; + static Backend& instance() noexcept; }; } diff --git a/include/aman/com/BackendReceiver.h b/include/aman/com/BackendReceiver.h deleted file mode 100644 index 680945e..0000000 --- a/include/aman/com/BackendReceiver.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * @brief Defines the aircraft scheduling notifier module to receive plans from the backend - * @file aman/com/BackendReceiver.h - * @author Sven Czarnian - * @copyright Copyright 2021 Sven Czarnian - * @license This project is published under the GNU General Public License v3 (GPLv3) - */ - -#pragma once - -#include -#include -#include - -#include - -#pragma warning(push, 0) -#include "protobuf/Communication.pb.h" -#pragma warning(pop) - -namespace aman { - /** - * @brief Defines the aircraft scheduling notification class to receive scheduling sequences - * @ingroup com - */ - class BackendReceiver { - private: - std::unique_ptr m_socket; - std::thread m_receiverThread; - std::atomic_bool m_stopReceiver; - std::list> m_sequences; - std::mutex m_sequencesLock; - - BackendReceiver() noexcept; - - template - bool setSocketKey(const std::string& key, T entry) { - try { - this->m_socket->set(entry, key); - return true; - } - catch (std::exception&) { - return false; - } - } - void receiveSequence(); - void run(); - - public: - BackendReceiver(const BackendReceiver&) = delete; - BackendReceiver(BackendReceiver&&) = delete; - BackendReceiver& operator=(const BackendReceiver&) = delete; - BackendReceiver& operator=(BackendReceiver&&) = delete; - - /** - * @brief Initializes the aircraft scheduler - * @param[in] configuration The current AMAM communication configuration - * @return True if the initialization is done, else false - */ - bool initialize(const Communication& configuration); - /** - * @brief Terminates the scheduler connection - */ - bool deinitialize(); - /** - * @brief Checks if the scheduler is initialized - * @return True if it is initialized, else false - */ - bool initialized() const noexcept; - /** - * @brief Returns the current sequence of the receiver queue - * @return The sequence queue - */ - std::shared_ptr receive(); - /** - * @brief Returns the scheduling instance - * @return The system-wide instance - */ - static BackendReceiver& instance() noexcept; - }; -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 98193d8..1eb2d46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,8 +34,7 @@ SET(SOURCE_FILES ) SET(SOURCE_COM_FILES - com/BackendReceiver.cpp - com/BackendNotification.cpp + com/Backend.cpp com/ZmqContext.cpp com/ZmqContext.h ) @@ -53,8 +52,7 @@ SET(SOURCE_FILES_RES ) SET(INCLUDE_COM_FILES - ${CMAKE_SOURCE_DIR}/include/aman/com/BackendReceiver.h - ${CMAKE_SOURCE_DIR}/include/aman/com/BackendNotification.h + ${CMAKE_SOURCE_DIR}/include/aman/com/Backend.h ) SET(INCLUDE_CONFIG_FILES diff --git a/src/PlugIn.cpp b/src/PlugIn.cpp index 6a5eca8..33d85df 100644 --- a/src/PlugIn.cpp +++ b/src/PlugIn.cpp @@ -15,11 +15,10 @@ #include #include -#include -#include #include #include +#include #include #include #include @@ -81,22 +80,14 @@ PlugIn::PlugIn() : ZmqContext::instance().initialize(); - if (false == BackendNotification::instance().initialize(this->m_configuration)) { + if (false == Backend::instance().initialize(this->m_configuration)) this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to initialize the reporter-connection to the backend", true, true, true, true, true); - return; - } - if (false == BackendReceiver::instance().initialize(this->m_configuration)) { - this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to initialize the scheduling-connection to the backend", true, true, true, true, true); - BackendNotification::instance().deinitialize(); - return; - } this->validateBackendData(); } PlugIn::~PlugIn() noexcept { - BackendReceiver::instance().deinitialize(); - BackendNotification::instance().deinitialize(); + Backend::instance().deinitialize(); ZmqContext::instance().deinitialize(); google::protobuf::ShutdownProtobufLibrary(); } @@ -356,7 +347,9 @@ void PlugIn::generateAircraftReportMessage(const EuroScopePlugIn::CRadarTarget& void PlugIn::OnRadarTargetPositionUpdate(EuroScopePlugIn::CRadarTarget radarTarget) { /* do nothing if the reporter is not initialized and ignore invalid targets */ - if (false == BackendNotification::instance().initialized() || false == radarTarget.IsValid()) + if (false == this->m_compatible || false == Backend::instance().initialized() || false == radarTarget.IsValid()) + return; + if (false == radarTarget.GetCorrelatedFlightPlan().GetTrackingControllerIsMe()) return; std::lock_guard guard(this->m_updateQueueLock); @@ -364,17 +357,19 @@ void PlugIn::OnRadarTargetPositionUpdate(EuroScopePlugIn::CRadarTarget radarTarg } void PlugIn::OnTimer(int counter) { - if (false == BackendNotification::instance().initialized() || 0 != (counter % 10)) + if (false == this->m_compatible || false == Backend::instance().initialized() || 0 != (counter % 10)) return; this->m_updateQueueLock.lock(); aman::AircraftUpdate update; + bool inserted = false; for (auto target = this->RadarTargetSelectFirst(); true == target.IsValid(); target = this->RadarTargetSelectNext(target)) { auto it = std::find(this->m_updateQueue.cbegin(), this->m_updateQueue.cend(), target.GetCallsign()); if (this->m_updateQueue.cend() != it) { auto report = update.add_reports(); this->generateAircraftReportMessage(target, report); + inserted = true; } } @@ -382,6 +377,6 @@ void PlugIn::OnTimer(int counter) { this->m_updateQueueLock.unlock(); /* send the report */ - if (false == BackendNotification::instance().send(update)) + if (true == inserted && nullptr != Backend::instance().update(update)) this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to send a new aircraft report update", true, true, true, true, true); } diff --git a/src/com/BackendNotification.cpp b/src/com/Backend.cpp similarity index 55% rename from src/com/BackendNotification.cpp rename to src/com/Backend.cpp index 511b726..6f9d74e 100644 --- a/src/com/BackendNotification.cpp +++ b/src/com/Backend.cpp @@ -2,31 +2,30 @@ * Author: * Sven Czarnian * Brief: - * Implements the backend notification + * Implements the backend communication * Copyright: * 2021 Sven Czarnian * License: * GNU General Public License v3 (GPLv3) */ -#include +#include #include #include "ZmqContext.h" using namespace aman; -BackendNotification::BackendNotification() noexcept : +Backend::Backend() noexcept : m_socket() { } -bool BackendNotification::initialize(const Communication& configuration) { +bool Backend::initialize(const Communication& configuration) { if (nullptr != this->m_socket) return true; if (false == configuration.valid) return false; - this->m_socket = std::make_unique(ZmqContext::instance().context(), zmq::socket_type::pub); - this->m_socket->set(zmq::sockopt::immediate, true); + this->m_socket = std::make_unique(ZmqContext::instance().context(), zmq::socket_type::req); /* configure the encryption */ if (false == this->setSocketKey(configuration.serverPublicIdentifier, zmq::sockopt::curve_serverkey)) @@ -48,7 +47,7 @@ bool BackendNotification::initialize(const Communication& configuration) { return true; } -bool BackendNotification::deinitialize() { +bool Backend::deinitialize() { if (nullptr == this->m_socket) return true; @@ -58,13 +57,33 @@ bool BackendNotification::deinitialize() { return true; } -bool BackendNotification::initialized() const noexcept { +bool Backend::initialized() const noexcept { return nullptr != this->m_socket; } -bool BackendNotification::send(aman::AircraftUpdate& report) { - bool retval = false; +std::shared_ptr Backend::receiveSequence() { + zmq::message_t message; + if (nullptr == this->m_socket) + return nullptr; + + try { + //auto result = this->m_socket->recv(message, zmq::recv_flags::dontwait); + auto result = this->m_socket->recv(message); + if (false == result.has_value() || 0 == result.value()) + return nullptr; + } + catch (zmq::error_t&) { + return nullptr; + } + + std::unique_ptr retval = std::make_unique(); + retval->ParseFromString(reinterpret_cast(message.data())); + + return std::move(retval); +} + +std::shared_ptr Backend::update(aman::AircraftUpdate& report) { if (nullptr != this->m_socket) { /* serialize the report */ std::string serialized = report.SerializeAsString(); @@ -72,19 +91,20 @@ bool BackendNotification::send(aman::AircraftUpdate& report) { std::memcpy(message.data(), serialized.c_str(), serialized.size()); try { - auto size = message.size(); - auto result = this->m_socket->send(message, zmq::send_flags::none); - retval = result.value() == size; + const auto size = message.size(); + const auto result = this->m_socket->send(message, zmq::send_flags::none); + if (result.value() == size) + return this->receiveSequence(); } catch (zmq::error_t&) { - return false; + return nullptr; } } - return retval; + return nullptr; } -BackendNotification& BackendNotification::instance() noexcept { - static BackendNotification __instance; +Backend& Backend::instance() noexcept { + static Backend __instance; return __instance; } diff --git a/src/com/BackendReceiver.cpp b/src/com/BackendReceiver.cpp deleted file mode 100644 index 7576d7e..0000000 --- a/src/com/BackendReceiver.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Author: - * Sven Czarnian - * Brief: - * Implements the backend receiver - * Copyright: - * 2021 Sven Czarnian - * License: - * GNU General Public License v3 (GPLv3) - */ - -#include - -#include "ZmqContext.h" - -using namespace aman; -using namespace std::chrono; - -BackendReceiver::BackendReceiver() noexcept : - m_socket(), - m_receiverThread(), - m_stopReceiver(false), - m_sequences(), - m_sequencesLock() { } - -bool BackendReceiver::initialize(const Communication& configuration) { - if (nullptr != this->m_socket) - return true; - if (false == configuration.valid) - return false; - - this->m_socket = std::make_unique(ZmqContext::instance().context(), zmq::socket_type::sub); - - /* configure the encryption */ - if (false == this->setSocketKey(configuration.serverPublicIdentifier, zmq::sockopt::curve_serverkey)) - return false; - if (false == this->setSocketKey(configuration.clientPublicIdentifier, zmq::sockopt::curve_publickey)) - return false; - if (false == this->setSocketKey(configuration.clientPrivateIdentifier, zmq::sockopt::curve_secretkey)) - return false; - - /* connect to the server */ - try { - this->m_socket->connect("tcp://" + configuration.address + ":" + std::to_string(configuration.portNotification)); - } - catch (zmq::error_t&) { - this->m_socket = std::unique_ptr(); - return false; - } - - this->m_stopReceiver = false; - this->m_receiverThread = std::thread(&BackendReceiver::run, this); - - return true; -} - -bool BackendReceiver::deinitialize() { - if (nullptr == this->m_socket) - return true; - - this->m_stopReceiver = true; - this->m_receiverThread.join(); - this->m_socket->close(); - this->m_socket = std::make_unique(); - - return true; -} - -bool BackendReceiver::initialized() const noexcept { - return nullptr != this->m_socket; -} - -void BackendReceiver::receiveSequence() { - zmq::message_t message; - - if (nullptr == this->m_socket) - return; - - try { - auto result = this->m_socket->recv(message, zmq::recv_flags::dontwait); - if (false == result.has_value() || 0 == result.value()) - return; - } - catch (zmq::error_t&) { - return; - } - - std::unique_ptr retval = std::make_unique(); - retval->ParseFromString(reinterpret_cast(message.data())); - - std::lock_guard guard(this->m_sequencesLock); - this->m_sequences.push_back(std::move(retval)); -} - -void BackendReceiver::run() { - while (false == this->m_stopReceiver) { - auto message = this->receive(); - if (nullptr == message) { - std::this_thread::sleep_for(500ms); - continue; - } - - this->receiveSequence(); - } -} - -std::shared_ptr BackendReceiver::receive() { - std::lock_guard guard(this->m_sequencesLock); - if (0 != this->m_sequences.size()) { - auto retval = this->m_sequences.front(); - this->m_sequences.pop_front(); - return retval; - } - - return nullptr; -} - -BackendReceiver& BackendReceiver::instance() noexcept { - static BackendReceiver __instance; - return __instance; -}