/* vim: set filetype=c ts=8 noexpandtab: */ #define CALL_ORIGINAL #define RELIABILITY_PRINT #ifdef RELIABILITY_PRINT #define dprintf(X,...) printf(X,__VA_ARGS__) #else #define dprintf(X,...) #endif #include "common.h" #include "bitstream.h" #include "rakpeer.h" #include "reliability.h" #include "rangelist_deserialize.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 } } /*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 */ static void UpdateThreadedMemory(struct CReliabilityLayer *this) { if (this->freeThreadedMemoryOnNextUpdate) { this->freeThreadedMemoryOnNextUpdate = 0; } } static void AddBitsReceivedStatistic(struct CReliabilityLayer *this, int bits) { unsigned int loValue; loValue = this->statistics_bitsReceivedLo32; this->statistics_bitsReceivedLo32 += bits; if (this->statistics_bitsReceivedLo32 < loValue) { this->statistics_bitsReceivedHi32++; } } #ifdef CALL_ORIGINAL __declspec(naked) #endif int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer( struct CReliabilityLayer *this, char *buffer, int length, struct PlayerID playerId, void *messageHandlerList, int MTUSize, int *ptrOutIsPacketFlood) { #ifdef CALL_ORIGINAL _asm { pop eax pop ecx push eax mov eax, 0x45F7E0 jmp eax } #else struct CInternalPacket *packet; struct CBitStream bitStream; 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); // connection request, ignore return 1; } UpdateThreadedMemory(this); AddBitsReceivedStatistic(this, length * 8); BitStream__ctor(&bitStream, buffer, length, 0); RakNet__GetTimeNS(&timeNS); wereAcksHandled = 0; BitStream__Read(&bitStream, &hasAcks); if (hasAcks) { dprintf("has acks\n"); wereAcksHandled = HandleAcks(this, &bitStream, timeNS); } returnValue = wereAcksHandled; while (packet = ReliabilityLayer__CreateInternalPacketFromBitStream( this, &bitStream, timeNS)) { returnValue = 1; HandlePacket(this, packet); } this->receivePacketCount++; BitStream__dtor(&bitStream); dprintf("HandleSocketReceiveFromConnectedPlayerEnd\n"); return returnValue; #endif }