From 67b228a91cac666797a7a678df1db0dbd34c5a61 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 11 Mar 2019 15:24:32 -0700 Subject: [PATCH] Added packet stats --- common/eq_stream_intf.h | 9 +++++++++ common/eq_stream_proxy.cpp | 5 +++++ common/eq_stream_proxy.h | 1 + common/net/eqstream.cpp | 28 ++++++++++++++++++++++++++++ common/net/eqstream.h | 7 +++++++ zone/command.cpp | 21 ++++++++++++++++++++- 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 14bfcd265..a48735dba 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -30,12 +30,20 @@ public: uint16 first_eq_opcode; uint32 first_length; //0=dont check length }; + typedef enum { MatchNotReady, MatchSuccessful, MatchFailed } MatchState; + struct Stats + { + EQ::Net::DaybreakConnectionStats DaybreakStats; + int RecvCount[_maxEmuOpcode]; + int SentCount[_maxEmuOpcode]; + }; + virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) = 0; virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true) = 0; virtual EQApplicationPacket *PopPacket() = 0; @@ -53,6 +61,7 @@ public: virtual void SetOpcodeManager(OpcodeManager **opm) = 0; virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; } virtual std::shared_ptr GetRawConnection() const = 0; + virtual Stats GetStats() const = 0; }; #endif /*EQSTREAMINTF_H_*/ diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index 3f9c977ea..e7021b8b1 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -94,6 +94,11 @@ std::shared_ptr EQStreamProxy::GetRawConnection() c return m_stream->GetRawConnection(); } +EQStreamInterface::Stats EQStreamProxy::GetStats() const +{ + return m_stream->GetStats(); +} + bool EQStreamProxy::CheckState(EQStreamState state) { if(m_stream) return(m_stream->CheckState(state)); diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index c5b47a20e..ebb82490a 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -32,6 +32,7 @@ public: virtual EQStreamState GetState(); virtual void SetOpcodeManager(OpcodeManager **opm); virtual std::shared_ptr GetRawConnection() const; + virtual Stats GetStats() const; protected: std::shared_ptr const m_stream; //we own this stream object. diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index 8e05071e7..1f9635e82 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -67,6 +67,9 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) opcode = p->GetOpcodeBypass(); } else { + if (m_owner->m_options.track_opcode_stats) { + m_packet_sent_count[p->GetOpcode()]++; //Wont bother with bypass tracking of these since those are rare for testing anyway + } opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode()); } @@ -116,6 +119,10 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() { } EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode); + if (m_owner->m_options.track_opcode_stats) { + m_packet_recv_count[emu_op]++; + } + EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->m_options.opcode_size, p->Length() - m_owner->m_options.opcode_size); ret->SetProtocolOpcode(opcode); m_packet_queue.pop_front(); @@ -215,3 +222,24 @@ EQStreamState EQ::Net::EQStream::GetState() { return CLOSED; } } + +EQ::Net::EQStream::Stats EQ::Net::EQStream::GetStats() const +{ + Stats ret; + ret.DaybreakStats = m_connection->GetStats(); + + for (int i = 0; i < _maxEmuOpcode; ++i) { + ret.RecvCount[i] = 0; + ret.SentCount[i] = 0; + } + + for (auto &s : m_packet_sent_count) { + ret.SentCount[s.first] = s.second; + } + + for (auto &r : m_packet_recv_count) { + ret.RecvCount[r.first] = r.second; + } + + return ret; +} diff --git a/common/net/eqstream.h b/common/net/eqstream.h index 9fb958cd1..1ff26c04f 100644 --- a/common/net/eqstream.h +++ b/common/net/eqstream.h @@ -6,6 +6,7 @@ #include "daybreak_connection.h" #include #include +#include namespace EQ { @@ -19,6 +20,7 @@ namespace EQ EQStreamManagerOptions(int port, bool encoded, bool compressed) { opcode_size = 2; + track_opcode_stats = false; //World seems to support both compression and xor zone supports one or the others. //Enforce one or the other in the convienence construct @@ -35,6 +37,7 @@ namespace EQ } int opcode_size; + bool track_opcode_stats; DaybreakConnectionManagerOptions daybreak_options; }; @@ -87,11 +90,15 @@ namespace EQ virtual std::shared_ptr GetRawConnection() const { return m_connection; } + + virtual Stats GetStats() const; private: EQStreamManager *m_owner; std::shared_ptr m_connection; OpcodeManager **m_opcode_manager; std::deque> m_packet_queue; + std::unordered_map m_packet_recv_count; + std::unordered_map m_packet_sent_count; friend class EQStreamManager; }; } diff --git a/zone/command.cpp b/zone/command.cpp index 5d31972ac..202f62316 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -9489,7 +9489,8 @@ void command_netstats(Client *c, const Seperator *sep) auto connection = c->Connection(); auto &opts = connection->GetRawConnection()->GetManager()->GetOptions(); - auto stats = connection->GetRawConnection()->GetStats(); + auto eqs_stats = connection->GetStats(); + auto &stats = eqs_stats.DaybreakStats; auto now = EQ::Net::Clock::now(); auto sec_since_stats_reset = std::chrono::duration_cast>(now - stats.created).count(); @@ -9520,6 +9521,24 @@ void command_netstats(Client *c, const Seperator *sep) c->Message(0, "Outgoing Link Saturation %.2f%% (%.2fkb/sec)", 100.0 * (1.0 - ((opts.outgoing_data_rate - stats.datarate_remaining) / opts.outgoing_data_rate)), opts.outgoing_data_rate); } + c->Message(0, "--------------------------------------------------------------------"); + c->Message(0, "Sent Packet Types"); + for (auto i = 0; i < _maxEmuOpcode; ++i) { + auto cnt = eqs_stats.SentCount[i]; + if (cnt > 0) { + c->Message(0, "%s: %u", OpcodeNames[i], cnt); + } + } + + c->Message(0, "--------------------------------------------------------------------"); + c->Message(0, "Recv Packet Types"); + for (auto i = 0; i < _maxEmuOpcode; ++i) { + auto cnt = eqs_stats.RecvCount[i]; + if (cnt > 0) { + c->Message(0, "%s: %u", OpcodeNames[i], cnt); + } + } + c->Message(0, "--------------------------------------------------------------------"); } }