#pragma once #include #include #include #include "Definitions.h" namespace ts { namespace server { class TSServer; } namespace stats { struct StatisticEntry { std::atomic use_count{0}; std::chrono::time_point timestamp; uint16_t size = 0; }; struct DataSummery { uint32_t send_minute; uint32_t send_second; uint32_t recv_minute; uint32_t recv_second; uint32_t file_recv; uint32_t file_send; }; struct FullReport { uint64_t connection_packets_sent[4]{0, 0, 0, 0}; uint64_t connection_bytes_sent[4]{0, 0, 0, 0}; uint64_t connection_packets_received[4]{0, 0, 0, 0}; uint64_t connection_bytes_received[4]{0, 0, 0, 0}; uint64_t file_bytes_sent = 0; uint64_t file_bytes_received = 0; }; class ConnectionStatistics { public: struct category { enum value { COMMAND, ACK, VOICE, UNKNOWN }; inline static category::value from_type(const protocol::PacketTypeInfo& type){ if(type == protocol::PacketTypeInfo::Command || type == protocol::PacketTypeInfo::CommandLow) return value::COMMAND; else if(type == protocol::PacketTypeInfo::Ack || type == protocol::PacketTypeInfo::AckLow) return value::ACK; else if(type == protocol::PacketTypeInfo::Voice || type == protocol::PacketTypeInfo::VoiceWhisper) return value::VOICE; return value::UNKNOWN; } }; explicit ConnectionStatistics(const std::shared_ptr& /* root */, bool /* spawn properties */); ~ConnectionStatistics(); std::shared_ptr statistics(); inline void logIncomingPacket(const protocol::ClientPacket& packet) { this->logIncomingPacket(category::from_type(packet.type()), packet.length()); } void logIncomingPacket(const category::value& /* category */, size_t /* length */); inline void logOutgoingPacket(const protocol::ServerPacket& packet) { this->logOutgoingPacket(category::from_type(packet.type()), packet.length()); } void logOutgoingPacket(const category::value& /* category */, size_t /* length */); void logFileTransferIn(uint64_t); void logFileTransferOut(uint64_t); void tick(); DataSummery dataReport(); FullReport full_report(); std::pair mark_file_bytes(); inline bool measure_bandwidths() { return this->_measure_bandwidths; } void measure_bandwidths(bool flag) { this->_measure_bandwidths = flag; } inline bool has_properties() { return !!this->properties; } private: bool _measure_bandwidths = true; std::shared_ptr handle; std::shared_ptr properties; std::atomic connection_packets_sent[4]{0, 0, 0, 0}; std::atomic connection_bytes_sent[4]{0, 0, 0, 0}; std::atomic connection_packets_received[4]{0, 0, 0, 0}; std::atomic connection_bytes_received[4]{0, 0, 0, 0}; std::atomic file_bytes_sent = 0; std::atomic file_bytes_received = 0; std::atomic mark_file_bytes_sent = 0; std::atomic mark_file_bytes_received = 0; spin_lock history_lock_outgoing; spin_lock history_lock_incoming; std::deque history_file_incoming{}; std::deque history_file_outgoing{}; std::deque history_incoming{}; std::deque history_outgoing{}; void _log_incoming_packet(StatisticEntry */* statistics */, int8_t /* type index */); void _log_outgoing_packet(StatisticEntry* /* statistics */, int8_t /* type index */); void _log_incoming_file_packet(StatisticEntry */* statistics */); void _log_outgoing_file_packet(StatisticEntry* /* statistics */); }; } }