diff --git a/rehlds/engine/net.h b/rehlds/engine/net.h index 1b8cb39..c39c495 100644 --- a/rehlds/engine/net.h +++ b/rehlds/engine/net.h @@ -276,15 +276,6 @@ typedef struct flow_s float avgkbytespersec; } flow_t; -const int NET_DECOMPRESS_MAX_TIMES = 10; - -typedef struct frag_decomp_failure_s -{ - float failure_times[NET_DECOMPRESS_MAX_TIMES]; - // Count of abnormal fragment decompressions in a time window - int num_failures; -} frag_decomp_failure_t; - const int FRAGMENT_C2S_MIN_SIZE = 16; const int FRAGMENT_S2C_MIN_SIZE = 256; const int FRAGMENT_S2C_MAX_SIZE = 1024; @@ -432,9 +423,6 @@ typedef struct netchan_s // Incoming and outgoing flow metrics flow_t flow[MAX_FLOWS]; - // Stats for decompression of incoming fragments - frag_decomp_failure_t frag_decompress[MAX_STREAMS]; - } netchan_t; #ifdef REHLDS_FIXES diff --git a/rehlds/engine/net_chan.cpp b/rehlds/engine/net_chan.cpp index b95b0a4..b1f9a35 100644 --- a/rehlds/engine/net_chan.cpp +++ b/rehlds/engine/net_chan.cpp @@ -174,10 +174,6 @@ void Netchan_Clear(netchan_t *chan) chan->frag_startpos[i] = 0; chan->frag_length[i] = 0; chan->incomingready[i] = FALSE; - - for (int j = 0; j < NET_DECOMPRESS_MAX_TIMES; j++) - chan->frag_decompress[i].failure_times[j] = 0; - chan->frag_decompress[i].num_failures = 0; } if (chan->tempbuffer) @@ -191,6 +187,7 @@ void Netchan_Clear(netchan_t *chan) void Netchan_Setup(netsrc_t socketnumber, netchan_t *chan, netadr_t adr, int player_slot, void *connection_status, qboolean(*pfnNetchan_Blocksize)(void *)) { Netchan_Clear(chan); + g_GameClients[player_slot]->NetchanClear(); Q_memset(chan, 0, sizeof(netchan_t)); @@ -1460,7 +1457,6 @@ qboolean Netchan_ValidateDecompress(netchan_t *chan, int stream, unsigned int co { #ifdef REHLDS_FIXES int i; - frag_decomp_failure_t *decomp; if (sv_net_incoming_decompression_max_ratio.value <= 0) return TRUE; // validation is disabled @@ -1477,24 +1473,24 @@ qboolean Netchan_ValidateDecompress(netchan_t *chan, int stream, unsigned int co Netchan_DecompressionCvarsBounds(); - decomp = &chan->frag_decompress[stream]; + FragStats_t &stats = g_GameClients[chan->player_slot - 1]->GetFragStats(stream); // check if the client should be rejected based on total failed decompress - if (decomp->num_failures >= sv_net_incoming_decompression_max_failures.value) + if (stats.num_decompress_failures >= sv_net_incoming_decompression_max_failures.value) { for (i = 0; i < sv_net_incoming_decompression_max_failures.value - 1; i++) - decomp->failure_times[i] = decomp->failure_times[i + 1]; + stats.decompress_failure_times[i] = stats.decompress_failure_times[i + 1]; - decomp->num_failures = sv_net_incoming_decompression_max_failures.value - 1; + stats.num_decompress_failures = sv_net_incoming_decompression_max_failures.value - 1; } - decomp->failure_times[decomp->num_failures++] = realtime; + stats.decompress_failure_times[stats.num_decompress_failures++] = realtime; // check if the client should be rejected based on recent failed decompress int recent_failures = 0; - for (i = 0; i < decomp->num_failures; i++) + for (i = 0; i < stats.num_decompress_failures; i++) { - if ((realtime - decomp->failure_times[i]) <= sv_net_incoming_decompression_min_failuretime.value) + if ((realtime - stats.decompress_failure_times[i]) <= sv_net_incoming_decompression_min_failuretime.value) recent_failures++; } diff --git a/rehlds/rehlds/rehlds_interfaces_impl.cpp b/rehlds/rehlds/rehlds_interfaces_impl.cpp index fa07ac5..0922bfa 100644 --- a/rehlds/rehlds/rehlds_interfaces_impl.cpp +++ b/rehlds/rehlds/rehlds_interfaces_impl.cpp @@ -530,6 +530,15 @@ netchan_t* EXT_FUNC CNetChan::GetChan() return m_pNetChan; } +void CNetChan::Clear() +{ + for (int i = 0; i < MAX_STREAMS; i++) + { + for (int j = 0; j < NET_DECOMPRESS_MAX_TIMES; j++) + m_FragStats[i].decompress_failure_times[j] = 0; + m_FragStats[i].num_decompress_failures = 0; + } +} int EXT_FUNC CRehldsServerStatic::GetMaxClients() diff --git a/rehlds/rehlds/rehlds_interfaces_impl.h b/rehlds/rehlds/rehlds_interfaces_impl.h index 5cf4dba..7c62547 100644 --- a/rehlds/rehlds/rehlds_interfaces_impl.h +++ b/rehlds/rehlds/rehlds_interfaces_impl.h @@ -30,6 +30,16 @@ #include "rehlds_interfaces.h" #include "server.h" +const int NET_DECOMPRESS_MAX_TIMES = 10; + +struct FragStats_t +{ + float decompress_failure_times[NET_DECOMPRESS_MAX_TIMES]; + + // Count of abnormal fragment decompressions in a time window + int num_decompress_failures; +}; + class CNetChan : public INetChan { private: @@ -38,6 +48,10 @@ private: #ifdef REHLDS_FIXES uint8_t m_messageBuffer[NET_MAX_PAYLOAD]; #endif + + // Stats for decompression of incoming fragments + FragStats_t m_FragStats[MAX_STREAMS]; + public: CNetChan(netchan_t* chan); @@ -46,10 +60,13 @@ public: virtual netchan_t* GetChan(); + void Clear(); + public: #ifdef REHLDS_FIXES uint8_t* GetExtendedMessageBuffer() { return m_messageBuffer; }; #endif + FragStats_t &GetFragStats(int stream) { return m_FragStats[stream]; }; }; @@ -247,6 +264,9 @@ public: uint8_t* GetExtendedMessageBuffer() { return m_NetChan.GetExtendedMessageBuffer(); }; #endif + void NetchanClear() { m_NetChan.Clear(); } + FragStats_t &GetFragStats(int stream) { return m_NetChan.GetFragStats(stream); }; + #ifdef REHLDS_FIXES void SetupLocalGameTime() { m_localGameTimeBase = g_psv.time; } double GetLocalGameTime() const { return g_psv.time - m_localGameTimeBase; }