270 lines
12 KiB
C++
270 lines
12 KiB
C++
//! \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 <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#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<Entry> & 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<Entry> 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
|