Compare commits
4 Commits
6f436ead4d
...
5be68642d0
Author | SHA1 | Date | |
---|---|---|---|
|
5be68642d0 | ||
|
495fa7d745 | ||
|
a4a19a8614 | ||
|
267301a7ba |
59
bitstream.c
59
bitstream.c
|
@ -4,6 +4,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "bitstream.h"
|
#include "bitstream.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
__declspec(naked)
|
__declspec(naked)
|
||||||
void __stdcall BitStream__ctor(
|
void __stdcall BitStream__ctor(
|
||||||
|
@ -44,3 +45,61 @@ int __stdcall BitStream__Read(struct CBitStream *this, char *out)
|
||||||
jmp eax
|
jmp eax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __stdcall Hooked_BitStream__ReadCompressed(
|
||||||
|
char *out,
|
||||||
|
unsigned char a,
|
||||||
|
unsigned char unsignedData)
|
||||||
|
{
|
||||||
|
struct CBitStream *this;
|
||||||
|
unsigned char tmpa, tmpread;
|
||||||
|
int myReadOffset;
|
||||||
|
|
||||||
|
_asm mov this, ecx
|
||||||
|
|
||||||
|
tmpa = (a >> 3) - 1;
|
||||||
|
if (unsignedData) {
|
||||||
|
unsignedData = 0;
|
||||||
|
a = 0;
|
||||||
|
} else {
|
||||||
|
unsignedData = 0xFF;
|
||||||
|
a = 0xF0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (tmpa > 0) {
|
||||||
|
myReadOffset = this->readOffset + 1;
|
||||||
|
if (myReadOffset > this->numberOfBitsUsed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((0x80 >> this->readOffset) == this->ptrData[myReadOffset]) {
|
||||||
|
this->readOffset = myReadOffset;
|
||||||
|
return (int) thiscall3(
|
||||||
|
(void*) 0x44DA70, this, (int) out, tmpa, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->readOffset = myReadOffset;
|
||||||
|
out[tmpa] = unsignedData;
|
||||||
|
tmpa--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->readOffset + 1 > this->numberOfBitsUsed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thiscall1((void*) 0x44D840, this, (int) &tmpread)) { /*readBit*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += 0; /*? esi + ebx but esi should be always 0?*/
|
||||||
|
if (tmpread) {
|
||||||
|
if (!thiscall3((void*) 0x44DA70, this, (int) out, 4, 1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*out |= a;
|
||||||
|
} else {
|
||||||
|
if (!thiscall3((void*) 0x44DA70, this, (int) out, 8, 1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -21,3 +21,7 @@ void __stdcall BitStream__ctor(
|
||||||
void __stdcall BitStream__dtor();
|
void __stdcall BitStream__dtor();
|
||||||
|
|
||||||
int __stdcall BitStream__Read(struct CBitStream *this, char *out);
|
int __stdcall BitStream__Read(struct CBitStream *this, char *out);
|
||||||
|
int __stdcall Hooked_BitStream__ReadCompressed(
|
||||||
|
char *out,
|
||||||
|
unsigned char,
|
||||||
|
unsigned char);
|
||||||
|
|
120
common.c
120
common.c
|
@ -3,6 +3,115 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
void j__free(void *ptr)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
mov eax, 0x49AAA8
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__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)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
add esp, 0xC
|
||||||
|
mov ecx, [esp-0x4]
|
||||||
|
mov eax, [esp-0x8]
|
||||||
|
push [esp-0xC]
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
void * __stdcall thiscall1(void *address, void *this, int a)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
add esp, 0xC
|
||||||
|
mov ecx, [esp-0x4]
|
||||||
|
mov eax, [esp-0x8]
|
||||||
|
push [esp-0xC]
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
void * __stdcall thiscall2(void *address, void *this, int a, int b)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
add esp, 0xC
|
||||||
|
mov ecx, [esp-0x4]
|
||||||
|
mov eax, [esp-0x8]
|
||||||
|
push [esp-0xC]
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
void * __stdcall thiscall3(void *address, void *this, int a, int b, int c)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
add esp, 0xC
|
||||||
|
mov ecx, [esp-0x4]
|
||||||
|
mov eax, [esp-0x8]
|
||||||
|
push [esp-0xC]
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
void * __stdcall thiscall4(void *address, void *this,
|
||||||
|
int a, int b, int c, int d)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
add esp, 0xC
|
||||||
|
mov ecx, [esp-0x4]
|
||||||
|
mov eax, [esp-0x8]
|
||||||
|
push [esp-0xC]
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__declspec(naked)
|
__declspec(naked)
|
||||||
void __stdcall RangeList__ctor(struct CRangeList *this)
|
void __stdcall RangeList__ctor(struct CRangeList *this)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +148,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)
|
||||||
|
|
52
common.h
52
common.h
|
@ -6,6 +6,9 @@
|
||||||
#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
|
||||||
|
#define NUMBER_OF_ORDERED_STREAMS 0x20
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct PlayerID {
|
struct PlayerID {
|
||||||
int binaryAddress;
|
int binaryAddress;
|
||||||
|
@ -37,6 +40,20 @@ struct CRangeNode_Short {
|
||||||
};
|
};
|
||||||
EXPECT_SIZE(struct CRangeNode_Short, 0x4);
|
EXPECT_SIZE(struct CRangeNode_Short, 0x4);
|
||||||
|
|
||||||
|
struct CListNode_DWORD {
|
||||||
|
void *value;
|
||||||
|
struct CListNode_DWORD *prev;
|
||||||
|
struct CListNode_DWORD *next;
|
||||||
|
};
|
||||||
|
EXPECT_SIZE(struct CListNode_DWORD, 0xC);
|
||||||
|
|
||||||
|
struct CCircularLinkedList {
|
||||||
|
unsigned int list_size;
|
||||||
|
void *root;
|
||||||
|
void *position;
|
||||||
|
};
|
||||||
|
EXPECT_SIZE(struct CCircularLinkedList, 0xC);
|
||||||
|
|
||||||
struct CRaknetTimeNS {
|
struct CRaknetTimeNS {
|
||||||
unsigned int lo32;
|
unsigned int lo32;
|
||||||
unsigned int hi32;
|
unsigned int hi32;
|
||||||
|
@ -45,15 +62,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 +114,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,9 +161,27 @@ 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 j__free(void *ptr);
|
||||||
|
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);
|
||||||
|
void * __stdcall thiscall3(void *address, void *this, int, int, int);
|
||||||
|
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);
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
/* vim: set filetype=c ts=8 noexpandtab: */
|
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "bitstream.h"
|
||||||
#include "rakpeer.h"
|
#include "rakpeer.h"
|
||||||
#include "processnetworkpacket.h"
|
#include "processnetworkpacket.h"
|
||||||
#include "uncompress.h"
|
#include "uncompress.h"
|
||||||
|
#include "rangelist_deserialize.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -24,4 +26,6 @@ void nethandler_init()
|
||||||
simple_redir_call(RP_PARSE_NETWORK_PACKET, ProcessNetworkPacket);
|
simple_redir_call(RP_PARSE_NETWORK_PACKET, ProcessNetworkPacket);
|
||||||
simple_redir_call(RP_PARSE_CONNECTION_REQ,
|
simple_redir_call(RP_PARSE_CONNECTION_REQ,
|
||||||
RakPeer__ParseConnectionRequestPacket);
|
RakPeer__ParseConnectionRequestPacket);
|
||||||
|
//simple_redir_call((void*) 0x45F951, RangeList__Deserialize_hooked);
|
||||||
|
simple_redir_call((void*) 0x45E2EF, Hooked_BitStream__ReadCompressed);
|
||||||
}
|
}
|
||||||
|
|
50
rangelist_deserialize.c
Normal file
50
rangelist_deserialize.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "rangelist_deserialize.h"
|
||||||
|
#include "bitstream.h"
|
||||||
|
|
||||||
|
__declspec(naked)
|
||||||
|
int __stdcall RangeList__Deserialize(
|
||||||
|
struct CRangeList *this,
|
||||||
|
struct CBitStream *bitStream)
|
||||||
|
{
|
||||||
|
_asm {
|
||||||
|
pop eax
|
||||||
|
pop ecx
|
||||||
|
push eax
|
||||||
|
mov eax, 0x45E2D0
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int __stdcall RangeList__Deserialize_hooked(struct CBitStream *bitStream)
|
||||||
|
{
|
||||||
|
struct CRangleList *this;
|
||||||
|
short result;
|
||||||
|
char confusingVar;
|
||||||
|
int value, valueshr3;
|
||||||
|
|
||||||
|
_asm mov this, ecx
|
||||||
|
|
||||||
|
thiscall0((void*) 0x45D820, this);
|
||||||
|
thiscall3((void*) 0x44DB30, bitStream, (int) &result, 0x10, 1);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
confusingVar = *((char*) bitStream); // ??
|
||||||
|
|
||||||
|
if (bitStream->readOffset + 1 <= bitStream->numberOfBitsUsed) {
|
||||||
|
value = (int) bitStream->ptrData;
|
||||||
|
valueshr3 = value >> 3;
|
||||||
|
value &= 0x8000007;
|
||||||
|
if (value & 0x80000000) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
8
rangelist_deserialize.h
Normal file
8
rangelist_deserialize.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||||
|
|
||||||
|
int __stdcall RangeList__Deserialize(
|
||||||
|
struct CRangeList *this,
|
||||||
|
struct CBitStream *bitStream);
|
||||||
|
|
||||||
|
int __stdcall RangeList__Deserialize_hooked(struct CBitStream *bitStream);
|
310
reliability.c
310
reliability.c
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
/* vim: set filetype=c ts=8 noexpandtab: */
|
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||||
|
|
||||||
|
//#define CALL_ORIGINAL
|
||||||
|
|
||||||
#define RELIABILITY_PRINT
|
#define RELIABILITY_PRINT
|
||||||
|
|
||||||
#ifdef RELIABILITY_PRINT
|
#ifdef RELIABILITY_PRINT
|
||||||
|
@ -13,6 +15,7 @@
|
||||||
#include "bitstream.h"
|
#include "bitstream.h"
|
||||||
#include "rakpeer.h"
|
#include "rakpeer.h"
|
||||||
#include "reliability.h"
|
#include "reliability.h"
|
||||||
|
#include "rangelist_deserialize.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
__declspec(naked)
|
__declspec(naked)
|
||||||
|
@ -48,13 +51,261 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("packet hole is %d\n", holeSize);
|
||||||
|
|
||||||
|
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
|
||||||
|
void DiscardPacket(
|
||||||
struct CReliabilityLayer *this,
|
struct CReliabilityLayer *this,
|
||||||
struct CInternalPacket *packet)
|
struct CInternalPacket *packet)
|
||||||
{
|
{
|
||||||
SendAckForPacket(this, packet);
|
j__free(packet->pData);
|
||||||
|
thiscall1((void*) 0x44EBF0, &this->internalPacketPool, (int) packet);
|
||||||
|
}
|
||||||
|
|
||||||
// here lol @45FC87
|
static
|
||||||
|
int HandleSequencedPacket(
|
||||||
|
struct CReliabilityLayer *this,
|
||||||
|
struct CInternalPacket *packet)
|
||||||
|
{
|
||||||
|
char channel;
|
||||||
|
short waitingIndex;
|
||||||
|
short newIndex;
|
||||||
|
|
||||||
|
if (packet->packetReliability != RELIABLE_SEQUENCED ||
|
||||||
|
packet->packetReliability != UNRELIABLE_SEQUENCED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel = packet->orderingChannel;
|
||||||
|
if (channel >= NUMBER_OF_ORDERED_STREAMS) {
|
||||||
|
DiscardPacket(this, packet);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
waitingIndex = this->waitingForSequencedPacketReadIndex[channel];
|
||||||
|
newIndex = packet->orderingIndex;
|
||||||
|
/*isOlderSequencedPacked*/
|
||||||
|
if (thiscall2((void*) 0x45B3D0, this, newIndex, waitingIndex)) {
|
||||||
|
this->statistics_sequencedMessagesOutOfOrder++;
|
||||||
|
DiscardPacket(this, packet);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
this->statistics_sequencedMessagesInOrder++;
|
||||||
|
|
||||||
|
/*ignoring split packet code @0x460098*/
|
||||||
|
|
||||||
|
this->waitingForSequencedPacketReadIndex[channel] = newIndex + 1;
|
||||||
|
Queue_Push_DWORD(&this->outputQueue, &packet);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void OutputNowInOrderPackets(
|
||||||
|
struct CReliabilityLayer *this,
|
||||||
|
struct CCircularLinkedList *orderingList,
|
||||||
|
short *waitingForIndex)
|
||||||
|
{
|
||||||
|
struct CInternalPacket *packet;
|
||||||
|
struct CListNode_DWORD *node, *root;
|
||||||
|
int wasAtLeastOneRemoved;
|
||||||
|
|
||||||
|
wasAtLeastOneRemoved = 1;
|
||||||
|
while (wasAtLeastOneRemoved && orderingList->list_size) {
|
||||||
|
wasAtLeastOneRemoved = 0;
|
||||||
|
root = node = orderingList->position = orderingList->root;
|
||||||
|
do {
|
||||||
|
packet = node->value;
|
||||||
|
if (packet->orderingIndex == *waitingForIndex) {
|
||||||
|
dprintf("popped out of order packet\n");
|
||||||
|
Queue_Push_DWORD(&this->outputQueue, &packet);
|
||||||
|
/*CCircularLinkedList::PopCurrent_DWORD*/
|
||||||
|
thiscall0((void*) 0x44E750, orderingList);
|
||||||
|
*waitingForIndex++;
|
||||||
|
wasAtLeastOneRemoved = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
} while (node != root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int HandleOrdenedPacket(
|
||||||
|
struct CReliabilityLayer *this,
|
||||||
|
struct CInternalPacket *packet)
|
||||||
|
{
|
||||||
|
char channel;
|
||||||
|
short newIndex;
|
||||||
|
short *waitingForIndex;
|
||||||
|
struct CCircularLinkedList *orderingList;
|
||||||
|
|
||||||
|
if (packet->packetReliability != RELIABLE_ORDENED) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel = packet->orderingChannel;
|
||||||
|
if (channel >= NUMBER_OF_ORDERED_STREAMS) {
|
||||||
|
DiscardPacket(this, packet);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newIndex = packet->orderingIndex;
|
||||||
|
waitingForIndex = &this->waitingForOrderedPacketReadIndex[channel];
|
||||||
|
if (newIndex != *waitingForIndex) {
|
||||||
|
/*not yet time to handle this one*/
|
||||||
|
dprintf("out of order packet\n");
|
||||||
|
/*do outOfOrderLimit here*/
|
||||||
|
this->statistics_orderedMessagesOutOfOrder++;
|
||||||
|
/*ReliabilityLayer__AddToOrderingList*/
|
||||||
|
thiscall1((void*) 0x45DEE0, this, (int) packet);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
this->statistics_orderedMessagesInOrder++;
|
||||||
|
|
||||||
|
Queue_Push_DWORD(&this->outputQueue, &packet);
|
||||||
|
orderingList = thiscall1((void*) 0x45C4C0, this, channel);
|
||||||
|
if (orderingList == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
OutputNowInOrderPackets(this, orderingList, waitingForIndex);
|
||||||
|
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)
|
||||||
|
@ -74,21 +325,6 @@ __stdcall ReliabilityLayer__CreateInternalPacketFromBitStream(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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*/
|
/*ReliabilityLayer__RemovePacketFromResendListAndDeleteOlderReliableSequenced*/
|
||||||
__declspec(naked)
|
__declspec(naked)
|
||||||
int __stdcall ReliabilityLayer__RemovePacketsConfirmedByAck(
|
int __stdcall ReliabilityLayer__RemovePacketsConfirmedByAck(
|
||||||
|
@ -138,7 +374,7 @@ void HandleAcksForMessageRange(
|
||||||
|
|
||||||
/*messageholelimit checked here?*/
|
/*messageholelimit checked here?*/
|
||||||
|
|
||||||
for (msgNum = minMessageNumber; msgNum < maxMessageNumber; msgNum++) {
|
for (msgNum = minMessageNumber; msgNum <= maxMessageNumber; msgNum++) {
|
||||||
ackedCounter = ReliabilityLayer__RemovePacketsConfirmedByAck(
|
ackedCounter = ReliabilityLayer__RemovePacketsConfirmedByAck(
|
||||||
this,
|
this,
|
||||||
msgNum,
|
msgNum,
|
||||||
|
@ -170,17 +406,17 @@ int HandleAcks(
|
||||||
struct CRangeList incomingAcksList;
|
struct CRangeList incomingAcksList;
|
||||||
struct CRangeNode_Short *ranges;
|
struct CRangeNode_Short *ranges;
|
||||||
int amountOfAckRanges, ackRangeIdx;
|
int amountOfAckRanges, ackRangeIdx;
|
||||||
int containedValidAcks;
|
int numAcks, pos;
|
||||||
short minMsg, maxMsg;
|
short minMsg, maxMsg;
|
||||||
|
|
||||||
dprintf("reading ackslist, position is %d\n", bitStream->readOffset);
|
pos = bitStream->readOffset;
|
||||||
RangeList__ctor(&incomingAcksList);
|
RangeList__ctor(&incomingAcksList);
|
||||||
if (!RangeList__Deserialize(&incomingAcksList, bitStream)) {
|
if (!RangeList__Deserialize(&incomingAcksList, bitStream)) {
|
||||||
dprintf("could not deserialize ackslist\n");
|
dprintf("could not deserialize ackslist\n");
|
||||||
RangeList__dtor(&incomingAcksList);
|
RangeList__dtor(&incomingAcksList);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dprintf("position after reading is %d\n", bitStream->readOffset);
|
dprintf("read acks from %d to %d\n", pos, bitStream->readOffset);
|
||||||
|
|
||||||
amountOfAckRanges = incomingAcksList._._.list_size;
|
amountOfAckRanges = incomingAcksList._._.list_size;
|
||||||
if (amountOfAckRanges == 0) {
|
if (amountOfAckRanges == 0) {
|
||||||
|
@ -189,7 +425,7 @@ int HandleAcks(
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
containedValidAcks = 0;
|
numAcks = 0;
|
||||||
ranges = (struct CRangeNode_Short*) incomingAcksList._._.values;
|
ranges = (struct CRangeNode_Short*) incomingAcksList._._.values;
|
||||||
for (ackRangeIdx = 0; ackRangeIdx < amountOfAckRanges; ackRangeIdx++) {
|
for (ackRangeIdx = 0; ackRangeIdx < amountOfAckRanges; ackRangeIdx++) {
|
||||||
minMsg = ranges[ackRangeIdx].minIndex;
|
minMsg = ranges[ackRangeIdx].minIndex;
|
||||||
|
@ -200,14 +436,14 @@ int HandleAcks(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
containedValidAcks = 1;
|
numAcks += maxMsg - minMsg + 1;
|
||||||
HandleAcksForMessageRange(this, minMsg, maxMsg, timeNS);
|
HandleAcksForMessageRange(this, minMsg, maxMsg, timeNS);
|
||||||
|
|
||||||
/*ackslimit checked here*/
|
/*ackslimit checked here*/
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeList__dtor(&incomingAcksList);
|
RangeList__dtor(&incomingAcksList);
|
||||||
return containedValidAcks;
|
return numAcks > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,6 +469,9 @@ void AddBitsReceivedStatistic(struct CReliabilityLayer *this, int bits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CALL_ORIGINAL
|
||||||
|
__declspec(naked)
|
||||||
|
#endif
|
||||||
int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
|
int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
|
||||||
struct CReliabilityLayer *this,
|
struct CReliabilityLayer *this,
|
||||||
char *buffer,
|
char *buffer,
|
||||||
|
@ -242,11 +481,21 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
|
||||||
int MTUSize,
|
int MTUSize,
|
||||||
int *ptrOutIsPacketFlood)
|
int *ptrOutIsPacketFlood)
|
||||||
{
|
{
|
||||||
|
#ifdef CALL_ORIGINAL
|
||||||
|
_asm {
|
||||||
|
pop eax
|
||||||
|
pop ecx
|
||||||
|
push eax
|
||||||
|
mov eax, 0x45F7E0
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
#else
|
||||||
struct CInternalPacket *packet;
|
struct CInternalPacket *packet;
|
||||||
struct CBitStream bitStream;
|
struct CBitStream bitStream;
|
||||||
struct CRaknetTimeNS timeNS;
|
struct CRaknetTimeNS timeNS;
|
||||||
char hasAcks, wereAcksHandled;
|
char hasAcks, wereAcksHandled;
|
||||||
int returnValue;
|
int returnValue;
|
||||||
|
int packetCount;
|
||||||
|
|
||||||
dprintf("HandleSocketReceiveFromConnectedPlayerStart\n");
|
dprintf("HandleSocketReceiveFromConnectedPlayerStart\n");
|
||||||
|
|
||||||
|
@ -265,20 +514,23 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
|
||||||
wereAcksHandled = 0;
|
wereAcksHandled = 0;
|
||||||
BitStream__Read(&bitStream, &hasAcks);
|
BitStream__Read(&bitStream, &hasAcks);
|
||||||
if (hasAcks) {
|
if (hasAcks) {
|
||||||
dprintf("has acks\n");
|
|
||||||
wereAcksHandled = HandleAcks(this, &bitStream, timeNS);
|
wereAcksHandled = HandleAcks(this, &bitStream, timeNS);
|
||||||
}
|
}
|
||||||
returnValue = wereAcksHandled;
|
returnValue = wereAcksHandled;
|
||||||
|
|
||||||
|
packetCount = 0;
|
||||||
while (packet = ReliabilityLayer__CreateInternalPacketFromBitStream(
|
while (packet = ReliabilityLayer__CreateInternalPacketFromBitStream(
|
||||||
this, &bitStream, timeNS))
|
this, &bitStream, timeNS))
|
||||||
{
|
{
|
||||||
returnValue = 1;
|
returnValue |= 0x10000000;
|
||||||
HandlePacket(this, packet);
|
packetCount++;
|
||||||
|
HandlePacket(this, packet, timeNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->receivePacketCount++;
|
this->receivePacketCount++;
|
||||||
BitStream__dtor(&bitStream);
|
BitStream__dtor(&bitStream);
|
||||||
dprintf("HandleSocketReceiveFromConnectedPlayerEnd\n");
|
dprintf("HandleSocketReceiveFromConnectedPlayerEnd acks=%d packets=%d\n",
|
||||||
|
returnValue & 0xFFFFFFF, packetCount);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,14 @@
|
||||||
RelativePath=".\rakpeer.h"
|
RelativePath=".\rakpeer.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\rangelist_deserialize.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\rangelist_deserialize.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\reliability.c"
|
RelativePath=".\reliability.c"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
/* vim: set filetype=c ts=8 noexpandtab: */
|
/* vim: set filetype=c ts=8 noexpandtab: */
|
||||||
|
|
||||||
#define COMPRESS_PRINT
|
//#define COMPRESS_PRINT
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "uncompress.h"
|
#include "uncompress.h"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user