From d6cbf10854dab85d00a916b6cd815c4aa0f14a1f Mon Sep 17 00:00:00 2001 From: Roland Winklmeier Date: Sun, 5 Oct 2014 20:01:39 +0200 Subject: [PATCH] refs #324 airspace watchdog CAirspaceWatchdog times out clients, if a no update has been received for a configured time --- src/blackcore/airspace_watchdog.cpp | 72 ++++++++++++++++++++++++ src/blackcore/airspace_watchdog.h | 85 +++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 src/blackcore/airspace_watchdog.cpp create mode 100644 src/blackcore/airspace_watchdog.h diff --git a/src/blackcore/airspace_watchdog.cpp b/src/blackcore/airspace_watchdog.cpp new file mode 100644 index 000000000..6ac8490a1 --- /dev/null +++ b/src/blackcore/airspace_watchdog.cpp @@ -0,0 +1,72 @@ +/* Copyright (C) 2014 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "airspace_watchdog.h" +#include "blackmisc/logmessage.h" + +namespace BlackCore +{ + + using namespace BlackMisc; + using namespace BlackMisc::Aviation; + using namespace BlackMisc::PhysicalQuantities; + + CAirspaceWatchdog::CAirspaceWatchdog(QObject *parent) + : QObject(parent) + { + startTimer(5000); + } + + CAirspaceWatchdog::CAirspaceWatchdog(const CTime &initialTimeOut, QObject *parent) + : QObject(parent), m_timeout(initialTimeOut) + { + } + + void CAirspaceWatchdog::addCallsign(const CCallsign &callsign) + { + if (m_callsignTimestamps.contains(callsign)) return; + m_callsignTimestamps.insert(callsign, QDateTime::currentDateTimeUtc()); + } + + void CAirspaceWatchdog::resetCallsign(const CCallsign &callsign) + { + Q_ASSERT(m_callsignTimestamps.contains(callsign)); + m_callsignTimestamps[callsign] = QDateTime::currentDateTimeUtc(); + } + + void CAirspaceWatchdog::removeCallsign(const CCallsign &callsign) + { + m_callsignTimestamps.remove(callsign); + } + + void CAirspaceWatchdog::removeAll() + { + m_callsignTimestamps.clear(); + } + + void CAirspaceWatchdog::timerEvent(QTimerEvent *event) + { + Q_UNUSED(event) + checkTimeouts(); + } + + void CAirspaceWatchdog::checkTimeouts() + { + for (CCallsign callsign : m_callsignTimestamps.keys()) + { + QDateTime timestamp = m_callsignTimestamps.value(callsign); + if (timestamp.secsTo(QDateTime::currentDateTimeUtc()) > m_timeout.value(CTimeUnit::s())) + { + CLogMessage().debug(this) << "Aircraft " << callsign.toQString() << "timed out!"; + m_callsignTimestamps.remove(callsign); + emit timeout(callsign); + } + } + } +} diff --git a/src/blackcore/airspace_watchdog.h b/src/blackcore/airspace_watchdog.h new file mode 100644 index 000000000..0f127cd6c --- /dev/null +++ b/src/blackcore/airspace_watchdog.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2014 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKCORE_AIRSPACE_WATCHDOG_H +#define BLACKCORE_AIRSPACE_WATCHDOG_H + +#include "blackmisc/pqtime.h" +#include "blackmisc/avcallsign.h" +#include +#include + +namespace BlackCore +{ + + /*! + * CAirspaceWatchdog monitores any added callsign, if it has timed out. + * + * This class was introduced due to a flaw in the VATSIM server implementation: + * Every client needs to send an add/delete packet on its own to inform other + * clients nearby. The server does not take care of that. When a client crashes, + * no delete packet is ever sent. This class therefore monitors callsigns and + * emits a timeout signal if it wasn't resetted during the specified timeout + * value. + */ + class CAirspaceWatchdog : public QObject + { + Q_OBJECT + + public: + //! Default constructor + CAirspaceWatchdog(QObject *parent); + + //! Constructor + CAirspaceWatchdog(const BlackMisc::PhysicalQuantities::CTime & initialTimeOut, QObject *parent); + + //! Log message category + static QString getMessageCategory() { return "swift.airspacewatchdog"; } + + //! Sets the maximum time, after a client is considered timed out + void setTimeout(const BlackMisc::PhysicalQuantities::CTime &value) { m_timeout = value; } + + //! Returns the currently configured timeout value + const BlackMisc::PhysicalQuantities::CTime &getTimeout() const { return m_timeout; } + + //! Add a new callsign to watch list + void addCallsign(const BlackMisc::Aviation::CCallsign &callsign); + + //! Reset the watchdog for Callsign + //! The callsign must have been added by \sa addCallsign before. + void resetCallsign(const BlackMisc::Aviation::CCallsign &callsign); + + //! Remove Callsign from watch list + void removeCallsign(const BlackMisc::Aviation::CCallsign &callsign); + + //! Remove all watched callsigns + void removeAll(); + + signals: + //! Callsign has timed out + void timeout(const BlackMisc::Aviation::CCallsign &callsign); + + protected: + //! \overload QObject::timerEvent + virtual void timerEvent(QTimerEvent * event) override; + + private: + + void checkTimeouts(); + + BlackMisc::PhysicalQuantities::CTime m_timeout = {15, BlackMisc::PhysicalQuantities::CTimeUnit::s() }; //!< Timeout value + QHash m_callsignTimestamps; //!< Hash of callsigns and latest timestamp + + }; + +} // namespace + +#endif