mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Engine: cleanup data block sender/receiver and add types
* Move member vars to correct place, to match it with the engine. * Added out-of-band network message ID's for the R5 engine. Also implemented 'ServerDataBlockSender::SendDataBlock()' and 'ClientDataBlockReceiver::AcknowledgeTransmission()'. NOTE that these are currently not tested, and also not in use! The code uses the version stored in the vftable which is what the engine itself provides. These have been implemented for reference only. If they need to be used, they need to be thoroughly tested first!
This commit is contained in:
parent
99af2877a6
commit
74da5c7c20
45
r5dev/common/proto_oob.h
Normal file
45
r5dev/common/proto_oob.h
Normal file
@ -0,0 +1,45 @@
|
||||
//============ Copyright Valve Corporation, All rights reserved. ==============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#if !defined( PROTO_OOB_H )
|
||||
#define PROTO_OOB_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "proto_version.h"
|
||||
|
||||
#define PORT_RCON 37015 // default RCON port, TCP
|
||||
#define PORT_SERVER 37015 // Default server port, UDP/TCP
|
||||
#define PORT_CLIENT 37005 // Default client port, UDP/TCP
|
||||
|
||||
// Out of band message id bytes
|
||||
// Prefixes: S = server, C = client, A = any
|
||||
|
||||
#define C2S_CONNECT 'A' // client requests to connect
|
||||
#define S2C_DISCONNECT 'B' // server requests to disconnect
|
||||
|
||||
#define C2S_CHALLENGE 'H' // + challenge value
|
||||
#define S2C_CHALLENGE 'I' // + challenge value
|
||||
|
||||
#define S2C_CONNACCEPT 'J'
|
||||
#define S2C_CONNREJECT 'K' // special protocol for rejected connections
|
||||
|
||||
// Generic Ping Request
|
||||
#define A2A_PING 'L' // respond with an A2A_ACK
|
||||
#define A2A_ACK 'M' // general acknowledgment without info
|
||||
|
||||
#define S2C_UNKNOWN_UISCRIPT 'N' // TODO: figure out what this does, see [r5apex + 0x288880]
|
||||
|
||||
// Data Block Request
|
||||
#define S2C_DATABLOCK_FRAGMENT 'O' // data block fragment
|
||||
#define C2S_DATABLOCK_ACK 'P' // data block fragment acknowledgment
|
||||
|
||||
// All OOB packet start with this sequence
|
||||
#define CONNECTIONLESS_HEADER 0xFFFFFFFF
|
||||
|
||||
#endif
|
17
r5dev/common/proto_version.h
Normal file
17
r5dev/common/proto_version.h
Normal file
@ -0,0 +1,17 @@
|
||||
//============ Copyright Valve Corporation, All rights reserved. ==============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#if !defined( PROTO_VERSION_H )
|
||||
#define PROTO_VERSION_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// The current network protocol version. Changing this makes clients and servers incompatible
|
||||
#define PROTOCOL_VERSION 529
|
||||
|
||||
#endif
|
@ -136,6 +136,8 @@ add_sources( SOURCE_GROUP "Shared"
|
||||
"shared/base_rcon.h"
|
||||
"shared/shared_rcon.cpp"
|
||||
"shared/shared_rcon.h"
|
||||
"shared/datablock.cpp"
|
||||
"shared/datablock.h"
|
||||
)
|
||||
|
||||
if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" )
|
||||
@ -207,7 +209,6 @@ add_sources( SOURCE_GROUP "Public"
|
||||
"${ENGINE_SOURCE_DIR}/public/dt_send.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/dt_recv.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/datamap.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/idatablock.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/idebugoverlay.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/iengine.h"
|
||||
"${ENGINE_SOURCE_DIR}/public/iserver.h"
|
||||
|
@ -1,60 +1,62 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: client side datablock receiver
|
||||
// Purpose: client side data block receiver
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "engine/client/clientstate.h"
|
||||
#include "datablock_receiver.h"
|
||||
#include "common/proto_oob.h"
|
||||
#include "engine/common.h"
|
||||
#include "engine/host_cmd.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
ClientDataBlockReceiver::~ClientDataBlockReceiver()
|
||||
{
|
||||
ClientDataBlockReceiver__Destructor(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: send an ack back to the server to let them know
|
||||
// we received the datablock
|
||||
// we received the data block
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientDataBlockReceiver::AcknowledgeTransmission()
|
||||
{
|
||||
ClientDataBlockReceiver__AcknowledgeTransmission(this);
|
||||
}
|
||||
const CClientState* const cl = m_pClientState;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: initialize the data block receiver context
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientDataBlockReceiver::StartBlockReceiver(const int transferSize, const double startTime)
|
||||
{
|
||||
m_bStartedRecv = true;
|
||||
m_nTransferSize = transferSize;
|
||||
m_nTotalBlocks = transferSize / MAX_DATABLOCK_FRAGMENT_SIZE + (transferSize % MAX_DATABLOCK_FRAGMENT_SIZE != 0);
|
||||
m_nBlockAckTick = 0;
|
||||
m_flStartTime = startTime;
|
||||
if (!cl)
|
||||
{
|
||||
Assert(0, "ClientDataBlockReceiver::AcknowledgeTransmission() called without a valid client handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(m_BlockStatus, 0, sizeof(m_BlockStatus));
|
||||
}
|
||||
const CNetChan* const chan = cl->m_NetChannel;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reset the data block receiver context
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientDataBlockReceiver::ResetBlockReceiver(const short transferNr)
|
||||
{
|
||||
m_nTransferNr = transferNr;
|
||||
if (!chan)
|
||||
{
|
||||
Assert(0, "ClientDataBlockReceiver::AcknowledgeTransmission() called without a net channel!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_bStartedRecv = false;
|
||||
m_bCompletedRecv = false;
|
||||
char dataBuf[DATABLOCK_FRAGMENT_PACKET_SIZE];
|
||||
bf_write buf(&dataBuf, sizeof(dataBuf));
|
||||
|
||||
m_TransferId = 0;
|
||||
m_nTotalBlocks = 0;
|
||||
m_nBlockAckTick = 0;
|
||||
m_flStartTime = 0.0;
|
||||
buf.WriteLong(CONNECTIONLESS_HEADER);
|
||||
buf.WriteByte(C2S_DATABLOCK_ACK);
|
||||
|
||||
memset(m_BlockStatus, 0, sizeof(m_BlockStatus));
|
||||
buf.WriteShort(m_TransferId);
|
||||
buf.WriteShort(m_nTransferNr);
|
||||
|
||||
for (int i = m_nTotalBlocks; (i--) > 0;)
|
||||
{
|
||||
if (m_BlockStatus[i])
|
||||
{
|
||||
// ack the last blockNr we recv'd and processed
|
||||
buf.WriteShort(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send the data block ack packet
|
||||
v_NET_SendPacket(NULL,
|
||||
chan->GetSocket(),
|
||||
chan->GetRemoteAddress(),
|
||||
buf.GetData(),
|
||||
buf.GetNumBytesWritten(),
|
||||
NULL, false, NULL, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1,37 +1,21 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: client side data block receiver
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef DATABLOCK_RECEIVER_H
|
||||
#define DATABLOCK_RECEIVER_H
|
||||
#include "idatablock.h"
|
||||
#include "engine/shared/datablock.h"
|
||||
|
||||
class CClientState;
|
||||
|
||||
class ClientDataBlockReceiver : public NetDataBlockReceiver
|
||||
{
|
||||
friend class CClientState;
|
||||
public:
|
||||
virtual ~ClientDataBlockReceiver();
|
||||
virtual void AcknowledgeTransmission() override;
|
||||
|
||||
void StartBlockReceiver(const int transferSize, const double startTime);
|
||||
void ResetBlockReceiver(const short transferNr);
|
||||
|
||||
bool ProcessDataBlock(const double startTime, const short transferId, const int transferSize,
|
||||
const short counter, const short currentBlockId, const void* const blockBuffer, const int blockBufferBytes);
|
||||
|
||||
protected:
|
||||
CClientState* m_pClientState;
|
||||
bool m_bStartedRecv;
|
||||
bool m_bCompletedRecv;
|
||||
bool byte12;
|
||||
short m_TransferId;
|
||||
short m_nTransferNr;
|
||||
bool m_bInitialized;
|
||||
int m_nTransferSize;
|
||||
int m_nTotalBlocks;
|
||||
int m_nBlockAckTick;
|
||||
double m_flStartTime;
|
||||
|
||||
bool m_BlockStatus[MAX_DATABLOCK_FRAGMENTS];
|
||||
char* m_pScratchBuffer;
|
||||
};
|
||||
|
||||
struct ClientDataBlockHeader_s
|
||||
@ -41,7 +25,6 @@ struct ClientDataBlockHeader_s
|
||||
};
|
||||
|
||||
// virtual methods
|
||||
inline void*(*ClientDataBlockReceiver__Destructor)(ClientDataBlockReceiver* thisptr);
|
||||
inline void*(*ClientDataBlockReceiver__AcknowledgeTransmission)(ClientDataBlockReceiver* thisptr);
|
||||
|
||||
// non-virtual methods
|
||||
@ -54,16 +37,11 @@ class VClientDataBlockReceiver : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("ClientDataBlockReceiver::~ClientDataBlockReceiver", ClientDataBlockReceiver__Destructor);
|
||||
LogFunAdr("ClientDataBlockReceiver::AcknowledgeTransmission", ClientDataBlockReceiver__AcknowledgeTransmission);
|
||||
LogFunAdr("ClientDataBlockReceiver::ProcessDataBlock", ClientDataBlockReceiver__ProcessDataBlock);
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 8B DA 48 8B F9 E8 ?? ?? ?? ?? F6 C3 01 74"
|
||||
" 0D BA ?? ?? ?? ?? 48 8B CF E8 ?? ?? ?? ?? 48 8B C7 48 8B 5C 24 ?? 48 83 C4 20 5F C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24"
|
||||
" ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8D 05 ?? ?? ?? ?? C6 41 12 00").GetPtr(ClientDataBlockReceiver__Destructor);
|
||||
|
||||
g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 4C 8B 51 08").GetPtr(ClientDataBlockReceiver__AcknowledgeTransmission);
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 0F B7 44 24 ??")
|
||||
|
@ -22,10 +22,16 @@ constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg==";
|
||||
inline void*(*v_NET_Init)(bool bDeveloper);
|
||||
inline void(*v_NET_SetKey)(netkey_t* pKey, const char* szHash);
|
||||
inline void(*v_NET_Config)(void);
|
||||
|
||||
inline int(*v_NET_GetPacket)(int iSocket, uint8_t* pScratch, bool bEncrypted);
|
||||
inline int(*v_NET_SendPacket)(CNetChan* pChan, int iSocket, const netadr_t& toAdr, const uint8_t* pData, unsigned int nLen, void* unused0, bool bCompress, void* unused1, bool bEncrypt);
|
||||
|
||||
inline bool(*v_NET_ReceiveDatagram)(int iSocket, netpacket_s* pInpacket, bool bRaw);
|
||||
inline int(*v_NET_SendDatagram)(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool bEncrypted);
|
||||
|
||||
inline bool(*v_NET_BufferToBufferCompress)(uint8_t* const dest, size_t* const destLen, uint8_t* const source, const size_t sourceLen);
|
||||
inline unsigned int(*v_NET_BufferToBufferDecompress_LZSS)(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize);
|
||||
|
||||
inline void(*v_NET_PrintFunc)(const char* fmt, ...);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -57,10 +63,16 @@ class VNet : public IDetour
|
||||
LogFunAdr("NET_Init", v_NET_Init);
|
||||
LogFunAdr("NET_Config", v_NET_Config);
|
||||
LogFunAdr("NET_SetKey", v_NET_SetKey);
|
||||
|
||||
LogFunAdr("NET_GetPacket", v_NET_GetPacket);
|
||||
LogFunAdr("NET_SendPacket", v_NET_SendPacket);
|
||||
|
||||
LogFunAdr("NET_ReceiveDatagram", v_NET_ReceiveDatagram);
|
||||
LogFunAdr("NET_SendDatagram", v_NET_SendDatagram);
|
||||
|
||||
LogFunAdr("NET_BufferToBufferCompress", v_NET_BufferToBufferCompress);
|
||||
LogFunAdr("NET_BufferToBufferDecompress_LZSS", v_NET_BufferToBufferDecompress_LZSS);
|
||||
|
||||
LogFunAdr("NET_PrintFunc", v_NET_PrintFunc);
|
||||
LogVarAdr("g_NetAdr", g_pNetAdr);
|
||||
LogVarAdr("g_NetKey", g_pNetKey);
|
||||
@ -71,6 +83,11 @@ class VNet : public IDetour
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 ??").GetPtr(v_NET_Init);
|
||||
g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 57 C0").GetPtr(v_NET_Config);
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8").GetPtr(v_NET_SetKey);
|
||||
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 8B C4 44 88 40 18 48 89 50 10 41 55").GetPtr(v_NET_GetPacket);
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 55 57 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 4C 63 F2").GetPtr(v_NET_SendPacket);
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 89 74 24 18 48 89 7C 24 20 55 41 54 41 55 41 56 41 57 48 8D AC 24 50 EB").GetPtr(v_NET_ReceiveDatagram);
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ?? 05 ?? ??").GetPtr(v_NET_SendDatagram);
|
||||
|
||||
|
@ -1,27 +1,60 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: server side datablock sender
|
||||
// Purpose: server side data block sender
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "engine/client/client.h"
|
||||
#include "common/proto_oob.h"
|
||||
#include "datablock_sender.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
ServerDataBlockSender::~ServerDataBlockSender()
|
||||
{
|
||||
ServerDataBlockSender__Destructor(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sends the datablock
|
||||
// Purpose: sends the data block
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerDataBlockSender::SendDataBlock(const short transferId, const int transferSize,
|
||||
const short transferNr, const short blockNr, const uint8_t* const blockData, const int blockSize)
|
||||
{
|
||||
ServerDataBlockSender__SendDataBlock(this, transferId, transferSize,
|
||||
transferNr, blockNr, blockData, blockSize);
|
||||
const CClient* const cl = m_pClient;
|
||||
|
||||
if (!cl)
|
||||
{
|
||||
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid client handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
const CNetChan* const chan = cl->m_NetChannel;
|
||||
|
||||
if (!chan)
|
||||
{
|
||||
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid net channel!");
|
||||
return;
|
||||
}
|
||||
|
||||
char dataBuf[DATABLOCK_FRAGMENT_PACKET_SIZE];
|
||||
bf_write buf(&dataBuf, sizeof(dataBuf));
|
||||
|
||||
// msg data (gets processed on client's out of band packet handler)
|
||||
buf.WriteLong(CONNECTIONLESS_HEADER);
|
||||
buf.WriteByte(S2C_DATABLOCK_FRAGMENT);
|
||||
|
||||
// transfer info
|
||||
buf.WriteByte(transferId);
|
||||
buf.WriteLong(transferSize);
|
||||
buf.WriteByte(transferNr);
|
||||
|
||||
// block info
|
||||
buf.WriteByte(blockNr);
|
||||
buf.WriteLong(blockSize);
|
||||
|
||||
// block data
|
||||
buf.WriteBytes(blockData, blockSize);
|
||||
|
||||
// send the data block packet
|
||||
v_NET_SendPacket(NULL,
|
||||
chan->GetSocket(),
|
||||
chan->GetRemoteAddress(),
|
||||
buf.GetData(),
|
||||
buf.GetNumBytesWritten(),
|
||||
NULL, false, NULL, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -60,72 +93,6 @@ const char* ServerDataBlockSender::GetReceiverName() const
|
||||
return m_pClient->m_szServerName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: initialize the data block sender context
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerDataBlockSender::StartBlockSender(const int transferSize, const bool isMultiplayer, const char* const debugName)
|
||||
{
|
||||
m_bMultiplayer = isMultiplayer;
|
||||
m_nBlockAckTick = 0;
|
||||
m_nTransferSize = transferSize + sizeof(ServerDataBlockHeader_s);
|
||||
|
||||
// calculate the number of data blocks we have, which get sent individually
|
||||
// to the receiver
|
||||
m_nTotalBlocks = m_nTransferSize / MAX_DATABLOCK_FRAGMENT_SIZE + (m_nTransferSize % MAX_DATABLOCK_FRAGMENT_SIZE != 0);
|
||||
|
||||
strncpy(m_szDebugName, debugName, sizeof(m_szDebugName));
|
||||
m_szDebugName[sizeof(m_szDebugName) - 1] = '\0';
|
||||
|
||||
// null status memory
|
||||
memset(m_bBlockAckStatus, 0, sizeof(m_bBlockAckStatus));
|
||||
memset(m_flBlockSendTimes, 0, sizeof(m_flBlockSendTimes));
|
||||
|
||||
m_bInitialized = true;
|
||||
m_bStartedTransfer = false;
|
||||
|
||||
const double currentTime = Plat_FloatTime();
|
||||
|
||||
m_TimeLastSend = currentTime;
|
||||
m_TimeCurrentSend = currentTime;
|
||||
m_TimeFirstSend = currentTime;
|
||||
|
||||
m_nTotalSizeRemaining = 4096;
|
||||
m_nBlockSendsAttempted = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reset the data block sender context
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerDataBlockSender::ResetBlockSender(void)
|
||||
{
|
||||
if (!m_bInitialized)
|
||||
return;
|
||||
|
||||
m_bInitialized = false;
|
||||
m_bStartedTransfer = false;
|
||||
|
||||
m_nTransferId = 0;
|
||||
m_nTransferSize = 0;
|
||||
m_nTotalBlocks = 0;
|
||||
m_nBlockAckTick = 0;
|
||||
|
||||
m_TimeCurrentSend = 0.0;
|
||||
m_TimeFirstSend = 0.0;
|
||||
|
||||
m_nTotalSizeRemaining = 0;
|
||||
|
||||
m_TimeLastSend = 0.0;
|
||||
m_szDebugName[0] = '\0';
|
||||
m_bDumbDataBlockInfo = false;
|
||||
m_nCurrentBlock = -1;
|
||||
m_nBlockSendsAttempted = 0;
|
||||
|
||||
memset(m_bBlockAckStatus, 0, sizeof(m_bBlockAckStatus));
|
||||
memset(m_flBlockSendTimes, 0, sizeof(m_flBlockSendTimes));
|
||||
|
||||
m_nTransferNr++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: write the whole data in the data block scratch buffer
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -172,8 +139,10 @@ void ServerDataBlockSender::WriteDataBlock(const uint8_t* const sourceData, cons
|
||||
memcpy(m_pScratchBuffer + sizeof(ServerDataBlockHeader_s), sourceData, actualDataSize);
|
||||
}
|
||||
|
||||
// create the context
|
||||
StartBlockSender(actualDataSize, isMultiplayer, debugName);
|
||||
// NOTE: we copy data in the scratch buffer with an offset of
|
||||
// sizeof(ServerDataBlockHeader_s), the header gets send up as well so we
|
||||
// have to take this into account !!!
|
||||
StartBlockSender(actualDataSize + sizeof(ServerDataBlockHeader_s), isMultiplayer, debugName);
|
||||
|
||||
ReleaseSRWLockExclusive(&m_Lock);
|
||||
}
|
||||
|
@ -1,83 +1,24 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: server side data block sender
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef DATABLOCK_SENDER_H
|
||||
#define DATABLOCK_SENDER_H
|
||||
#include "idatablock.h"
|
||||
#include "engine/shared/datablock.h"
|
||||
|
||||
class CClient;
|
||||
|
||||
class ServerDataBlockSender : public NetDataBlockSender
|
||||
{
|
||||
friend class CClient;
|
||||
public:
|
||||
virtual ~ServerDataBlockSender() override;
|
||||
virtual void SendDataBlock(const short transferId, const int transferSize, const short transferNr,
|
||||
const short blockNr, const uint8_t* const blockData, const int blockSize) override;
|
||||
|
||||
virtual float GetResendRate() const override;
|
||||
virtual const char* GetReceiverName() const override;
|
||||
|
||||
void StartBlockSender(const int transferSize, const bool isMultiplayer, const char* const debugName);
|
||||
void ResetBlockSender();
|
||||
|
||||
void WriteDataBlock(const uint8_t* const sourceData, const int dataSize, const bool isMultiplayer, const char* const debugName);
|
||||
|
||||
protected:
|
||||
char pad_0008[56];
|
||||
RTL_SRWLOCK m_Lock;
|
||||
char pad_0048[56];
|
||||
|
||||
// the server side client handle that is our 'receiving' end
|
||||
CClient* m_pClient;
|
||||
|
||||
char m_bInitialized;
|
||||
char m_bStartedTransfer;
|
||||
|
||||
char m_bMultiplayer;
|
||||
char field_8B;
|
||||
|
||||
// the current transfer id, and the global transfer count for this
|
||||
// particular client. the transfer nr keeps getting incremented on
|
||||
// each new context setup
|
||||
short m_nTransferId;
|
||||
short m_nTransferNr;
|
||||
|
||||
// the total transfer size for the data, and the number of blocks this data
|
||||
// has been carved up to
|
||||
int m_nTransferSize;
|
||||
int m_nTotalBlocks;
|
||||
|
||||
// last block that has been ack'd, and the current block that is pending to
|
||||
// be sent to the receiver
|
||||
int m_nBlockAckTick;
|
||||
int m_nCurrentBlock;
|
||||
|
||||
// the total number of bytes remaining to be sent, and the number of times
|
||||
// we attempted to send data blocks
|
||||
int m_nTotalSizeRemaining;
|
||||
int m_nBlockSendsAttempted;
|
||||
|
||||
// the resend rate for this connection, which depends of the stability/loss
|
||||
// and other factors computed from the netchan
|
||||
float m_flResendRate;
|
||||
char pad_00AC[4]; // padding, in case we want to stuff our own vars in here
|
||||
|
||||
// times used to determine when a data block has been sent, and how long it
|
||||
// took to get this out and acknowledged
|
||||
double m_TimeCurrentSend;
|
||||
double m_TimeFirstSend;
|
||||
double m_TimeLastSend;
|
||||
|
||||
// the last time we attempted to send this block, this gets updated when
|
||||
// a data block hasn't been acknowledged in time and is being resent
|
||||
double m_flBlockSendTimes[MAX_DATABLOCK_FRAGMENTS];
|
||||
|
||||
// the debug name used when details get dumped to the console
|
||||
char m_szDebugName[MAX_DATABLOCK_DEBUG_NAME];
|
||||
|
||||
// if a data block has been acknowledged by the receiver, we mark that
|
||||
// particular block as acknowledged
|
||||
bool m_bBlockAckStatus[MAX_DATABLOCK_FRAGMENTS];
|
||||
uint8_t* m_pScratchBuffer;
|
||||
bool m_bDumbDataBlockInfo;
|
||||
};
|
||||
|
||||
struct ServerDataBlock
|
||||
@ -93,7 +34,6 @@ struct ServerDataBlockHeader_s
|
||||
bool isCompressed;
|
||||
};
|
||||
|
||||
inline void*(*ServerDataBlockSender__Destructor)(ServerDataBlockSender* thisptr);
|
||||
inline void* (*ServerDataBlockSender__SendDataBlock)(ServerDataBlockSender* thisptr,
|
||||
const short transferId, const int transferSize, const short transferNr,
|
||||
const short blockNr, const uint8_t* const blockData, const int blockSize);
|
||||
@ -103,15 +43,10 @@ class VServerDataBlockSender : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("ServerDataBlockSender::~ServerDataBlockSender", ServerDataBlockSender__Destructor);
|
||||
LogFunAdr("ServerDataBlockSender::SendDataBlock", ServerDataBlockSender__SendDataBlock);
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 8B DA 48 8B F9 E8 ?? ?? ?? ?? F6 C3 01 74"
|
||||
" 0D BA ?? ?? ?? ?? 48 8B CF E8 ?? ?? ?? ?? 48 8B C7 48 8B 5C 24 ?? 48 83 C4 20 5F C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24"
|
||||
" ?? 48 89 74 24 ?? 57 48 83 EC 20 33 F6 66 C7 81 ?? ?? ?? ?? ?? ??").GetPtr(ServerDataBlockSender__Destructor);
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 99 ?? ?? ?? ??").GetPtr(ServerDataBlockSender__SendDataBlock);
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
|
112
r5dev/engine/shared/datablock.cpp
Normal file
112
r5dev/engine/shared/datablock.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: data block sender & receiver
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "datablock.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
NetDataBlockSender::~NetDataBlockSender()
|
||||
{
|
||||
ResetBlockSender();
|
||||
|
||||
delete[] m_pScratchBuffer;
|
||||
m_pScratchBuffer = nullptr;
|
||||
|
||||
m_pClient = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reset the data block sender context
|
||||
//-----------------------------------------------------------------------------
|
||||
void NetDataBlockSender::ResetBlockSender(void)
|
||||
{
|
||||
m_bInitialized = false;
|
||||
m_bStartedTransfer = false;
|
||||
|
||||
m_nTransferId = 0;
|
||||
m_nTransferSize = 0;
|
||||
m_nTotalBlocks = 0;
|
||||
m_nBlockAckTick = 0;
|
||||
|
||||
m_TimeCurrentSend = 0.0;
|
||||
m_TimeFirstSend = 0.0;
|
||||
|
||||
m_nTotalSizeRemaining = 0;
|
||||
|
||||
m_TimeLastSend = 0.0;
|
||||
m_szDebugName[0] = '\0';
|
||||
m_bDumbDataBlockInfo = false;
|
||||
m_nCurrentBlock = DATABLOCK_INVALID_BLOCK_NR;
|
||||
m_nBlockSendsAttempted = 0;
|
||||
|
||||
memset(m_bBlockAckStatus, 0, sizeof(m_bBlockAckStatus));
|
||||
memset(m_flBlockSendTimes, 0, sizeof(m_flBlockSendTimes));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: initialize the data block sender context
|
||||
//-----------------------------------------------------------------------------
|
||||
void NetDataBlockSender::StartBlockSender(const int transferSize, const bool isMultiplayer, const char* const debugName)
|
||||
{
|
||||
m_bMultiplayer = isMultiplayer;
|
||||
m_nBlockAckTick = 0;
|
||||
m_nTransferSize = transferSize;
|
||||
|
||||
// calculate the number of data blocks we have, which get sent individually
|
||||
// to the receiver
|
||||
m_nTotalBlocks = m_nTransferSize / MAX_DATABLOCK_FRAGMENT_SIZE + (m_nTransferSize % MAX_DATABLOCK_FRAGMENT_SIZE != 0);
|
||||
|
||||
strncpy(m_szDebugName, debugName, sizeof(m_szDebugName));
|
||||
m_szDebugName[sizeof(m_szDebugName) - 1] = '\0';
|
||||
|
||||
// null status memory
|
||||
memset(m_bBlockAckStatus, 0, sizeof(m_bBlockAckStatus));
|
||||
memset(m_flBlockSendTimes, 0, sizeof(m_flBlockSendTimes));
|
||||
|
||||
m_bInitialized = true;
|
||||
m_bStartedTransfer = false;
|
||||
|
||||
const double currentTime = Plat_FloatTime();
|
||||
|
||||
m_TimeLastSend = currentTime;
|
||||
m_TimeCurrentSend = currentTime;
|
||||
m_TimeFirstSend = currentTime;
|
||||
|
||||
m_nTotalSizeRemaining = 4096;
|
||||
m_nBlockSendsAttempted = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: initialize the data block receiver context
|
||||
//-----------------------------------------------------------------------------
|
||||
void NetDataBlockReceiver::StartBlockReceiver(const int transferSize, const double startTime)
|
||||
{
|
||||
m_bStartedRecv = true;
|
||||
m_nTransferSize = transferSize;
|
||||
m_nTotalBlocks = transferSize / MAX_DATABLOCK_FRAGMENT_SIZE + (transferSize % MAX_DATABLOCK_FRAGMENT_SIZE != 0);
|
||||
m_nBlockAckTick = 0;
|
||||
m_flStartTime = startTime;
|
||||
|
||||
memset(m_BlockStatus, 0, sizeof(m_BlockStatus));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reset the data block receiver context
|
||||
//-----------------------------------------------------------------------------
|
||||
void NetDataBlockReceiver::ResetBlockReceiver(const short transferNr)
|
||||
{
|
||||
m_nTransferNr = transferNr;
|
||||
|
||||
m_bStartedRecv = false;
|
||||
m_bCompletedRecv = false;
|
||||
|
||||
m_TransferId = 0;
|
||||
m_nTotalBlocks = 0;
|
||||
m_nBlockAckTick = 0;
|
||||
m_flStartTime = 0.0;
|
||||
|
||||
memset(m_BlockStatus, 0, sizeof(m_BlockStatus));
|
||||
}
|
173
r5dev/engine/shared/datablock.h
Normal file
173
r5dev/engine/shared/datablock.h
Normal file
@ -0,0 +1,173 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose: data block sender & receiver
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef IDATABLOCK_H
|
||||
#define IDATABLOCK_H
|
||||
|
||||
// the maximum size of each data block fragment
|
||||
#define MAX_DATABLOCK_FRAGMENT_SIZE 1024
|
||||
|
||||
// the maximum amount of fragments per data block
|
||||
#define MAX_DATABLOCK_FRAGMENTS 768
|
||||
|
||||
#define DATABLOCK_DEBUG_NAME_LEN 64
|
||||
#define DATABLOCK_INVALID_BLOCK_NR -1
|
||||
|
||||
// the maximum size of a data block fragment packet (encoded header + actual data)
|
||||
#define DATABLOCK_FRAGMENT_PACKET_SIZE (MAX_DATABLOCK_FRAGMENT_SIZE + 176)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward decelerations
|
||||
//-----------------------------------------------------------------------------
|
||||
class CClient;
|
||||
class CClientState;
|
||||
|
||||
abstract_class NetDataBlockSender
|
||||
{
|
||||
public:
|
||||
virtual ~NetDataBlockSender();
|
||||
|
||||
|
||||
virtual void SendDataBlock(const short transferId, const int transferSize,
|
||||
const short transferNr, const short blockNr, const uint8_t* const blockData, const int blockSize) = 0;
|
||||
virtual float GetResendRate() const = 0;
|
||||
virtual const char* GetReceiverName() const = 0;
|
||||
|
||||
void StartBlockSender(const int transferSize, const bool isMultiplayer, const char* const debugName);
|
||||
void ResetBlockSender();
|
||||
|
||||
protected:
|
||||
char pad_0008[56];
|
||||
RTL_SRWLOCK m_Lock;
|
||||
char pad_0048[56];
|
||||
|
||||
// the server side client handle that is our 'receiving' end
|
||||
CClient* m_pClient;
|
||||
|
||||
char m_bInitialized;
|
||||
char m_bStartedTransfer;
|
||||
|
||||
char m_bMultiplayer;
|
||||
char field_8B;
|
||||
|
||||
// the current transfer id, and the global transfer count for this
|
||||
// particular client. the transfer nr keeps getting incremented on
|
||||
// each new context setup
|
||||
short m_nTransferId;
|
||||
short m_nTransferNr;
|
||||
|
||||
// the total transfer size for the data, and the number of blocks this data
|
||||
// has been carved up to
|
||||
int m_nTransferSize;
|
||||
int m_nTotalBlocks;
|
||||
|
||||
// last block that has been ack'd, and the current block that is pending to
|
||||
// be sent to the receiver
|
||||
int m_nBlockAckTick;
|
||||
int m_nCurrentBlock;
|
||||
|
||||
// the total number of bytes remaining to be sent, and the number of times
|
||||
// we attempted to send data blocks
|
||||
int m_nTotalSizeRemaining;
|
||||
int m_nBlockSendsAttempted;
|
||||
|
||||
// the resend rate for this connection, which depends of the stability/loss
|
||||
// and other factors computed from the netchan
|
||||
float m_flResendRate;
|
||||
char pad_00AC[4]; // padding, in case we want to stuff our own vars in here
|
||||
|
||||
// times used to determine when a data block has been sent, and how long it
|
||||
// took to get this out and acknowledged
|
||||
double m_TimeCurrentSend;
|
||||
double m_TimeFirstSend;
|
||||
double m_TimeLastSend;
|
||||
|
||||
// the last time we attempted to send this block, this gets updated when
|
||||
// a data block hasn't been acknowledged in time and is being resent
|
||||
double m_flBlockSendTimes[MAX_DATABLOCK_FRAGMENTS];
|
||||
|
||||
// the debug name used when details get dumped to the console
|
||||
char m_szDebugName[DATABLOCK_DEBUG_NAME_LEN];
|
||||
|
||||
// if a data block has been acknowledged by the receiver, we mark that
|
||||
// particular block as acknowledged
|
||||
bool m_bBlockAckStatus[MAX_DATABLOCK_FRAGMENTS];
|
||||
uint8_t* m_pScratchBuffer;
|
||||
bool m_bDumbDataBlockInfo;
|
||||
};
|
||||
|
||||
abstract_class NetDataBlockReceiver
|
||||
{
|
||||
public:
|
||||
virtual ~NetDataBlockReceiver() {};
|
||||
// Called when cvar 'net_debugDataBlockReceiver' is set;
|
||||
// currently a nullsub in the engine.
|
||||
virtual void DebugDataBlockReceiver() {};
|
||||
virtual void AcknowledgeTransmission() = 0;
|
||||
|
||||
void StartBlockReceiver(const int transferSize, const double startTime);
|
||||
void ResetBlockReceiver(const short transferNr);
|
||||
|
||||
protected:
|
||||
// the client side 'client' handle
|
||||
CClientState* m_pClientState;
|
||||
|
||||
// whether the transfer has been started and completed
|
||||
bool m_bStartedRecv;
|
||||
bool m_bCompletedRecv;
|
||||
|
||||
bool byte12;
|
||||
|
||||
// the current transfer id, and the global transfer count for this
|
||||
// particular client. the transfer nr keeps getting incremented on
|
||||
// each new context setup
|
||||
short m_TransferId;
|
||||
short m_nTransferNr;
|
||||
|
||||
bool m_bInitialized;
|
||||
|
||||
// the total transfer size, and the # amount of blocks the data has been
|
||||
// carved into
|
||||
int m_nTransferSize;
|
||||
int m_nTotalBlocks;
|
||||
|
||||
int m_nBlockAckTick;
|
||||
|
||||
// the time the data block receiver was started for this transfer
|
||||
double m_flStartTime;
|
||||
|
||||
// if we successfully processed a data block, we mark it as processed
|
||||
bool m_BlockStatus[MAX_DATABLOCK_FRAGMENTS];
|
||||
char* m_pScratchBuffer;
|
||||
};
|
||||
|
||||
inline void* (*NetDataBlockSender__Destructor)(NetDataBlockSender* thisptr);
|
||||
inline void* (*NetDataBlockReceiver__Destructor)(NetDataBlockReceiver* thisptr);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VNetDataBlock : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("NetDataBlockSender::~NetDataBlockSender", NetDataBlockSender__Destructor);
|
||||
LogFunAdr("NetDataBlockReceiver::~NetDataBlockReceiver", NetDataBlockReceiver__Destructor);
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 8B DA 48 8B F9 E8 ?? ?? ?? ?? F6 C3 01 74"
|
||||
" 0D BA ?? ?? ?? ?? 48 8B CF E8 ?? ?? ?? ?? 48 8B C7 48 8B 5C 24 ?? 48 83 C4 20 5F C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24"
|
||||
" ?? 48 89 74 24 ?? 57 48 83 EC 20 33 F6 66 C7 81 ?? ?? ?? ?? ?? ??").GetPtr(NetDataBlockSender__Destructor);
|
||||
|
||||
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 8B DA 48 8B F9 E8 ?? ?? ?? ?? F6 C3 01 74"
|
||||
" 0D BA ?? ?? ?? ?? 48 8B CF E8 ?? ?? ?? ?? 48 8B C7 48 8B 5C 24 ?? 48 83 C4 20 5F C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24"
|
||||
" ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8D 05 ?? ?? ?? ?? C6 41 12 00").GetPtr(NetDataBlockReceiver__Destructor);
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Detour(const bool bAttach) const { }
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // IDATABLOCK_H
|
@ -1,32 +0,0 @@
|
||||
#ifndef IDATABLOCK_H
|
||||
#define IDATABLOCK_H
|
||||
|
||||
// the maximum size of each data block fragment
|
||||
#define MAX_DATABLOCK_FRAGMENT_SIZE 1024
|
||||
|
||||
// the maximum amount of fragments per data block
|
||||
#define MAX_DATABLOCK_FRAGMENTS 768
|
||||
|
||||
#define MAX_DATABLOCK_DEBUG_NAME 64
|
||||
|
||||
abstract_class NetDataBlockSender
|
||||
{
|
||||
public:
|
||||
virtual ~NetDataBlockSender() {};
|
||||
virtual void SendDataBlock(const short transferId, const int transferSize,
|
||||
const short transferNr, const short blockNr, const uint8_t* const blockData, const int blockSize) = 0;
|
||||
virtual float GetResendRate() const = 0;
|
||||
virtual const char* GetReceiverName() const = 0;
|
||||
};
|
||||
|
||||
abstract_class NetDataBlockReceiver
|
||||
{
|
||||
public:
|
||||
virtual ~NetDataBlockReceiver() {};
|
||||
// Called when cvar 'net_debugDataBlockReceiver' is set;
|
||||
// currently a nullsub in the engine.
|
||||
virtual void DebugDataBlockReceiver() {};
|
||||
virtual void AcknowledgeTransmission() = 0;
|
||||
};
|
||||
|
||||
#endif // IDATABLOCK_H
|
Loading…
x
Reference in New Issue
Block a user