more of HandleSocketReceiveFromConnectedPlayer

Still missing: ordened and sequenced packets.
This commit is contained in:
yugecin 2020-04-05 18:45:47 +02:00
parent 267301a7ba
commit a4a19a8614
No known key found for this signature in database
GPG Key ID: BB3591E3D68964DE
4 changed files with 234 additions and 8 deletions

View File

@ -3,6 +3,45 @@
#include "common.h" #include "common.h"
__declspec(naked)
void * __stdcall Queue_AtPosition_QWORD(struct CQueue *queue, int position)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45B690
jmp eax
}
}
__declspec(naked)
void __stdcall Queue_Push_QWORD(struct CQueue *queue, void *value)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45B5B0
jmp eax
}
}
/**
@param value a POINTER to the value (so for a queue of pointers, a **value)
*/
__declspec(naked)
void __stdcall Queue_Push_DWORD(struct CQueue *queue, void *value)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x450FA0
jmp eax
}
}
__declspec(naked) __declspec(naked)
void * __stdcall thiscall0(void *address, void *this) void * __stdcall thiscall0(void *address, void *this)
{ {
@ -100,6 +139,17 @@ int __stdcall BPlusTree__IsEmpty(void *this)
} }
} }
void RaknetTimeNS_Add(struct CRaknetTimeNS *this, unsigned int value)
{
unsigned int oldLo;
oldLo = this->lo32;
this->lo32 += value;
if (this->lo32 < oldLo) {
this->hi32++;
}
}
int RaknetTimeNS_IsBigger( int RaknetTimeNS_IsBigger(
struct CRaknetTimeNS isbigger, struct CRaknetTimeNS isbigger,
struct CRaknetTimeNS than) struct CRaknetTimeNS than)

View File

@ -6,6 +6,8 @@
#define STATIC_ASSERT(E) typedef char __static_assert_[(E)?1:-1] #define STATIC_ASSERT(E) typedef char __static_assert_[(E)?1:-1]
#define EXPECT_SIZE(S,SIZE) STATIC_ASSERT(sizeof(S)==(SIZE)) #define EXPECT_SIZE(S,SIZE) STATIC_ASSERT(sizeof(S)==(SIZE))
#define DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE 0x200
#pragma pack(push, 1) #pragma pack(push, 1)
struct PlayerID { struct PlayerID {
int binaryAddress; int binaryAddress;
@ -45,15 +47,19 @@ EXPECT_SIZE(struct CRaknetTimeNS, 0x8);
struct CQueue { struct CQueue {
void *array; void *array;
void *head; /*index of head element*/
void *tail; int head;
/*index of tail element*/
int tail;
int allocationSize; int allocationSize;
}; };
EXPECT_SIZE(struct CQueue, 0x10); EXPECT_SIZE(struct CQueue, 0x10);
struct CReliabilityLayer { struct CReliabilityLayer {
/*000*/ char _pad0[0xC]; /*000*/ char _pad0[0xC];
/**packets ready for handling*/
/*00C*/ struct CQueue outputQueue; /*00C*/ struct CQueue outputQueue;
/**this is acknowlegements to send on next update*/
/*01C*/ void *acknowlegements; // DataStructures::RangeList<short> /*01C*/ void *acknowlegements; // DataStructures::RangeList<short>
/*020*/ char _pad20[0x20]; /*020*/ char _pad20[0x20];
/*040*/ void *resendList; /*040*/ void *resendList;
@ -93,7 +99,16 @@ struct CReliabilityLayer {
/*3EC*/ char _pad3EC[0x28]; /*3EC*/ char _pad3EC[0x28];
/*414*/ int someCounter; /*414*/ int someCounter;
/*418*/ char _pad418[0xC]; /*418*/ char _pad418[0xC];
/**
Queue that stores received packets with a higher message number than the first
next packet that we are supposed to receive. 0 values means the packet with that
number (the index == messagenumber) has been received, non-0 values are the
timeNS when this packet hole should be expired (removed).
*/
/*424*/ struct CQueue hasReceivedPacketQueue; /*424*/ struct CQueue hasReceivedPacketQueue;
/**
Next message number that is needed.
*/
/*434*/ short receivedPacketsBaseIndex; /*434*/ short receivedPacketsBaseIndex;
/*436*/ char resetReceivedPackets; /*436*/ char resetReceivedPackets;
/*437*/ char _pad437[0x11]; /*437*/ char _pad437[0x11];
@ -131,6 +146,17 @@ struct CInternalPacket {
EXPECT_SIZE(struct CInternalPacket, 0x38); EXPECT_SIZE(struct CInternalPacket, 0x38);
#pragma pack(pop) #pragma pack(pop)
#define QUEUE_SIZE(X) \
((X.tail > X.head) ? \
(X.tail - X.head) : (X.allocationSize - X.head + X.tail))
#define QUEUE_POP_IGNOREVALUE(X) \
(X.head = (X.head+1 == X.allocationSize) ? 0 : (X.head+1))
void * __stdcall Queue_AtPosition_QWORD(struct CQueue *queue, int position);
void __stdcall Queue_Push_QWORD(struct CQueue *queue, void *value);
void __stdcall Queue_Push_DWORD(struct CQueue *queue, void *value);
void * __stdcall thiscall0(void *address, void *this); void * __stdcall thiscall0(void *address, void *this);
void * __stdcall thiscall1(void *address, void *this, int); void * __stdcall thiscall1(void *address, void *this, int);
void * __stdcall thiscall2(void *address, void *this, int, int); void * __stdcall thiscall2(void *address, void *this, int, int);
@ -139,6 +165,7 @@ void * __stdcall thiscall4(void *address, void *this, int, int, int, int);
void __stdcall RangeList__ctor(struct CRangeList *this); void __stdcall RangeList__ctor(struct CRangeList *this);
void __stdcall RangeList__dtor(struct CRangeList *this); void __stdcall RangeList__dtor(struct CRangeList *this);
int __stdcall BPlusTree__IsEmpty(void *this); int __stdcall BPlusTree__IsEmpty(void *this);
void RaknetTimeNS_Add(struct CRaknetTimeNS *this, unsigned int value);
int RaknetTimeNS_IsBigger( int RaknetTimeNS_IsBigger(
struct CRaknetTimeNS isbigger, struct CRaknetTimeNS isbigger,
struct CRaknetTimeNS than); struct CRaknetTimeNS than);

View File

@ -5,7 +5,6 @@
#include "rangelist_deserialize.h" #include "rangelist_deserialize.h"
#include "bitstream.h" #include "bitstream.h"
static
__declspec(naked) __declspec(naked)
int __stdcall RangeList__Deserialize( int __stdcall RangeList__Deserialize(
struct CRangeList *this, struct CRangeList *this,

View File

@ -1,7 +1,7 @@
/* vim: set filetype=c ts=8 noexpandtab: */ /* vim: set filetype=c ts=8 noexpandtab: */
#define CALL_ORIGINAL //#define CALL_ORIGINAL
#define RELIABILITY_PRINT #define RELIABILITY_PRINT
@ -51,13 +51,163 @@ void SendAckForPacket(
} }
static static
void HandlePacket( void ResetReceivedPackets(struct CReliabilityLayer *this)
{
if (!this->resetReceivedPackets) {
return;
}
thiscall1((void*) 0x45B770, &this->hasReceivedPacketQueue,
DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE);
}
/**
@return 0 if packet should be discarded
*/
static
int HandlePacketHole(
struct CReliabilityLayer *this,
int holeSize,
struct CRaknetTimeNS time)
{
struct CQueue *queueptr;
struct CRaknetTimeNS *timeAt, timeTmp;
#define queue this->hasReceivedPacketQueue
queueptr = &this->hasReceivedPacketQueue;
if (holeSize == 0) {
if (QUEUE_SIZE(queue)) {
QUEUE_POP_IGNOREVALUE(queue);
}
this->receivedPacketsBaseIndex++;
return 1;
}
if (holeSize > 0x8000) {
/*? underflow apparently*/
this->statistics_duplicateMessagesReceived++;
return 0;
}
if (holeSize < QUEUE_SIZE(queue)) {
timeAt = Queue_AtPosition_QWORD(queueptr, holeSize);
if (timeAt->lo32 == 0 && timeAt->hi32 == 0) {
/*was already received, so duplicate packet*/
this->statistics_duplicateMessagesReceived++;
return 0;
}
/*it was a hole that has just been filled*/
timeAt->lo32 = timeAt->hi32 = 0;
return 1;
}
/*add to queue, with holes in between*/
while (holeSize > QUEUE_SIZE(queue)) {
timeTmp = time;
RaknetTimeNS_Add(&timeTmp, this->timeoutTimeMS * 1000);
Queue_Push_QWORD(queueptr, &time);
}
timeTmp.lo32 = timeTmp.hi32 = 0;
Queue_Push_QWORD(queueptr, &timeTmp);
return 1;
}
static
void RemovePacketHolesNotReceivedInTime(
struct CReliabilityLayer *this,
struct CRaknetTimeNS time)
{
struct CQueue *queueptr;
struct CRaknetTimeNS *expireTime;
#define queue this->hasReceivedPacketQueue
queueptr = &this->hasReceivedPacketQueue;
while (QUEUE_SIZE(queue)) {
expireTime = Queue_AtPosition_QWORD(queueptr, queue.head);
if (!RaknetTimeNS_IsBigger(time, *expireTime)) {
return;
}
QUEUE_POP_IGNOREVALUE(queue);
this->receivedPacketsBaseIndex++;
}
}
static
void CompressMessageHoleQueue(struct CReliabilityLayer *this)
{
#define queue this->hasReceivedPacketQueue
if (queue.allocationSize <= DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE) {
return;
}
if (QUEUE_SIZE(queue) * 3 <= queue.allocationSize) {
return;
}
/*Queue::Compress*/
thiscall0((void*) 0x45B6C0, &this->hasReceivedPacketQueue);
}
static
int HandleSequencedPacket(
struct CReliabilityLayer *this, struct CReliabilityLayer *this,
struct CInternalPacket *packet) struct CInternalPacket *packet)
{ {
SendAckForPacket(this, packet); if (packet->packetReliability != RELIABLE_SEQUENCED ||
packet->packetReliability != UNRELIABLE_SEQUENCED)
{
return 0;
}
return 1;
}
// here lol @45FC87 static
int HandleOrdenedPacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet)
{
if (packet->packetReliability != RELIABLE_ORDENED) {
return 0;
}
return 1;
}
static
void HandlePacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet,
struct CRaknetTimeNS time)
{
short holes;
SendAckForPacket(this, packet);
ResetReceivedPackets(this);
holes = packet->messageNumber - this->receivedPacketsBaseIndex;
if (!HandlePacketHole(this, holes, time)) {
return;
}
RemovePacketHolesNotReceivedInTime(this, time);
this->statistics_messagesReceived++;
CompressMessageHoleQueue(this);
/*split packets are dropped, skipping 0x45FECE*/
if (HandleSequencedPacket(this, packet)) {
return;
}
if (HandleOrdenedPacket(this, packet)) {
return;
}
Queue_Push_DWORD(&this->outputQueue, &packet);
} }
__declspec(naked) __declspec(naked)
@ -274,7 +424,7 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
this, &bitStream, timeNS)) this, &bitStream, timeNS))
{ {
returnValue = 1; returnValue = 1;
HandlePacket(this, packet); HandlePacket(this, packet, timeNS);
} }
this->receivePacketCount++; this->receivePacketCount++;