From 6f436ead4d542c2483ed6656df1e4273b36f996f Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 5 Apr 2020 00:47:06 +0200 Subject: [PATCH] slightly more of HandleSocketReceiveFromConnectedPlayer --- common.c | 50 +++++++++++ common.h | 46 ++++++++-- datastructures.c | 28 ------ reliability.c | 224 +++++++++++++++++++++++++++++++++++++++++++++-- samp-re.vcproj | 4 +- 5 files changed, 306 insertions(+), 46 deletions(-) create mode 100644 common.c delete mode 100644 datastructures.c diff --git a/common.c b/common.c new file mode 100644 index 0000000..ead1ea6 --- /dev/null +++ b/common.c @@ -0,0 +1,50 @@ + +/* vim: set filetype=c ts=8 noexpandtab: */ + +#include "common.h" + +__declspec(naked) +void __stdcall RangeList__ctor(struct CRangeList *this) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45F2D0 + jmp eax + } +} + +__declspec(naked) +void __stdcall RangeList__dtor(struct CRangeList *this) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45F300 + jmp eax + } +} + +__declspec(naked) +int __stdcall BPlusTree__IsEmpty(void *this) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45B570 + jmp eax + } +} + +int RaknetTimeNS_IsBigger( + struct CRaknetTimeNS isbigger, + struct CRaknetTimeNS than) +{ + if (isbigger.hi32 > than.hi32) { + return 1; + } + return isbigger.hi32 == than.hi32 && isbigger.lo32 > than.lo32; +} diff --git a/common.h b/common.h index a305f98..482b682 100644 --- a/common.h +++ b/common.h @@ -22,18 +22,24 @@ struct CList { EXPECT_SIZE(struct CList, 0xC); struct COrdenedList { - struct CList _parent; + struct CList _; }; EXPECT_SIZE(struct COrdenedList, 0xC); struct CRangeList { - struct COrdenedList _parent; + struct COrdenedList _; }; EXPECT_SIZE(struct CRangeList, 0xC); +struct CRangeNode_Short { + short minIndex; + short maxIndex; +}; +EXPECT_SIZE(struct CRangeNode_Short, 0x4); + struct CRaknetTimeNS { - int lo32; - int hi32; + unsigned int lo32; + unsigned int hi32; }; EXPECT_SIZE(struct CRaknetTimeNS, 0x8); @@ -78,7 +84,9 @@ struct CReliabilityLayer { /*3C4*/ char _pad3C4[0x4]; /*3C8*/ unsigned int statistics_bitsReceivedLo32; /*3CC*/ unsigned int statistics_bitsReceivedHi32; -/*3D0*/ char _pad3D0[0x10]; +/*3D0*/ char _pad3D0[0x8]; +/*3D8*/ int statistics_acksReceived; +/*3DC*/ char _pad3DC[0x4]; /*3E0*/ int statistics_messagesReceived; /*3E4*/ char _pad3E4[0x4]; /*3E8*/ int statistics_duplicateMessagesReceived; @@ -90,7 +98,7 @@ struct CReliabilityLayer { /*436*/ char resetReceivedPackets; /*437*/ char _pad437[0x11]; /*448*/ struct CRaknetTimeNS histogramStartTime; -/*450*/ int histogramReceiveMarker; +/*450*/ unsigned int histogramReceiveMarker; /*454*/ char _pad454[0x8]; /*45C*/ int histogramAckCount; /*460*/ char _pad460[0x24]; @@ -103,7 +111,29 @@ struct CReliabilityLayer { /*728*/ void *internalPacketPool; }; EXPECT_SIZE(struct CReliabilityLayer, 0x72C); + +struct CInternalPacket { +/*000*/ short messageNumber; +/*002*/ char _pad2[0x6]; +/*008*/ int packetPriority; +/*00C*/ int packetReliability; +/*010*/ char orderingChannel; +/*011*/ char _pad11[0x1]; +/*012*/ short orderingIndex; +/*014*/ short splitPacketId; +/*016*/ char _pad16[0x6]; +/*01C*/ int splitPacketCount; +/*020*/ struct CRaknetTimeNS creationTime; +/*028*/ struct CRaknetTimeNS nextActionTime; +/*030*/ int numberOfBitsToSend; +/*034*/ char *pData; +}; +EXPECT_SIZE(struct CInternalPacket, 0x38); #pragma pack(pop) -void __stdcall __RangeList__ctor(struct CRangeList *this); -void __stdcall __RangeList__dtor(struct CRangeList *this); +void __stdcall RangeList__ctor(struct CRangeList *this); +void __stdcall RangeList__dtor(struct CRangeList *this); +int __stdcall BPlusTree__IsEmpty(void *this); +int RaknetTimeNS_IsBigger( + struct CRaknetTimeNS isbigger, + struct CRaknetTimeNS than); diff --git a/datastructures.c b/datastructures.c deleted file mode 100644 index 39bafde..0000000 --- a/datastructures.c +++ /dev/null @@ -1,28 +0,0 @@ - -/* vim: set filetype=c ts=8 noexpandtab: */ - -#include "common.h" - -__declspec(naked) -void __stdcall __RangeList__ctor(struct CRangeList *this) -{ - _asm { - pop eax - pop ecx - push eax - mov eax, 0x45F2D0 - jmp eax - } -} - -__declspec(naked) -void __stdcall __RangeList__dtor(struct CRangeList *this) -{ - _asm { - pop eax - pop ecx - push eax - mov eax, 0x45F300 - jmp eax - } -} diff --git a/reliability.c b/reliability.c index a0ec73e..764d99a 100644 --- a/reliability.c +++ b/reliability.c @@ -15,6 +15,201 @@ #include "reliability.h" #include +__declspec(naked) +static +void RangeList_Short__Insert( + void *this, + short value) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45E0C0 + jmp eax + } +} + +static +void SendAckForPacket( + struct CReliabilityLayer *this, + struct CInternalPacket *packet) +{ + if (packet->packetReliability != RELIABLE_SEQUENCED || + packet->packetReliability != RELIABLE_ORDENED || + packet->packetReliability != RELIABLE) + { + return; + } + + this->statistics_acknowlegementsSent++; + /*acknowlegements is probably an inlined struct*/ + RangeList_Short__Insert(&this->acknowlegements, packet->messageNumber); +} + +static +void HandlePacket( + struct CReliabilityLayer *this, + struct CInternalPacket *packet) +{ + SendAckForPacket(this, packet); + + // here lol @45FC87 +} + +__declspec(naked) +static +struct CInternalPacket * +__stdcall ReliabilityLayer__CreateInternalPacketFromBitStream( + struct CReliabilityLayer *this, + struct CBitStream *bitstream, + struct CRaknetTimeNS time) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45C000 + jmp eax + } +} + +static +__declspec(naked) +int __stdcall RangeList__Deserialize( + struct CRangeList *this, + struct CBitStream *bitStream) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45E2D0 + jmp eax + } +} + +/*ReliabilityLayer__RemovePacketFromResendListAndDeleteOlderReliableSequenced*/ +__declspec(naked) +int __stdcall ReliabilityLayer__RemovePacketsConfirmedByAck( + struct CReliabilityLayer *this, + short ackMessageNumber, + struct CRaknetTimeNS time) +{ + _asm { + pop eax + pop ecx + push eax + mov eax, 0x45EC40 + jmp eax + } +} + +static +void UpdateHistogramAckCount( + struct CReliabilityLayer *this, + struct CRaknetTimeNS timeNS, + unsigned int ackedCounter) +{ + if (!RaknetTimeNS_IsBigger(this->histogramStartTime, timeNS)) { + return; + } + + if (ackedCounter == (unsigned int) -1) { + return; + } + + if (ackedCounter != this->histogramReceiveMarker) { + return; + } + + this->histogramAckCount++; +} + +static +void HandleAcksForMessageRange( + struct CReliabilityLayer *this, + short minMessageNumber, + short maxMessageNumber, + struct CRaknetTimeNS timeNS) +{ + unsigned int ackedCounter; + short msgNum; + + /*messageholelimit checked here?*/ + + for (msgNum = minMessageNumber; msgNum < maxMessageNumber; msgNum++) { + ackedCounter = ReliabilityLayer__RemovePacketsConfirmedByAck( + this, + msgNum, + timeNS); + + UpdateHistogramAckCount(this, timeNS, ackedCounter); + + /*resendList is not a pointer but + inlined struct that hasn't been defined yet*/ + if (BPlusTree__IsEmpty(&this->resendList)) { + this->lastAckTime.lo32 = 0; + this->lastAckTime.hi32 = 0; + continue; + } + + this->lastAckTime = timeNS; + } +} + +/** +@return 0 if it did not contain valid acks +*/ +static +int HandleAcks( + struct CReliabilityLayer *this, + struct CBitStream *bitStream, + struct CRaknetTimeNS timeNS) +{ + struct CRangeList incomingAcksList; + struct CRangeNode_Short *ranges; + int amountOfAckRanges, ackRangeIdx; + int containedValidAcks; + short minMsg, maxMsg; + + dprintf("reading ackslist, position is %d\n", bitStream->readOffset); + RangeList__ctor(&incomingAcksList); + if (!RangeList__Deserialize(&incomingAcksList, bitStream)) { + dprintf("could not deserialize ackslist\n"); + RangeList__dtor(&incomingAcksList); + return 0; + } + dprintf("position after reading is %d\n", bitStream->readOffset); + + amountOfAckRanges = incomingAcksList._._.list_size; + if (amountOfAckRanges == 0) { + dprintf("ackslist is empty\n"); + RangeList__dtor(&incomingAcksList); + return 1; + } + + containedValidAcks = 0; + ranges = (struct CRangeNode_Short*) incomingAcksList._._.values; + for (ackRangeIdx = 0; ackRangeIdx < amountOfAckRanges; ackRangeIdx++) { + minMsg = ranges[ackRangeIdx].minIndex; + maxMsg = ranges[ackRangeIdx].maxIndex; + + if (minMsg > maxMsg) { + dprintf("invalid ack range %hd>%hd\n", minMsg, maxMsg); + continue; + } + + containedValidAcks = 1; + HandleAcksForMessageRange(this, minMsg, maxMsg, timeNS); + + /*ackslimit checked here*/ + } + + RangeList__dtor(&incomingAcksList); + return containedValidAcks; +} + /** seems like a nop */ @@ -47,10 +242,13 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer( int MTUSize, int *ptrOutIsPacketFlood) { + struct CInternalPacket *packet; struct CBitStream bitStream; - struct CRaknetTimeNS time; - struct CRangeList incomingAcks; - char hasAcks; + struct CRaknetTimeNS timeNS; + char hasAcks, wereAcksHandled; + int returnValue; + + dprintf("HandleSocketReceiveFromConnectedPlayerStart\n"); if (length == 1 || buffer == NULL) { dprintf("ignoring length %d buffer %p\n", length, buffer); @@ -62,15 +260,25 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer( AddBitsReceivedStatistic(this, length * 8); BitStream__ctor(&bitStream, buffer, length, 0); - RakNet__GetTimeNS(&time); - __RangeList__ctor(&incomingAcks); + RakNet__GetTimeNS(&timeNS); + wereAcksHandled = 0; BitStream__Read(&bitStream, &hasAcks); if (hasAcks) { - dprintf("hasacks\n"); + dprintf("has acks\n"); + wereAcksHandled = HandleAcks(this, &bitStream, timeNS); + } + returnValue = wereAcksHandled; + + while (packet = ReliabilityLayer__CreateInternalPacketFromBitStream( + this, &bitStream, timeNS)) + { + returnValue = 1; + HandlePacket(this, packet); } - __RangeList__dtor(&incomingAcks); + this->receivePacketCount++; BitStream__dtor(&bitStream); - return 0; + dprintf("HandleSocketReceiveFromConnectedPlayerEnd\n"); + return returnValue; } diff --git a/samp-re.vcproj b/samp-re.vcproj index b44414a..15401df 100644 --- a/samp-re.vcproj +++ b/samp-re.vcproj @@ -102,11 +102,11 @@ >