//! \addtogroup IO //! \{ //! \file pidiagnostics.h //! \brief //! \~english Connection quality diagnostics //! \~russian Диагностика качества связи //! \details //! \~english This class provides connection quality diagnostics based on packet reception statistics //! \~russian Класс обеспечивает диагностику качества связи на основе статистики приема пакетов //! \~\} /* PIP - Platform Independent Primitives Speed and quality in/out diagnostics Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIDIAGNOSTICS_H #define PIDIAGNOSTICS_H #include "piqueue.h" #include "pitimer.h" //! \~english Connection quality diagnostics class based on packet statistics //! \~russian Класс диагностики качества связи на основе статистики пакетов class PIP_EXPORT PIDiagnostics: public PITimer { PIOBJECT_SUBCLASS(PIDiagnostics, PITimer); friend class PIConnection; public: NO_COPY_CLASS(PIDiagnostics); //! \~english Constructs an empty diagnostics and if "start_" start it //! \~russian Создает пустую диагностику и запускает её, если "start_" установлено PIDiagnostics(bool start_ = true); //! \~english Virtual destructor //! \~russian Виртуальный деструктор virtual ~PIDiagnostics(); //! \~english Connection quality enumeration //! \~russian Перечисление качества связи enum Quality { //! \~english Unknown, no one packet received yet //! \~russian Неизвестно, еще не получен ни один пакет Unknown = 1, //! \~english No connection, no one correct packet received for last period //! \~russian Нет соединения, за последний период не получено ни одного корректного пакета Failure = 2, //! \~english Bad connection, correct packets received <= 20% //! \~russian Плохое соединение, корректных пакетов получено <= 20% Bad = 3, //! \~english Average connection, correct packets received > 20% and <= 80% //! \~russian Среднее соединение, корректных пакетов получено > 20% и <= 80% Average = 4, //! \~english Good connection, correct packets received > 80% //! \~russian Хорошее соединение, корректных пакетов получено > 80% Good = 5 }; //! \~english Information about current diagnostics state //! \~russian Информация о текущем состоянии диагностики struct PIP_EXPORT State { //! \~english Default constructor //! \~russian Конструктор по умолчанию State(); //! \~english Immediate frequency in Hz //! \~russian Мгновенная частота в Гц float immediate_freq = 0.f; //! \~english Integral frequency in Hz //! \~russian Интегральная частота в Гц float integral_freq = 0.f; //! \~english Received packets per second //! \~russian Принятых пакетов в секунду ullong received_packets_per_sec = 0ull; //! \~english Total received packets count //! \~russian Общее количество принятых пакетов ullong received_packets = 0ull; //! \~english Total received wrong packets count //! \~russian Общее количество неправильно принятых пакетов ullong received_packets_wrong = 0ull; //! \~english Received bytes per second //! \~russian Принятых байт в секунду ullong received_bytes_per_sec = 0ull; //! \~english Total received bytes count //! \~russian Общее количество принятых байт ullong received_bytes = 0ull; //! \~english Total received wrong bytes count //! \~russian Общее количество неправильно принятых байт ullong received_bytes_wrong = 0ull; //! \~english Sended packets per second //! \~russian Отправленных пакетов в секунду ullong sended_packets_per_sec = 0ull; //! \~english Total sended packets count //! \~russian Общее количество отправленных пакетов ullong sended_packets = 0ull; //! \~english Sended bytes per second //! \~russian Отправленных байт в секунду ullong sended_bytes_per_sec = 0ull; //! \~english Total sended bytes count //! \~russian Общее количество отправленных байт ullong sended_bytes = 0ull; //! \~english Receive speed string in format "n {B|kB|MB|GB|TB}/s" //! \~russian Строка скорости приема в формате "n {B|kB|MB|GB|TB}/s" PIString receive_speed; //! \~english Send speed string in format "n {B|kB|MB|GB|TB}/s" //! \~russian Строка скорости отправки в формате "n {B|kB|MB|GB|TB}/s" PIString send_speed; //! \~english Current connection quality //! \~russian Текущее качество соединения PIDiagnostics::Quality quality = PIDiagnostics::Unknown; }; //! \~english Returns current diagnostics state //! \~russian Возвращает текущее состояние диагностики PIDiagnostics::State state() const; //! \~english Returns period of full disconnect in seconds and period of averaging frequency //! \~russian Возвращает период полного отключения в секундах и период усреднения частоты PISystemTime disconnectTimeout() const { return disconn_; } //! \~english Set disconnect timeout (deprecated, use PISystemTime version) //! \~russian Установить таймаут отключения (устаревший, используйте версию с PISystemTime) void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") { setDisconnectTimeout(PISystemTime::fromSeconds(s)); } //! \~english Set disconnect timeout //! \~russian Установить таймаут отключения void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); } //! \~english Returns connection quality //! \~russian Возвращает качество соединения PIDiagnostics::Quality quality() const; //! \~english Returns receive speed in format "n {B|kB|MB|GB|TB}/s" //! \~russian Возвращает скорость приема в формате "n {B|kB|MB|GB|TB}/s" PIString receiveSpeed() const; //! \~english Returns send speed in format "n {B|kB|MB|GB|TB}/s" //! \~russian Возвращает скорость отправки в формате "n {B|kB|MB|GB|TB}/s" PIString sendSpeed() const; //! \handlers //! \{ //! \fn void start() //! \~english Start diagnostics with default period (1000ms) //! \~russian Запустить диагностику с периодом по умолчанию (1000мс) EVENT_HANDLER0(void, start); //! \fn void start(PISystemTime interval) //! \~english Start diagnostics with specified period //! \~russian Запустить диагностику с указанным периодом EVENT_HANDLER1(void, start, PISystemTime, interval); //! \fn void reset() //! \~english Reset diagnostics counters //! \~russian Сбросить счетчики диагностики EVENT_HANDLER0(void, reset); //! \fn void received(int size) //! \~english Notify diagnostics about received packet //! \~russian Уведомить диагностику о принятом пакете EVENT_HANDLER1(void, received, int, size) { received(size, true); } //! \fn void received(int size, bool correct) //! \~english Notify diagnostics about received packet with correctness flag //! \~russian Уведомить диагностику о принятом пакете с флагом корректности EVENT_HANDLER2(void, received, int, size, bool, correct); //! \fn void sended(int size) //! \~english Notify diagnostics about sended packet //! \~russian Уведомить диагностику об отправленном пакете EVENT_HANDLER1(void, sended, int, size); //! \} //! \events //! \{ //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \~english Emitted when receive quality changes //! \~russian Генерируется при изменении качества приема EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); //! \} private: //! \~english Internal structure for packet statistics history //! \~russian Внутренняя структура для истории статистики пакетов struct PIP_EXPORT Entry { //! \~english Number of correct bytes //! \~russian Количество корректных байт ullong bytes_ok = 0; //! \~english Number of wrong bytes //! \~russian Количество неправильных байт ullong bytes_fail = 0; //! \~english Count of correct packets //! \~russian Количество корректных пакетов uint cnt_ok = 0; //! \~english Count of wrong packets //! \~russian Количество неправильных пакетов uint cnt_fail = 0; //! \~english Flag indicating if entry is empty //! \~russian Флаг, указывающий, что запись пустая bool empty = true; }; //! \~english Equality operator for Entry structure //! \~russian Оператор равенства для структуры Entry friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); //! \~english Inequality operator for Entry structure //! \~russian Оператор неравенства для структуры Entry friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); //! \~english Less-than operator for Entry structure //! \~russian Оператор меньше для структуры Entry friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); //! \~english Timer tick handler //! \~russian Обработчик тика таймера void tick(int) override; //! \~english Calculate history statistics //! \~russian Вычислить статистику истории Entry calcHistory(PIQueue & hist, int & cnt); //! \~english Property changed handler //! \~russian Обработчик изменения свойства void propertyChanged(const char *) override; //! \~english Change disconnect timeout //! \~russian Изменить таймаут отключения void changeDisconnectTimeout(PISystemTime disct); //! \~english History queue for received packets //! \~russian Очередь истории для принятых пакетов PIQueue history_rec, history_send; //! \~english Disconnect timeout //! \~russian Таймаут отключения PISystemTime disconn_; //! \~english Current state //! \~russian Текущее состояние State cur_state; //! \~english Mutex for state access protection //! \~russian Мьютекс для защиты доступа к состоянию mutable PIMutex mutex_state; }; inline bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return f.bytes_ok == s.bytes_ok && f.bytes_fail == s.bytes_fail && f.cnt_ok == s.cnt_ok && f.cnt_fail == s.cnt_fail && f.empty == s.empty; } inline bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return !(f == s); } inline bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return f.bytes_ok < s.bytes_ok; } #endif // PIDIAGNOSTICS_H