2021-12-25 22:36:38 +01:00
|
|
|
//=============================================================================//
|
|
|
|
//
|
|
|
|
// Purpose: Netchannel system utilities
|
|
|
|
//
|
|
|
|
//=============================================================================//
|
|
|
|
|
|
|
|
#include "core/stdafx.h"
|
2023-05-16 00:44:59 +02:00
|
|
|
#include "tier0/frametask.h"
|
2022-04-09 16:16:40 +02:00
|
|
|
#include "tier1/cvar.h"
|
2023-05-16 00:44:59 +02:00
|
|
|
#include "vpc/keyvalues.h"
|
|
|
|
#include "common/callback.h"
|
2022-04-06 00:49:17 +02:00
|
|
|
#include "engine/net.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
#include "engine/net_chan.h"
|
2022-09-18 23:19:50 +02:00
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
#include "engine/server/server.h"
|
|
|
|
#include "engine/client/client.h"
|
|
|
|
#include "server/vengineserver_impl.h"
|
|
|
|
#endif // !CLIENT_DLL
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
|
2023-06-22 00:33:00 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the netchannel network loss
|
|
|
|
// Output : float
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float CNetChan::GetNetworkLoss() const
|
|
|
|
{
|
2023-08-18 02:33:41 +02:00
|
|
|
int64_t totalupdates = this->m_DataFlow[FLOW_INCOMING].totalupdates;
|
|
|
|
if (!totalupdates && !this->m_nSequencesSkipped_MAYBE)
|
2023-06-22 00:33:00 +02:00
|
|
|
return 0.0f;
|
|
|
|
|
2023-08-20 13:50:59 +02:00
|
|
|
float lossRate = (float)(totalupdates + m_nSequencesSkipped_MAYBE);
|
2023-08-18 02:33:41 +02:00
|
|
|
if (totalupdates + m_nSequencesSkipped_MAYBE < 0.0f)
|
2023-08-20 13:50:59 +02:00
|
|
|
lossRate += float(2 ^ 64);
|
2023-06-22 00:33:00 +02:00
|
|
|
|
2023-08-20 13:50:59 +02:00
|
|
|
return m_nSequencesSkipped_MAYBE / lossRate;
|
2023-06-22 00:33:00 +02:00
|
|
|
}
|
|
|
|
|
2022-04-02 02:48:54 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the netchannel sequence number
|
|
|
|
// Input : flow -
|
|
|
|
// Output : int
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int CNetChan::GetSequenceNr(int flow) const
|
|
|
|
{
|
|
|
|
if (flow == FLOW_OUTGOING)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-07-12 17:43:55 +02:00
|
|
|
return m_nOutSequenceNr;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
2022-04-02 02:48:54 +02:00
|
|
|
else if (flow == FLOW_INCOMING)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-07-12 17:43:55 +02:00
|
|
|
return m_nInSequenceNr;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2022-04-02 02:48:54 +02:00
|
|
|
return NULL;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2022-04-02 02:48:54 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the netchannel connect time
|
|
|
|
// Output : double
|
|
|
|
//-----------------------------------------------------------------------------
|
2023-02-15 20:49:14 +01:00
|
|
|
double CNetChan::GetTimeConnected(void) const
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-02-15 20:49:14 +01:00
|
|
|
double t = *g_pNetTime - connect_time;
|
|
|
|
return (t > 0.0) ? t : 0.0;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2023-08-18 12:47:16 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: flows a new packet
|
|
|
|
// Input : *pChan -
|
|
|
|
// outSeqNr -
|
|
|
|
// acknr -
|
|
|
|
// inSeqNr -
|
|
|
|
// nChoked -
|
|
|
|
// nDropped -
|
|
|
|
// nSize -
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CNetChan::_FlowNewPacket(CNetChan* pChan, int flow, int outSeqNr, int inSeqNr, int nChoked, int nDropped, int nSize)
|
|
|
|
{
|
2023-09-16 22:03:39 +02:00
|
|
|
float netTime; // xmm4_8 (was double)
|
2023-08-18 12:47:16 +02:00
|
|
|
int v8; // r13d
|
|
|
|
int v9; // r14d
|
|
|
|
int v12; // r12d
|
|
|
|
int currentindex; // eax
|
2023-08-18 21:24:35 +02:00
|
|
|
int nextIndex; // r15d
|
2023-08-18 12:47:16 +02:00
|
|
|
int v17; // r8d
|
|
|
|
int v18; // ebp
|
|
|
|
unsigned int v19; // eax
|
|
|
|
int v20; // r9 (was char)
|
|
|
|
int v21; // r8d
|
|
|
|
__int64 v22; // r14
|
|
|
|
float time; // xmm0_4
|
|
|
|
__int64 v24; // rdx
|
|
|
|
__int64 v25; // rcx
|
|
|
|
__int64 v26; // rdx
|
|
|
|
__int64 v27; // rcx
|
|
|
|
__int64 v28; // rdx
|
|
|
|
__int64 v29; // rcx
|
|
|
|
int v30; // edx
|
|
|
|
int v31; // r8 (was char)
|
|
|
|
float v32; // xmm0_4
|
|
|
|
__int64 v33; // r9
|
|
|
|
__int64 v34; // rax
|
|
|
|
__int64 v35; // rdx
|
|
|
|
int v36; // r8d
|
|
|
|
float v37; // xmm3_4
|
|
|
|
__int64 result; // rax
|
|
|
|
float v39; // xmm1_4
|
|
|
|
float v40; // xmm0_4
|
|
|
|
float v41; // xmm1_4
|
|
|
|
netframe_header_t* v42; // rdx
|
|
|
|
float v43; // xmm0_4
|
|
|
|
float v44; // xmm2_4
|
|
|
|
float v45; // xmm0_4
|
|
|
|
|
2023-09-16 22:03:39 +02:00
|
|
|
netTime = (float)*g_pNetTime;
|
2023-08-18 12:47:16 +02:00
|
|
|
v8 = flow;
|
|
|
|
v9 = inSeqNr;
|
|
|
|
netflow_t* pFlow = &pChan->m_DataFlow[flow];
|
|
|
|
v12 = outSeqNr;
|
|
|
|
|
|
|
|
netframe_header_t* pFrameHeader = nullptr;
|
|
|
|
netframe_t* pFrame = nullptr;
|
|
|
|
|
|
|
|
currentindex = pFlow->currentindex;
|
|
|
|
if (outSeqNr > currentindex)
|
|
|
|
{
|
2023-08-18 21:24:35 +02:00
|
|
|
nextIndex = currentindex + 1;
|
2023-08-18 12:47:16 +02:00
|
|
|
if (currentindex + 1 <= outSeqNr)
|
|
|
|
{
|
2023-08-18 21:24:35 +02:00
|
|
|
// This variable makes sure the loops below do not execute more
|
|
|
|
// than NET_FRAMES_BACKUP times. This has to be done as the
|
|
|
|
// headers and frame arrays in the netflow_t structure is as
|
|
|
|
// large as NET_FRAMES_BACKUP. Any execution past it is futile
|
|
|
|
// and only wastes CPU time. Sending an outSeqNr that is higher
|
|
|
|
// than the current index by something like a million or more will
|
|
|
|
// hang the engine for several milliseconds to several seconds.
|
|
|
|
int numPacketFrames = 0;
|
|
|
|
|
|
|
|
v17 = outSeqNr - nextIndex;
|
|
|
|
|
2023-08-18 12:47:16 +02:00
|
|
|
if (v17 + 1 >= 4)
|
|
|
|
{
|
|
|
|
v18 = nChoked + nDropped;
|
2023-08-18 21:24:35 +02:00
|
|
|
v19 = ((unsigned int)(v12 - nextIndex - 3) >> 2) + 1;
|
|
|
|
v20 = nextIndex + 2;
|
2023-08-18 12:47:16 +02:00
|
|
|
v21 = v17 - 2;
|
|
|
|
v22 = v19;
|
|
|
|
time = (float)*g_pNetTime;
|
2023-08-18 21:24:35 +02:00
|
|
|
nextIndex += 4 * v19;
|
2023-08-18 13:06:00 +02:00
|
|
|
|
2023-08-18 12:47:16 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
v24 = (v20 - 2) & NET_FRAMES_MASK;
|
|
|
|
v25 = v24;
|
|
|
|
pFlow->frame_headers[v25].time = time;
|
|
|
|
pFlow->frame_headers[v25].valid = 0;
|
|
|
|
pFlow->frame_headers[v25].size = 0;
|
|
|
|
pFlow->frame_headers[v25].latency = -1.0;
|
|
|
|
pFlow->frames[v24].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
pFlow->frame_headers[v25].choked = 0;
|
|
|
|
pFlow->frames[v24].dropped = 0;
|
|
|
|
if (v21 + 2 < v18)
|
|
|
|
{
|
|
|
|
if (v21 + 2 >= nChoked)
|
|
|
|
pFlow->frames[v24].dropped = 1;
|
|
|
|
else
|
|
|
|
pFlow->frame_headers[(v20 - 2) & NET_FRAMES_MASK].choked = 1;
|
|
|
|
}
|
|
|
|
v26 = (v20 - 1) & NET_FRAMES_MASK;
|
|
|
|
v27 = v26;
|
|
|
|
pFlow->frame_headers[v27].time = time;
|
|
|
|
pFlow->frame_headers[v27].valid = 0;
|
|
|
|
pFlow->frame_headers[v27].size = 0;
|
|
|
|
pFlow->frame_headers[v27].latency = -1.0;
|
|
|
|
pFlow->frames[v26].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
pFlow->frame_headers[v27].choked = 0;
|
|
|
|
pFlow->frames[v26].dropped = 0;
|
|
|
|
if (v21 + 1 < v18)
|
|
|
|
{
|
|
|
|
if (v21 + 1 >= nChoked)
|
|
|
|
pFlow->frames[v26].dropped = 1;
|
|
|
|
else
|
|
|
|
pFlow->frame_headers[(v20 - 1) & NET_FRAMES_MASK].choked = 1;
|
|
|
|
}
|
|
|
|
v28 = v20 & NET_FRAMES_MASK;
|
|
|
|
v29 = v28;
|
|
|
|
pFlow->frame_headers[v29].time = time;
|
|
|
|
pFlow->frame_headers[v29].valid = 0;
|
|
|
|
pFlow->frame_headers[v29].size = 0;
|
|
|
|
pFlow->frame_headers[v29].latency = -1.0;
|
|
|
|
pFlow->frames[v28].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
pFlow->frame_headers[v29].choked = 0;
|
|
|
|
pFlow->frames[v28].dropped = 0;
|
|
|
|
if (v21 < v18)
|
|
|
|
{
|
|
|
|
if (v21 >= nChoked)
|
|
|
|
pFlow->frames[v28].dropped = 1;
|
|
|
|
else
|
|
|
|
pFlow->frame_headers[v20 & NET_FRAMES_MASK].choked = 1;
|
|
|
|
}
|
|
|
|
pFrame = &pFlow->frames[(v20 + 1) & NET_FRAMES_MASK];
|
|
|
|
pFrameHeader = &pFlow->frame_headers[(v20 + 1) & NET_FRAMES_MASK];
|
|
|
|
pFrameHeader->time = time;
|
|
|
|
pFrameHeader->valid = 0;
|
|
|
|
pFrameHeader->size = 0;
|
|
|
|
pFrameHeader->latency = -1.0;
|
|
|
|
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
pFrameHeader->choked = 0;
|
|
|
|
pFrame->dropped = 0;
|
|
|
|
if (v21 - 1 < v18)
|
|
|
|
{
|
|
|
|
if (v21 - 1 >= nChoked)
|
|
|
|
pFrame->dropped = 1;
|
|
|
|
else
|
|
|
|
pFrameHeader->choked = 1;
|
|
|
|
}
|
2023-08-18 21:24:35 +02:00
|
|
|
|
|
|
|
// Incremented by four since this loop does four frames
|
|
|
|
// per iteration.
|
|
|
|
numPacketFrames += 4;
|
2023-08-18 12:47:16 +02:00
|
|
|
v21 -= 4;
|
|
|
|
v20 += 4;
|
|
|
|
--v22;
|
2023-08-18 13:06:00 +02:00
|
|
|
} while (v22 && numPacketFrames < NET_FRAMES_BACKUP);
|
2023-08-18 12:47:16 +02:00
|
|
|
v12 = outSeqNr;
|
|
|
|
v8 = flow;
|
|
|
|
v9 = inSeqNr;
|
|
|
|
}
|
2023-08-18 21:24:35 +02:00
|
|
|
|
|
|
|
// Check if we did not reach NET_FRAMES_BACKUP, else we will
|
|
|
|
// execute the 129'th iteration as well. Also check if the next
|
|
|
|
// index doesn't exceed the outSeqNr.
|
|
|
|
if (numPacketFrames < NET_FRAMES_BACKUP && nextIndex <= v12)
|
2023-08-18 12:47:16 +02:00
|
|
|
{
|
2023-08-18 21:24:35 +02:00
|
|
|
v30 = v12 - nextIndex;
|
|
|
|
v31 = nextIndex;
|
|
|
|
v33 = v12 - nextIndex + 1;
|
2023-08-18 12:47:16 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
pFrame = &pFlow->frames[v31 & NET_FRAMES_MASK];
|
|
|
|
pFrameHeader = &pFlow->frame_headers[v31 & NET_FRAMES_MASK];
|
2023-09-16 22:03:39 +02:00
|
|
|
v32 = netTime;
|
2023-08-18 12:47:16 +02:00
|
|
|
pFrameHeader->time = v32;
|
|
|
|
pFrameHeader->valid = 0;
|
|
|
|
pFrameHeader->size = 0;
|
|
|
|
pFrameHeader->latency = -1.0;
|
|
|
|
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
pFrameHeader->choked = 0;
|
|
|
|
pFrame->dropped = 0;
|
|
|
|
if (v30 < nChoked + nDropped)
|
|
|
|
{
|
|
|
|
if (v30 >= nChoked)
|
|
|
|
pFrame->dropped = 1;
|
|
|
|
else
|
|
|
|
pFrameHeader->choked = 1;
|
|
|
|
}
|
|
|
|
--v30;
|
|
|
|
++v31;
|
|
|
|
--v33;
|
2023-08-18 21:24:35 +02:00
|
|
|
++numPacketFrames;
|
|
|
|
} while (v33 && numPacketFrames < NET_FRAMES_BACKUP);
|
2023-08-18 12:47:16 +02:00
|
|
|
v9 = inSeqNr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pFrame->dropped = nDropped;
|
|
|
|
pFrameHeader->choked = (short)nChoked;
|
|
|
|
pFrameHeader->size = nSize;
|
|
|
|
pFrameHeader->valid = 1;
|
|
|
|
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
|
|
|
|
}
|
|
|
|
++pFlow->totalpackets;
|
|
|
|
pFlow->currentindex = v12;
|
|
|
|
v34 = 544i64;
|
|
|
|
|
|
|
|
if (!v8)
|
|
|
|
v34 = 3688i64;
|
|
|
|
|
|
|
|
pFlow->current_frame = pFrame;
|
|
|
|
v35 = 548i64;
|
|
|
|
v36 = *(_DWORD*)(&pChan->m_bProcessingMessages + v34);
|
|
|
|
if (v9 > v36 - NET_FRAMES_BACKUP)
|
|
|
|
{
|
|
|
|
if (!v8)
|
|
|
|
v35 = 3692i64;
|
|
|
|
result = (__int64)pChan + 16 * (v9 & NET_FRAMES_MASK);
|
|
|
|
v42 = (netframe_header_t*)(result + v35);
|
|
|
|
if (v42->valid && v42->latency == -1.0)
|
|
|
|
{
|
|
|
|
v43 = 0.0;
|
2023-09-16 22:03:39 +02:00
|
|
|
v44 = fmax(0.0f, netTime - v42->time);
|
2023-08-18 12:47:16 +02:00
|
|
|
v42->latency = v44;
|
|
|
|
if (v44 >= 0.0)
|
|
|
|
v43 = v44;
|
|
|
|
else
|
|
|
|
v42->latency = 0.0;
|
|
|
|
v45 = v43 + pFlow->latency;
|
|
|
|
++pFlow->totalupdates;
|
|
|
|
pFlow->latency = v45;
|
|
|
|
pFlow->maxlatency = fmaxf(pFlow->maxlatency, v42->latency);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!v8)
|
|
|
|
v35 = 3692i64;
|
|
|
|
|
|
|
|
v37 = *(float*)(&pChan->m_bProcessingMessages + 16 * (v36 & NET_FRAMES_MASK) + v35);
|
|
|
|
result = v35 + 16i64 * (((_BYTE)v36 + 1) & NET_FRAMES_MASK);
|
|
|
|
v39 = v37 - *(float*)(&pChan->m_bProcessingMessages + result);
|
|
|
|
++pFlow->totalupdates;
|
2023-09-16 22:03:39 +02:00
|
|
|
v40 = (float)((float)(v39 / 127.0) * (float)(v36 - v9)) + netTime - v37;
|
2023-08-18 12:47:16 +02:00
|
|
|
v41 = fmaxf(pFlow->maxlatency, v40);
|
|
|
|
pFlow->latency = v40 + pFlow->latency;
|
|
|
|
pFlow->maxlatency = v41;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-16 00:44:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: shutdown netchannel
|
|
|
|
// Input : *this -
|
|
|
|
// *szReason -
|
|
|
|
// bBadRep -
|
|
|
|
// bRemoveNow -
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow)
|
|
|
|
{
|
|
|
|
v_NetChan_Shutdown(pChan, szReason, bBadRep, bRemoveNow);
|
|
|
|
}
|
|
|
|
|
2022-09-18 23:19:50 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: process message
|
|
|
|
// Input : *pChan -
|
|
|
|
// *pMsg -
|
|
|
|
// Output : true on success, false on failure
|
|
|
|
//-----------------------------------------------------------------------------
|
2023-08-21 16:29:28 +02:00
|
|
|
bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pBuf)
|
2022-09-17 23:34:36 +02:00
|
|
|
{
|
2023-09-16 22:03:39 +02:00
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
if (!ThreadInServerFrameThread() || !net_processTimeBudget->GetInt())
|
|
|
|
return pChan->ProcessMessages(pBuf);
|
|
|
|
|
|
|
|
const double flStartTime = Plat_FloatTime();
|
|
|
|
const bool bResult = pChan->ProcessMessages(pBuf);
|
|
|
|
|
|
|
|
if (!pChan->m_MessageHandler) // NetChannel removed?
|
|
|
|
return bResult;
|
|
|
|
|
2023-12-30 02:51:02 +01:00
|
|
|
CClient* const pClient = reinterpret_cast<CClient*>(pChan->m_MessageHandler);
|
|
|
|
CClientExtended* const pExtended = pClient->GetClientExtended();
|
2023-09-16 22:03:39 +02:00
|
|
|
|
2023-12-30 15:05:14 +01:00
|
|
|
// Reset every second.
|
|
|
|
if ((flStartTime - pExtended->GetNetProcessingTimeBase()) > 1.0)
|
2023-09-16 22:03:39 +02:00
|
|
|
{
|
2023-12-30 15:05:14 +01:00
|
|
|
pExtended->SetNetProcessingTimeBase(flStartTime);
|
|
|
|
pExtended->SetNetProcessingTimeMsecs(0.0, 0.0);
|
2023-09-16 22:03:39 +02:00
|
|
|
}
|
|
|
|
|
2023-12-30 15:05:14 +01:00
|
|
|
const double flCurrentTime = Plat_FloatTime();
|
|
|
|
pExtended->SetNetProcessingTimeMsecs(flStartTime, flCurrentTime);
|
|
|
|
|
|
|
|
if (pExtended->GetNetProcessingTimeMsecs() > net_processTimeBudget->GetFloat())
|
2023-09-16 22:03:39 +02:00
|
|
|
{
|
2023-12-30 15:05:14 +01:00
|
|
|
Warning(eDLL_T::SERVER, "Removing netchannel '%s' ('%s' exceeded time budget by '%3.1f'ms!)\n",
|
|
|
|
pChan->GetName(), pChan->GetAddress(), (pExtended->GetNetProcessingTimeMsecs() - net_processTimeBudget->GetFloat()));
|
2023-09-16 22:03:39 +02:00
|
|
|
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "#DISCONNECT_NETCHAN_OVERFLOW");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bResult;
|
|
|
|
#else // !CLIENT_DLL
|
2023-08-28 02:45:37 +02:00
|
|
|
return pChan->ProcessMessages(pBuf);
|
2023-09-16 22:03:39 +02:00
|
|
|
#endif
|
2022-09-17 23:34:36 +02:00
|
|
|
}
|
|
|
|
|
2023-08-21 16:29:28 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: process message
|
|
|
|
// Input : *buf -
|
|
|
|
// Output : true on success, false on failure
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CNetChan::ProcessMessages(bf_read* buf)
|
|
|
|
{
|
|
|
|
m_bStopProcessing = false;
|
2023-10-08 16:37:35 +02:00
|
|
|
//const double flStartTime = Plat_FloatTime();
|
2023-08-28 02:45:37 +02:00
|
|
|
|
2023-08-21 16:29:28 +02:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
int cmd = net_NOP;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (buf->GetNumBitsLeft() < NETMSG_TYPE_BITS)
|
|
|
|
return true; // Reached the end.
|
|
|
|
|
|
|
|
if (!NET_ReadMessageType(&cmd, buf) && buf->m_bOverflow)
|
|
|
|
{
|
|
|
|
Warning(eDLL_T::ENGINE, "%s(%s): Incoming buffer overflow!\n", __FUNCTION__, GetAddress());
|
|
|
|
m_MessageHandler->ConnectionCrashed("Buffer overflow in net message");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd <= net_Disconnect)
|
|
|
|
break; // Either a Disconnect or NOP packet; process it below.
|
|
|
|
|
|
|
|
INetMessage* netMsg = FindMessage(cmd);
|
|
|
|
|
|
|
|
if (!netMsg)
|
|
|
|
{
|
2023-08-21 20:38:07 +02:00
|
|
|
DevWarning(eDLL_T::ENGINE, "%s(%s): Received unknown net message (%i)!\n",
|
|
|
|
__FUNCTION__, GetAddress(), cmd);
|
2023-08-21 16:29:28 +02:00
|
|
|
Assert(0);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!netMsg->ReadFromBuffer(buf))
|
|
|
|
{
|
2023-08-21 20:38:07 +02:00
|
|
|
DevWarning(eDLL_T::ENGINE, "%s(%s): Failed reading message '%s'!\n",
|
|
|
|
__FUNCTION__, GetAddress(), netMsg->GetName());
|
2023-08-21 16:29:28 +02:00
|
|
|
Assert(0);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Netmessage calls the Process function that was registered by
|
|
|
|
// it's MessageHandler.
|
|
|
|
m_bProcessingMessages = true;
|
|
|
|
const bool bRet = netMsg->Process();
|
|
|
|
m_bProcessingMessages = false;
|
|
|
|
|
|
|
|
// This means we were deleted during the processing of that message.
|
|
|
|
if (m_bShouldDelete)
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This means our message buffer was freed or invalidated during
|
|
|
|
// the processing of that message.
|
|
|
|
if (m_bStopProcessing)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!bRet)
|
|
|
|
{
|
2023-08-28 02:45:37 +02:00
|
|
|
DevWarning(eDLL_T::ENGINE, "%s(%s): Failed processing message '%s'!\n",
|
2023-08-21 20:38:07 +02:00
|
|
|
__FUNCTION__, GetAddress(), netMsg->GetName());
|
2023-08-21 16:29:28 +02:00
|
|
|
Assert(0);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsOverflowed())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bProcessingMessages = true;
|
|
|
|
|
|
|
|
if (cmd == net_NOP) // NOP; continue to next packet.
|
|
|
|
{
|
|
|
|
m_bProcessingMessages = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (cmd == net_Disconnect) // Disconnect request.
|
|
|
|
{
|
|
|
|
char reason[1024];
|
|
|
|
buf->ReadString(reason, sizeof(reason), false);
|
|
|
|
|
|
|
|
m_MessageHandler->ConnectionClosing(reason, 1);
|
|
|
|
m_bProcessingMessages = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bProcessingMessages = false;
|
|
|
|
|
|
|
|
if (m_bShouldDelete)
|
|
|
|
delete this;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-03 18:19:28 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: send message
|
|
|
|
// Input : &msg -
|
|
|
|
// bForceReliable -
|
|
|
|
// bVoice -
|
|
|
|
// Output : true on success, false on failure
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CNetChan::SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice)
|
|
|
|
{
|
|
|
|
if (remote_address.GetType() == netadrtype_t::NA_NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bf_write* pStream = &m_StreamUnreliable;
|
|
|
|
|
|
|
|
if (msg.IsReliable() || bForceReliable)
|
|
|
|
pStream = &m_StreamReliable;
|
|
|
|
|
|
|
|
if (bVoice)
|
|
|
|
pStream = &m_StreamVoice;
|
|
|
|
|
|
|
|
if (pStream != &m_StreamUnreliable ||
|
|
|
|
pStream->GetNumBytesLeft() >= NET_UNRELIABLE_STREAM_MINSIZE)
|
|
|
|
{
|
2023-08-28 02:45:37 +02:00
|
|
|
AcquireSRWLockExclusive(&m_Lock);
|
2023-06-03 18:19:28 +02:00
|
|
|
|
|
|
|
pStream->WriteUBitLong(msg.GetType(), NETMSG_TYPE_BITS);
|
|
|
|
if (!pStream->IsOverflowed())
|
|
|
|
msg.WriteToBuffer(pStream);
|
|
|
|
|
2023-08-28 02:45:37 +02:00
|
|
|
ReleaseSRWLockExclusive(&m_Lock);
|
2023-06-03 18:19:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-08-21 16:29:28 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: finds a registered net message by type
|
|
|
|
// Input : type -
|
|
|
|
// Output : net message pointer on success, NULL otherwise
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
INetMessage* CNetChan::FindMessage(int type)
|
|
|
|
{
|
|
|
|
int numtypes = m_NetMessages.Count();
|
|
|
|
|
|
|
|
for (int i = 0; i < numtypes; i++)
|
|
|
|
{
|
|
|
|
if (m_NetMessages[i]->GetType() == type)
|
|
|
|
return m_NetMessages[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: registers a net message
|
|
|
|
// Input : *msg
|
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CNetChan::RegisterMessage(INetMessage* msg)
|
|
|
|
{
|
|
|
|
Assert(msg);
|
|
|
|
|
|
|
|
if (FindMessage(msg->GetType()))
|
|
|
|
{
|
|
|
|
Assert(0); // Duplicate registration!
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_NetMessages.AddToTail(msg);
|
|
|
|
msg->SetNetChannel(this);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: free's the receive data fragment list
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CNetChan::FreeReceiveList()
|
|
|
|
{
|
|
|
|
m_ReceiveList.blockSize = NULL;
|
|
|
|
m_ReceiveList.transferSize = NULL;
|
|
|
|
if (m_ReceiveList.buffer)
|
|
|
|
{
|
|
|
|
delete m_ReceiveList.buffer;
|
|
|
|
m_ReceiveList.buffer = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:15:01 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: check if there is still data in the reliable waiting buffers
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CNetChan::HasPendingReliableData(void)
|
|
|
|
{
|
|
|
|
return (m_StreamReliable.GetNumBitsWritten() > 0)
|
|
|
|
|| (m_WaitingList.Count() > 0);
|
|
|
|
}
|
|
|
|
|
2022-09-17 23:34:36 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-11-26 13:21:20 +01:00
|
|
|
void VNetChan::Detour(const bool bAttach) const
|
2022-09-17 23:34:36 +02:00
|
|
|
{
|
2023-11-26 13:21:20 +01:00
|
|
|
DetourSetup(&v_NetChan_Shutdown, &CNetChan::_Shutdown, bAttach);
|
|
|
|
DetourSetup(&v_NetChan_FlowNewPacket, &CNetChan::_FlowNewPacket, bAttach);
|
|
|
|
DetourSetup(&v_NetChan_ProcessMessages, &CNetChan::_ProcessMessages, bAttach);
|
2022-09-18 23:19:50 +02:00
|
|
|
}
|