more of HandleSocketReceiveFromConnectedPlayer
Still missing: ordened and sequenced packets.
This commit is contained in:
parent
267301a7ba
commit
a4a19a8614
50
common.c
50
common.c
|
@ -3,6 +3,45 @@
|
|||
|
||||
#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)
|
||||
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(
|
||||
struct CRaknetTimeNS isbigger,
|
||||
struct CRaknetTimeNS than)
|
||||
|
|
31
common.h
31
common.h
|
@ -6,6 +6,8 @@
|
|||
#define STATIC_ASSERT(E) typedef char __static_assert_[(E)?1:-1]
|
||||
#define EXPECT_SIZE(S,SIZE) STATIC_ASSERT(sizeof(S)==(SIZE))
|
||||
|
||||
#define DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE 0x200
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct PlayerID {
|
||||
int binaryAddress;
|
||||
|
@ -45,15 +47,19 @@ EXPECT_SIZE(struct CRaknetTimeNS, 0x8);
|
|||
|
||||
struct CQueue {
|
||||
void *array;
|
||||
void *head;
|
||||
void *tail;
|
||||
/*index of head element*/
|
||||
int head;
|
||||
/*index of tail element*/
|
||||
int tail;
|
||||
int allocationSize;
|
||||
};
|
||||
EXPECT_SIZE(struct CQueue, 0x10);
|
||||
|
||||
struct CReliabilityLayer {
|
||||
/*000*/ char _pad0[0xC];
|
||||
/**packets ready for handling*/
|
||||
/*00C*/ struct CQueue outputQueue;
|
||||
/**this is acknowlegements to send on next update*/
|
||||
/*01C*/ void *acknowlegements; // DataStructures::RangeList<short>
|
||||
/*020*/ char _pad20[0x20];
|
||||
/*040*/ void *resendList;
|
||||
|
@ -93,7 +99,16 @@ struct CReliabilityLayer {
|
|||
/*3EC*/ char _pad3EC[0x28];
|
||||
/*414*/ int someCounter;
|
||||
/*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;
|
||||
/**
|
||||
Next message number that is needed.
|
||||
*/
|
||||
/*434*/ short receivedPacketsBaseIndex;
|
||||
/*436*/ char resetReceivedPackets;
|
||||
/*437*/ char _pad437[0x11];
|
||||
|
@ -131,6 +146,17 @@ struct CInternalPacket {
|
|||
EXPECT_SIZE(struct CInternalPacket, 0x38);
|
||||
#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 thiscall1(void *address, void *this, 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__dtor(struct CRangeList *this);
|
||||
int __stdcall BPlusTree__IsEmpty(void *this);
|
||||
void RaknetTimeNS_Add(struct CRaknetTimeNS *this, unsigned int value);
|
||||
int RaknetTimeNS_IsBigger(
|
||||
struct CRaknetTimeNS isbigger,
|
||||
struct CRaknetTimeNS than);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "rangelist_deserialize.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
static
|
||||
__declspec(naked)
|
||||
int __stdcall RangeList__Deserialize(
|
||||
struct CRangeList *this,
|
||||
|
|
160
reliability.c
160
reliability.c
|
@ -1,7 +1,7 @@
|
|||
|
||||
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||
|
||||
#define CALL_ORIGINAL
|
||||
//#define CALL_ORIGINAL
|
||||
|
||||
#define RELIABILITY_PRINT
|
||||
|
||||
|
@ -51,13 +51,163 @@ void SendAckForPacket(
|
|||
}
|
||||
|
||||
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 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)
|
||||
|
@ -274,7 +424,7 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
|
|||
this, &bitStream, timeNS))
|
||||
{
|
||||
returnValue = 1;
|
||||
HandlePacket(this, packet);
|
||||
HandlePacket(this, packet, timeNS);
|
||||
}
|
||||
|
||||
this->receivePacketCount++;
|
||||
|
|
Loading…
Reference in New Issue
Block a user