/*! \file pidiagnostics.h * \ingroup IO * \~\brief * \~english Connection quality diagnostics * \~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 "pitimer.h" #include "piqueue.h" class PIP_EXPORT PIDiagnostics: public PITimer { PIOBJECT_SUBCLASS(PIDiagnostics, PITimer); friend class PIConnection; public: NO_COPY_CLASS(PIDiagnostics); //! Constructs an empty diagnostics and if "start_" start it PIDiagnostics(bool start_ = true); virtual ~PIDiagnostics(); //! Connection quality enum Quality { Unknown /** Unknown, no one packet received yet */ = 1, Failure /** No connection, no one correct packet received for last period */ = 2, Bad /** Bad connection, correct packets received <= 20% */ = 3, Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, Good /** Good connection, correct packets received > 80% */ = 5 }; //! Information about current diagnostics state struct PIP_EXPORT State { State(); float immediate_freq; float integral_freq; ullong received_packets_per_sec; ullong received_packets; ullong received_packets_wrong; ullong received_bytes_per_sec; ullong received_bytes; ullong received_bytes_wrong; ullong sended_packets_per_sec; ullong sended_packets; ullong sended_bytes_per_sec; ullong sended_bytes; PIString receive_speed; PIString send_speed; PIDiagnostics::Quality quality; }; //! Returns current state PIDiagnostics::State state() const; //! Returns period of full disconnect in seconds and period of averaging frequency float disconnectTimeout() const {return disconn_;} //! Returns period of full disconnect in seconds and period of averaging frequency void setDisconnectTimeout(float s) {setProperty("disconnectTimeout", s);} //! Returns connection quality PIDiagnostics::Quality quality() const; //! Returns receive speed in format "n {B|kB|MB|GB|TB}/s" PIString receiveSpeed() const; //! Returns send speed in format "n {B|kB|MB|GB|TB}/s" PIString sendSpeed() const; EVENT_HANDLER0(void, start) {PITimer::start(100.); changeDisconnectTimeout(disconn_);} EVENT_HANDLER1(void, start, double, msecs) {if (msecs > 0.) {PITimer::start(msecs); changeDisconnectTimeout(disconn_);}} EVENT_HANDLER0(void, reset); EVENT_HANDLER1(void, received, int, size) {received(size, true);} EVENT_HANDLER2(void, received, int, size, bool, correct); EVENT_HANDLER1(void, sended, int, size); EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); //! \handlers //! \{ //! \fn void start(double msecs = 1000.) //! \brief Start diagnostics evaluations with period "msecs" milliseconds //! \fn void reset() //! \brief Reset diagnostics counters //! \fn void received(int size, bool correct = true) //! \brief Notify diagnostics about "correct" corected received packet //! \fn void sended(int size) //! \brief Notify diagnostics about sended packet //! \} //! \events //! \{ //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \brief Raise on change receive quality from "old_quality" to "new_quality" //! \} private: struct PIP_EXPORT Entry { Entry() {bytes_ok = bytes_fail = 0; cnt_ok = cnt_fail = 0; empty = true;} ullong bytes_ok; ullong bytes_fail; uint cnt_ok; uint cnt_fail; bool empty; }; friend bool operator ==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator !=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator <(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); void tick(void *, int); Entry calcHistory(PIQueue & hist, int & cnt); void propertyChanged(const char *); void changeDisconnectTimeout(float disct); PIQueue history_rec, history_send; float disconn_; State cur_state; 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