From aaf198773fd8e041b0976cc0682e83f8acf394d0 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Tue, 1 Jul 2025 20:41:31 -0300 Subject: beginning of `query.cc` --- Makefile | 2 +- reference/game.c | 799 --------------------------------------------------- src/communication.cc | 10 +- src/crplayer.cc | 2 - src/query.cc | 382 +++++++++++++++++++++++- src/query.hh | 39 ++- src/stubs.hh | 16 -- 7 files changed, 422 insertions(+), 828 deletions(-) delete mode 100644 src/stubs.hh diff --git a/Makefile b/Makefile index 41c5495..c522f85 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ else CFLAGS += -O2 endif -HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/houses.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/reader.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/threads.hh $(SRCDIR)/writer.hh +HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/houses.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/reader.hh $(SRCDIR)/script.hh $(SRCDIR)/threads.hh $(SRCDIR)/writer.hh $(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/communication.obj $(BUILDDIR)/config.obj $(BUILDDIR)/connections.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crnonpl.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/crypto.obj $(BUILDDIR)/houses.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/reader.obj $(BUILDDIR)/receiving.obj $(BUILDDIR)/script.obj $(BUILDDIR)/sending.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/threads.obj $(BUILDDIR)/time.obj $(BUILDDIR)/utils.obj $(BUILDDIR)/writer.obj @echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^ diff --git a/reference/game.c b/reference/game.c index db75c28..9d2bd20 100644 --- a/reference/game.c +++ b/reference/game.c @@ -1,805 +1,6 @@ // QUERY.CC //============================================================================== -void SetQueryManagerLoginData(int Type,char *Data) - -{ - ApplicationType = Type; - if (Data == (char *)0x0) { - LoginData[0] = '\0'; - } - else { - strncpy(LoginData,Data,0x1e); - } - return; -} - - - -// DWARF original prototype: void TQueryManagerConnection(TQueryManagerConnection * this, int -// QueryBufferSize) - -void __thiscall -TQueryManagerConnection::TQueryManagerConnection(TQueryManagerConnection *this,int QueryBufferSize) - -{ - uint uVar1; - uchar *puVar2; - uint *puVar3; - sockaddr *__addr; - socklen_t in_stack_ffffffe0; - uint local_1c [4]; - - local_1c[3] = 0x4000; - puVar3 = local_1c + 3; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - puVar2 = (uchar *)operator_new__(*puVar3); - this->Buffer = puVar2; - local_1c[2] = 0x4000; - puVar3 = local_1c + 2; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - TReadBuffer::TReadBuffer(&this->ReadBuffer,this->Buffer,*puVar3); - local_1c[1] = 0x4000; - puVar3 = local_1c + 1; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - __addr = (sockaddr *)*puVar3; - puVar2 = this->Buffer; - TWriteBuffer::TWriteBuffer(&this->WriteBuffer,puVar2,(int)__addr); - local_1c[0] = 0x4000; - puVar3 = local_1c; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - uVar1 = *puVar3; - this->Socket = -1; - this->QueryOk = false; - this->BufferSize = uVar1; - connect(this,(int)puVar2,__addr,in_stack_ffffffe0); - return; -} - - - -// DWARF original prototype: void TQueryManagerConnection(TQueryManagerConnection * this, int -// QueryBufferSize) - -void __thiscall -TQueryManagerConnection::TQueryManagerConnection(TQueryManagerConnection *this,int QueryBufferSize) - -{ - uint uVar1; - uchar *puVar2; - uint *puVar3; - sockaddr *__addr; - socklen_t in_stack_ffffffe0; - uint local_1c [4]; - - local_1c[3] = 0x4000; - puVar3 = local_1c + 3; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - puVar2 = (uchar *)operator_new__(*puVar3); - this->Buffer = puVar2; - local_1c[2] = 0x4000; - puVar3 = local_1c + 2; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - TReadBuffer::TReadBuffer(&this->ReadBuffer,this->Buffer,*puVar3); - local_1c[1] = 0x4000; - puVar3 = local_1c + 1; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - __addr = (sockaddr *)*puVar3; - puVar2 = this->Buffer; - TWriteBuffer::TWriteBuffer(&this->WriteBuffer,puVar2,(int)__addr); - local_1c[0] = 0x4000; - puVar3 = local_1c; - if (0x3fff < QueryBufferSize) { - puVar3 = (uint *)&QueryBufferSize; - } - uVar1 = *puVar3; - this->Socket = -1; - this->QueryOk = false; - this->BufferSize = uVar1; - connect(this,(int)puVar2,__addr,in_stack_ffffffe0); - return; -} - - - -// DWARF original prototype: void ~TQueryManagerConnection(TQueryManagerConnection * this, int -// __in_chrg) - -void __thiscall -TQueryManagerConnection::~TQueryManagerConnection(TQueryManagerConnection *this,int __in_chrg) - -{ - int iVar1; - int *piVar2; - - if (-1 < this->Socket) { - iVar1 = close(this->Socket); - if (iVar1 < 0) { - piVar2 = __errno_location(); - error(&DAT_0810dc00,*piVar2); - } - this->Socket = -1; - } - if (this->Buffer == (uchar *)0x0) { - return; - } - operator_delete__(this->Buffer); - return; -} - - - -// DWARF original prototype: void ~TQueryManagerConnection(TQueryManagerConnection * this, int -// __in_chrg) - -void __thiscall -TQueryManagerConnection::~TQueryManagerConnection(TQueryManagerConnection *this,int __in_chrg) - -{ - int iVar1; - int *piVar2; - - if (-1 < this->Socket) { - iVar1 = close(this->Socket); - if (iVar1 < 0) { - piVar2 = __errno_location(); - error(&DAT_0810dc00,*piVar2); - } - this->Socket = -1; - } - if (this->Buffer == (uchar *)0x0) { - return; - } - operator_delete__(this->Buffer); - return; -} - - - -// DWARF original prototype: void connect(TQueryManagerConnection * this) - -int __thiscall -TQueryManagerConnection::connect - (TQueryManagerConnection *this,int __fd,sockaddr *__addr,socklen_t __len) - -{ - ushort uVar1; - int Result; - int iVar2; - int *piVar3; - char *__cp; - TWriteBuffer *this_00; - int Try; - int iVar4; - int iVar5; - hostent *local_858; - hostent *HostEntAddr; - int ErrorCode; - char local_84c [4]; - char Buffer [2048]; - hostent HostEnt; - undefined1 local_2c [4]; - sockaddr_in QueryManagerAddress; - - iVar4 = 0; - if (0 < NumberOfQueryManagers) { - do { - local_2c._0_2_ = 0; - local_2c[2] = '\0'; - local_2c[3] = '\0'; - QueryManagerAddress.sin_family = 0; - QueryManagerAddress.sin_port = 0; - QueryManagerAddress.sin_addr.s_addr = 0; - QueryManagerAddress.sin_zero[0] = '\0'; - QueryManagerAddress.sin_zero[1] = '\0'; - QueryManagerAddress.sin_zero[2] = '\0'; - QueryManagerAddress.sin_zero[3] = '\0'; - QueryManagerAddress._0_4_ = inet_addr(QUERY_MANAGER[iVar4].Host); - if (QueryManagerAddress._0_4_ == 0xffffffff) { - HostEntAddr = (hostent *)0x0; - iVar2 = gethostbyname_r(QUERY_MANAGER[iVar4].Host,(hostent *)(Buffer + 0x7fc), - local_84c,0x800,&local_858,(int *)&HostEntAddr); - if ((iVar2 == 0) && (local_858 != (hostent *)0x0)) { - __cp = inet_ntoa((in_addr)*(in_addr_t *)*local_858->h_addr_list); - QueryManagerAddress._0_4_ = inet_addr(__cp); - goto LAB_080e0505; - } -LAB_080e06c8: - print(); - } - else { -LAB_080e0505: - iVar2 = socket(2,1,0); - this->Socket = iVar2; - if (iVar2 < 0) goto LAB_080e06c8; - uVar1 = (ushort)QUERY_MANAGER[iVar4].Port; - iVar5 = 0x10; - ErrorCode._2_2_ = uVar1 >> 8 | uVar1 << 8; - local_2c._2_2_ = ErrorCode._2_2_; - local_2c._0_2_ = 2; - iVar2 = ::connect(this->Socket,(sockaddr *)local_2c,0x10); - if (iVar2 < 0) { - print(); - } - else { - this_00 = &this->WriteBuffer; - this->QueryOk = true; - (this->WriteBuffer).Position = 0; - // try { // try from 080e0595 to 080e05a9 has its CatchHandler @ 080e0754 - TWriteBuffer::writeWord(this_00,0); - TWriteBuffer::writeByte(this_00,'\0'); - // try { // try from 080e05b8 to 080e05bc has its CatchHandler @ 080e0791 - TWriteBuffer::writeByte(this_00,(uchar)ApplicationType); - // try { // try from 080e05d1 to 080e05d5 has its CatchHandler @ 080e07c1 - TWriteStream::writeString - (&this_00->super_TWriteStream,QUERY_MANAGER[iVar4].Password); - if (ApplicationType == 1) { - // try { // try from 080e069d to 080e06a1 has its CatchHandler @ 080e07f1 - TWriteStream::writeString(&this_00->super_TWriteStream,LoginData); - } - iVar5 = executeQuery(this,0x1e,false); - if (iVar5 == 0) { - return 0; - } - print(); - } - if (-1 < this->Socket) { - iVar2 = close(this->Socket); - if (iVar2 < 0) { - piVar3 = __errno_location(); - error(&DAT_0810dc00,*piVar3,iVar5); - } - this->Socket = -1; - } - } - iVar4 = iVar4 + 1; - } while (iVar4 < NumberOfQueryManagers); - } - print(); - this->Socket = -1; - return (int)this; -} - - - -// DWARF original prototype: void disconnect(TQueryManagerConnection * this) - -void __thiscall TQueryManagerConnection::disconnect(TQueryManagerConnection *this) - -{ - int iVar1; - int *piVar2; - - if (-1 < this->Socket) { - iVar1 = close(this->Socket); - if (iVar1 < 0) { - piVar2 = __errno_location(); - error(&DAT_0810dc00,*piVar2); - } - this->Socket = -1; - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: Chances -// DWARF original prototype: int write(TQueryManagerConnection * this, uchar * Buffer, int Size) - -ssize_t __thiscall -TQueryManagerConnection::write(TQueryManagerConnection *this,int __fd,void *__buf,size_t __n) - -{ - ssize_t sVar1; - int *piVar2; - int nwritten; - int nleft; - void *__n_00; - int local_14; - int Chances; - - local_14 = 0x32; - __n_00 = __buf; - if (0 < (int)__buf) { - do { - sVar1 = ::write(this->Socket,(void *)__fd,(size_t)__n_00); - if (((sVar1 == -1) && (piVar2 = __errno_location(), *piVar2 == 0xb)) && (0 < local_14)) - { - DelayThread(0,100000); - local_14 = local_14 + -1; - } - else { - if (sVar1 < 1) { - return sVar1; - } - __n_00 = (void *)((int)__n_00 - sVar1); - __fd = __fd + sVar1; - } - } while (0 < (int)__n_00); - } - return (int)__buf - (int)__n_00; -} - - - -// DWARF original prototype: int read(TQueryManagerConnection * this, uchar * Buffer, int Size, int -// Timeout) - -ssize_t __thiscall -TQueryManagerConnection::read(TQueryManagerConnection *this,int __fd,void *__buf,size_t __nbytes) - -{ - int iVar1; - ssize_t sVar2; - int *piVar3; - int nread; - int nleft; - void *__nbytes_00; - int local_20; - int Chances; - pollfd ufds; - - local_20 = 0x32; - __nbytes_00 = __buf; - if (0 < (int)__buf) { - do { - Chances = this->Socket; - ufds.fd._0_2_ = 1; - ufds.fd._2_2_ = 0; - iVar1 = poll((pollfd *)&Chances,1,__nbytes * 1000); - if (iVar1 < 1) { - return -2; - } - sVar2 = ::read(this->Socket,(void *)__fd,(size_t)__nbytes_00); - if (sVar2 == 0) break; - if (sVar2 < 0) { - piVar3 = __errno_location(); - if (*piVar3 != 4) { - if (*piVar3 != 0xb) { - return sVar2; - } - if (__nbytes_00 == __buf) { - return sVar2; - } - if (local_20 == 0) { - return sVar2; - } - local_20 = local_20 + -1; - DelayThread(0,100000); - } - } - else { - __nbytes_00 = (void *)((int)__nbytes_00 - sVar2); - __fd = __fd + sVar2; - } - } while (0 < (int)__nbytes_00); - } - return (int)__buf - (int)__nbytes_00; -} - - - -// DWARF original prototype: void prepareQuery(TQueryManagerConnection * this, int QueryType) - -void __thiscall TQueryManagerConnection::prepareQuery(TQueryManagerConnection *this,int QueryType) - -{ - this->QueryOk = true; - (this->WriteBuffer).Position = 0; - // try { // try from 080e0a08 to 080e0a1c has its CatchHandler @ 080e0a27 - TWriteBuffer::writeWord(&this->WriteBuffer,0); - TWriteBuffer::writeByte(&this->WriteBuffer,(uchar)QueryType); - return; -} - - - -// DWARF original prototype: void sendFlag(TQueryManagerConnection * this, bool f) - -void __thiscall TQueryManagerConnection::sendFlag(TQueryManagerConnection *this,bool f) - -{ - TWriteBuffer::writeByte(&this->WriteBuffer,f); - return; -} - - - -// DWARF original prototype: void sendByte(TQueryManagerConnection * this, uchar b) - -void __thiscall TQueryManagerConnection::sendByte(TQueryManagerConnection *this,uchar b) - -{ - // try { // try from 080e0a9d to 080e0aa1 has its CatchHandler @ 080e0ab0 - TWriteBuffer::writeByte(&this->WriteBuffer,b); - return; -} - - - -// DWARF original prototype: void sendWord(TQueryManagerConnection * this, ushort w) - -void __thiscall TQueryManagerConnection::sendWord(TQueryManagerConnection *this,ushort w) - -{ - // try { // try from 080e0b0d to 080e0b11 has its CatchHandler @ 080e0b20 - TWriteBuffer::writeWord(&this->WriteBuffer,w); - return; -} - - - -// DWARF original prototype: void sendQuad(TQueryManagerConnection * this, ulong q) - -void __thiscall TQueryManagerConnection::sendQuad(TQueryManagerConnection *this,ulong q) - -{ - // try { // try from 080e0b7c to 080e0b80 has its CatchHandler @ 080e0b90 - TWriteBuffer::writeQuad(&this->WriteBuffer,q); - return; -} - - - -// DWARF original prototype: void sendString(TQueryManagerConnection * this, char * s) - -void __thiscall TQueryManagerConnection::sendString(TQueryManagerConnection *this,char *s) - -{ - // try { // try from 080e0bec to 080e0bf0 has its CatchHandler @ 080e0c00 - TWriteStream::writeString(&(this->WriteBuffer).super_TWriteStream,s); - return; -} - - - -// DWARF original prototype: void sendBytes(TQueryManagerConnection * this, uchar * Buffer, int -// Count) - -void __thiscall TQueryManagerConnection::sendBytes(TQueryManagerConnection *this) - -{ - uchar *in_stack_00000008; - int in_stack_0000000c; - - // try { // try from 080e0c63 to 080e0c67 has its CatchHandler @ 080e0c72 - TWriteBuffer::writeBytes(&this->WriteBuffer,in_stack_00000008,in_stack_0000000c); - return; -} - - - -// DWARF original prototype: bool getFlag(TQueryManagerConnection * this) - -bool __thiscall TQueryManagerConnection::getFlag(TQueryManagerConnection *this) - -{ - uchar uVar1; - - // try { // try from 080e0cc2 to 080e0cc6 has its CatchHandler @ 080e0cd8 - uVar1 = TReadBuffer::readByte(&this->ReadBuffer); - return uVar1 != '\0'; -} - - - -// DWARF original prototype: uchar getByte(TQueryManagerConnection * this) - -uchar __thiscall TQueryManagerConnection::getByte(TQueryManagerConnection *this) - -{ - uchar uVar1; - - // try { // try from 080e0d22 to 080e0d26 has its CatchHandler @ 080e0d31 - uVar1 = TReadBuffer::readByte(&this->ReadBuffer); - return uVar1; -} - - - -// DWARF original prototype: ushort getWord(TQueryManagerConnection * this) - -ushort __thiscall TQueryManagerConnection::getWord(TQueryManagerConnection *this) - -{ - ushort uVar1; - - // try { // try from 080e0d82 to 080e0d86 has its CatchHandler @ 080e0d91 - uVar1 = TReadBuffer::readWord(&this->ReadBuffer); - return uVar1; -} - - - -// DWARF original prototype: ulong getQuad(TQueryManagerConnection * this) - -ulong __thiscall TQueryManagerConnection::getQuad(TQueryManagerConnection *this) - -{ - ulong uVar1; - - // try { // try from 080e0de2 to 080e0de6 has its CatchHandler @ 080e0df0 - uVar1 = TReadBuffer::readQuad(&this->ReadBuffer); - return uVar1; -} - - - -// DWARF original prototype: void getString(TQueryManagerConnection * this, char * Buffer, int -// MaxLength) - -void __thiscall -TQueryManagerConnection::getString(TQueryManagerConnection *this,char *Buffer,int MaxLength) - -{ - // try { // try from 080e0e53 to 080e0e57 has its CatchHandler @ 080e0e62 - TReadStream::readString(&(this->ReadBuffer).super_TReadStream,Buffer,MaxLength); - return; -} - - - -// DWARF original prototype: void getBytes(TQueryManagerConnection * this, uchar * Buffer, int -// Count) - -void __thiscall TQueryManagerConnection::getBytes(TQueryManagerConnection *this) - -{ - uchar *in_stack_00000008; - int in_stack_0000000c; - - // try { // try from 080e0ec0 to 080e0ec4 has its CatchHandler @ 080e0ed0 - TReadBuffer::readBytes(&this->ReadBuffer,in_stack_00000008,in_stack_0000000c); - return; -} - - - -// WARNING: Variable defined which should be unmapped: Help -// DWARF original prototype: int executeQuery(TQueryManagerConnection * this, int Timeout, bool -// AutoReconnect) - -int __thiscall -TQueryManagerConnection::executeQuery(TQueryManagerConnection *this,int Timeout,bool AutoReconnect) - -{ - byte bVar1; - void *pvVar2; - sockaddr *psVar3; - ssize_t sVar4; - int iVar5; - void *pvVar6; - int Result; - TWriteBuffer *this_00; - int Size; - int DataSize; - sockaddr *__buf; - undefined4 uStackY_40; - char *Text; - uchar *puVar7; - socklen_t in_stack_ffffffd0; - undefined1 auStack_2c [11]; - char local_21; - char *pcStack_20; - bool SecondChance; - char local_19; - byte local_18; - undefined1 local_17 [2]; - bool AutoReconnect_local; - uchar Help2 [4]; - uchar Help [2]; - - this_00 = &this->WriteBuffer; - local_19 = AutoReconnect; - __buf = (sockaddr *)(this->WriteBuffer).Position; - (this->WriteBuffer).Position = 0; - if ((int)__buf < 0xffff) { - // try { // try from 080e1376 to 080e137a has its CatchHandler @ 080e13ed - uStackY_40 = 0x80e137b; - TWriteBuffer::writeWord(this_00,(short)__buf - 2); - } - else { - if (this->BufferSize < (int)(__buf->sa_data + 2)) { - Text = "TQueryManagerConnection::executeQuery: Puffer zu klein.\n"; - goto LAB_080e0f4d; - } - pcStack_20 = __buf[-1].sa_data + 0xc; - uStackY_40 = 0x80e0f86; - memmove(this->Buffer + 6,this->Buffer + 2,(size_t)pcStack_20); - // try { // try from 080e0f91 to 080e0f95 has its CatchHandler @ 080e1380 - uStackY_40 = 0x80e0f96; - TWriteBuffer::writeWord(this_00,0xffff); - // try { // try from 080e0fa0 to 080e0fa4 has its CatchHandler @ 080e13bd - uStackY_40 = 0x80e0fa5; - TWriteBuffer::writeQuad(this_00,(ulong)pcStack_20); - __buf = (sockaddr *)(__buf->sa_data + 2); - } - local_21 = '\x01'; - if (this->QueryOk != false) { - do { - if (this->Socket < 0) { - if (local_19 == '\0') { - return 3; - } - if ((int)__buf < 0x4000) { - iVar5 = -((uint)(__buf->sa_data + 0xd) & 0xfffffff0); - puVar7 = this->Buffer; - *(sockaddr **)(Help2 + iVar5 + -0x20) = __buf; - *(uchar **)(&stack0xffffffc8 + iVar5) = puVar7; - *(undefined1 **)(&stack0xffffffc4 + iVar5) = auStack_2c + iVar5; - *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1335; - memcpy(*(void **)(&stack0xffffffc4 + iVar5),*(void **)(&stack0xffffffc8 + iVar5) - ,*(size_t *)(Help2 + iVar5 + -0x20)); - *(TQueryManagerConnection **)(&stack0xffffffc4 + iVar5) = this; - *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1340; - connect(*(TQueryManagerConnection **)(&stack0xffffffc4 + iVar5), - *(int *)(&stack0xffffffc8 + iVar5),*(sockaddr **)(Help2 + iVar5 + -0x20) - ,*(socklen_t *)(&stack0xffffffd0 + iVar5)); - puVar7 = this->Buffer; - *(undefined1 **)(&stack0xffffffc8 + iVar5) = auStack_2c + iVar5; - *(sockaddr **)(Help2 + iVar5 + -0x20) = __buf; - *(uchar **)(&stack0xffffffc4 + iVar5) = puVar7; - *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1356; - memcpy(*(void **)(&stack0xffffffc4 + iVar5),*(void **)(&stack0xffffffc8 + iVar5) - ,*(size_t *)(Help2 + iVar5 + -0x20)); - } - else { - uStackY_40 = 0x80e0ff6; - pvVar2 = operator_new__((uint)__buf); - puVar7 = this->Buffer; - uStackY_40 = 0x80e100e; - psVar3 = __buf; - memcpy(pvVar2,puVar7,(size_t)__buf); - uStackY_40 = 0x80e1019; - connect(this,(int)puVar7,psVar3,in_stack_ffffffd0); - uStackY_40 = 0x80e102f; - memcpy(this->Buffer,pvVar2,(size_t)__buf); - if (pvVar2 != (void *)0x0) { - uStackY_40 = 0x80e103b; - operator_delete__(pvVar2); - } - } - if (this->Socket < 0) { - return 3; - } - } - uStackY_40 = 0x80e1069; - psVar3 = (sockaddr *)write(this,(int)this->Buffer,__buf,in_stack_ffffffd0); - if (psVar3 == __buf) { - uStackY_40 = 0x80e1092; - in_stack_ffffffd0 = Timeout; - sVar4 = read(this,(int)(Help2 + 2),(void *)0x2,Timeout); - if (sVar4 == 2) { - pvVar2 = (void *)((uint)Help2[3] * 0x100 + (uint)Help2[2]); - if (pvVar2 == (void *)0xffff) { - uStackY_40 = 0x80e1241; - sVar4 = read(this,(int)&local_18,(void *)0x4,Timeout); - if (sVar4 != 4) { - if (this->Socket < 0) { - return 3; - } - uStackY_40 = 0x80e1263; - iVar5 = close(this->Socket); - if (iVar5 < 0) { - uStackY_40 = 0x80e127b; - __errno_location(); - uStackY_40 = 0x80e128d; - error(&DAT_0810dc00); - } - this->Socket = -1; - return 3; - } - pvVar2 = (void *)((uint)local_18 + (uint)_local_17 * 0x100); - } - if ((pvVar2 == (void *)0x0) || (this->BufferSize < (int)pvVar2)) { - if (-1 < this->Socket) { - uStackY_40 = 0x80e114a; - iVar5 = close(this->Socket); - if (iVar5 < 0) { - uStackY_40 = 0x80e115f; - __errno_location(); - uStackY_40 = 0x80e1171; - error(&DAT_0810dc00); - } - this->Socket = -1; - } - uStackY_40 = 0x80e113d; - error(&DAT_0810e120); - return 3; - } - uStackY_40 = 0x80e1190; - pvVar6 = (void *)read(this,(int)this->Buffer,pvVar2,Timeout); - if (pvVar6 == pvVar2) { - (this->ReadBuffer).Size = (int)pvVar6; - (this->ReadBuffer).Position = 0; - // try { // try from 080e11f7 to 080e11fb has its CatchHandler @ 080e1415 - uStackY_40 = 0x80e11fc; - bVar1 = TReadBuffer::readByte(&this->ReadBuffer); - if (bVar1 == 3) { - uStackY_40 = 0x80e121a; - error("TQueryManagerConnection::executeQuery: Anfrage fehlgeschlagen.\n" - ); - return 3; - } - return (uint)bVar1; - } - if (-1 < this->Socket) { - uStackY_40 = 0x80e11bb; - iVar5 = close(this->Socket); - if (iVar5 < 0) { - uStackY_40 = 0x80e11d0; - __errno_location(); - uStackY_40 = 0x80e11e2; - error(&DAT_0810dc00); - } - this->Socket = -1; - } - Text = - "TQueryManagerConnection::executeQuery: Fehler beim Auslesen der Daten.\n"; - goto LAB_080e0f4d; - } - if (-1 < this->Socket) { - uStackY_40 = 0x80e10ce; - iVar5 = close(this->Socket); - if (iVar5 < 0) { - uStackY_40 = 0x80e10e3; - __errno_location(); - uStackY_40 = 0x80e10f5; - error(&DAT_0810dc00); - } - this->Socket = -1; - } - if (sVar4 == -2) { - return 3; - } - if (local_21 == '\0') { - return 3; - } - } - else { - if (-1 < this->Socket) { - uStackY_40 = 0x80e12e8; - iVar5 = close(this->Socket); - if (iVar5 < 0) { - uStackY_40 = 0x80e12fd; - __errno_location(); - uStackY_40 = 0x80e130f; - error(&DAT_0810dc00); - } - this->Socket = -1; - } - if (local_21 == '\0') { - Text = - "TQueryManagerConnection::executeQuery: Fehler beim Abschicken der Anfrage.\n"; - goto LAB_080e0f4d; - } - } - local_21 = '\0'; - } while( true ); - } - Text = "TQueryManagerConnection::executeQuery: Fehler beim Zusammenbauen der Anfrage.\n"; -LAB_080e0f4d: - uStackY_40 = 0x80e0f52; - error(Text); - return 3; -} - - - // DWARF original prototype: int checkAccountPassword(TQueryManagerConnection * this, ulong // AccountID, char * Password, char * IPAddress) diff --git a/src/communication.cc b/src/communication.cc index 99c891a..bb71327 100644 --- a/src/communication.cc +++ b/src/communication.cc @@ -273,11 +273,11 @@ bool WriteToSocket(TConnection *Connection, uint8 *Buffer, int Size){ int BytesToWrite = Size + 2; uint8 *WritePtr = Buffer; while(BytesToWrite > 0){ - int ret = (int)write(Connection->GetSocket(), WritePtr, BytesToWrite); - if(ret > 0){ - BytesToWrite -= ret; - WritePtr += ret; - }else if(ret == 0){ + int BytesWritten = (int)write(Connection->GetSocket(), WritePtr, BytesToWrite); + if(BytesWritten > 0){ + BytesToWrite -= BytesWritten; + WritePtr += BytesWritten; + }else if(BytesWritten == 0){ // TODO(fusion): Can this even happen without an error? error("WriteToSocket: Fehler %d beim Senden an Socket %d.\n", errno, Connection->GetSocket()); diff --git a/src/crplayer.cc b/src/crplayer.cc index a53e676..e5874be 100644 --- a/src/crplayer.cc +++ b/src/crplayer.cc @@ -8,8 +8,6 @@ #include "threads.hh" #include "writer.hh" -#include "stubs.hh" - static Semaphore PlayerMutex(1); static vector PlayerList(0, 100, 10, NULL); static int FirstFreePlayer; diff --git a/src/query.cc b/src/query.cc index 697a3ce..a31b9b0 100644 --- a/src/query.cc +++ b/src/query.cc @@ -1,3 +1,383 @@ #include "query.hh" +#include "config.hh" -// TODO +#include +#include +#include +#include +#include + +static int ApplicationType; +static char LoginData[30]; + +void SetQueryManagerLoginData(int Type, const char *Data){ + ApplicationType = Type; + if(Data != NULL){ + strncpy(LoginData, Data, sizeof(LoginData)); + LoginData[sizeof(LoginData) - 1] = 0; + }else{ + LoginData[0] = 0; + } +} + +// TODO(fusion): An initializer list executes in the same order fields are +// declared. This initialization should work as long as `BufferSize` is the +// first field declared in `TQueryManagerConnection`, which it is. +TQueryManagerConnection::TQueryManagerConnection(int QueryBufferSize) : + BufferSize(std::max(QueryBufferSize, KB(16))), + Buffer(new uint8[this->BufferSize]), + ReadBuffer(this->Buffer, this->BufferSize), + WriteBuffer(this->Buffer, this->BufferSize), + Socket(-1), + QueryOk(false) +{ + this->connect(); +} + +TQueryManagerConnection::~TQueryManagerConnection(void){ + this->disconnect(); + delete[] this->Buffer; +} + +bool ResolveHostNameAddress(const char *HostName, in_addr_t *OutAddr){ + // TODO(fusion): Just use `getaddrinfo`? + int ErrorCode; + hostent HostEnt; + hostent *HostEntResult; + char Buffer[2048]; + int Ret = gethostbyname_r(HostName, &HostEnt, + Buffer, sizeof(Buffer), &HostEntResult, &ErrorCode); + if(Ret != 0 || HostEntResult == NULL){ + return false; + } + + if(OutAddr){ + *OutAddr = ((in_addr_t)HostEntResult->h_addr_list[0][0] << 24) + | ((in_addr_t)HostEntResult->h_addr_list[0][1] << 16) + | ((in_addr_t)HostEntResult->h_addr_list[0][2] << 8) + | ((in_addr_t)HostEntResult->h_addr_list[0][3] << 0); + } + + return true; +} + +void TQueryManagerConnection::connect(void){ + for(int i = 0; i < NumberOfQueryManagers; i += 1){ + in_addr_t Addr = inet_addr(QUERY_MANAGER[i].Host); + if(Addr == 0xFFFFFFFF && !ResolveHostNameAddress(QUERY_MANAGER[i].Host, &Addr)){ + print(2, "TQueryManagerConnection::connect: Kann Rechnernamen nicht auflösen.\n"); + continue; + } + + this->Socket = socket(AF_INET, SOCK_STREAM, 0); + if(this->Socket == -1){ + print(2, "TQueryManagerConnection::connect: Kann Socket nicht öffnen.\n"); + continue; + } + + struct sockaddr_in QueryManagerAddress = {}; + QueryManagerAddress.sin_family = AF_INET; + QueryManagerAddress.sin_port = htons(QUERY_MANAGER[i].Port); + QueryManagerAddress.sin_addr.s_addr = Addr; + if(::connect(this->Socket, (struct sockaddr*)&QueryManagerAddress, sizeof(QueryManagerAddress)) == -1){ + this->disconnect(); + continue; + } + + this->prepareQuery(0); + this->sendByte((uint8)ApplicationType); + this->sendString(QUERY_MANAGER[i].Password); + if(ApplicationType == 1){ + this->sendString(LoginData); + } + + int Ret = this->executeQuery(30, false); + if(Ret != 0){ + print(2, "TQueryManagerConnection::connect: Anmeldung fehlgeschlagen (%d).\n", Ret); + this->disconnect(); + continue; + } + + break; + } + + if(!this->isConnected()){ + print(2, "TQueryManagerConnection::connect: Kein Query-Manager verfügbar.\n"); + } +} + +void TQueryManagerConnection::disconnect(void){ + if(this->Socket != -1){ + if(close(this->Socket) == -1){ + error("TQueryManagerConnection::disconnect: Fehler %d beim Schließen der Socket.\n", errno); + } + this->Socket = -1; + } +} + +int TQueryManagerConnection::write(const uint8 *Buffer, int Size){ + int Attempts = 50; + int BytesToWrite = Size; + const uint8 *WritePtr = Buffer; + while(BytesToWrite > 0){ + int BytesWritten = (int)::write(this->Socket, WritePtr, BytesToWrite); + if(BytesWritten > 0){ + BytesToWrite -= BytesWritten; + WritePtr += BytesWritten; + }else if(BytesWritten == 0){ + break; + }else{ + // TODO(fusion): We don't set the socket as non blocking so I don't + // think we can even get `EAGAIN` here. + if(errno != EAGAIN || Attempts <= 0){ + return -1; + } + + DelayThread(0, 100000); + Attempts -= 1; + } + } + return Size - BytesToWrite; +} + +int TQueryManagerConnection::read(uint8 *Buffer, int Size, int Timeout){ + int Attempts = 50; + int BytesToRead = Size; + uint8 *ReadPtr = Buffer; + while(BytesToRead > 0){ + struct pollfd pollfd = {}; + pollfd.fd = this->Socket; + pollfd.events = POLLIN; + if(poll(&pollfd, 1, Timeout * 1000) != 1){ + return -2; + } + + int BytesRead = ::read(this->Socket, ReadPtr, BytesToRead); + if(BytesRead > 0){ + BytesToRead -= BytesRead; + ReadPtr += BytesRead; + }else if(BytesRead == 0){ + break; + }else if(errno != EINTR){ + if(errno != EAGAIN || BytesToRead == Size || Attempts <= 0){ + return -1; + } + + DelayThread(0, 100000); + Attempts -= 1; + } + } + return Size - BytesToRead; +} + +void TQueryManagerConnection::prepareQuery(int QueryType){ + this->QueryOk = true; + this->WriteBuffer.Position = 0; + + try{ + this->WriteBuffer.writeWord(0); + this->WriteBuffer.writeByte((uint8)QueryType); + }catch(const char *str){ + error("TQueryManagerConnection::prepareQuery: %s.\n", str); + this->QueryOk = false; + } +} + +void TQueryManagerConnection::sendFlag(bool Flag){ + this->sendByte(Flag ? 0x01 : 0x00); +} + +void TQueryManagerConnection::sendByte(uint8 Byte){ + try{ + this->WriteBuffer.writeByte(Byte); + }catch(const char *str){ + error("TQueryManagerConnection::sendByte: %s.\n", str); + this->QueryOk = false; + } +} + +void TQueryManagerConnection::sendWord(uint16 Word){ + try{ + this->WriteBuffer.writeWord(Word); + }catch(const char *str){ + error("TQueryManagerConnection::sendWord: %s.\n", str); + this->QueryOk = false; + } +} + +void TQueryManagerConnection::sendQuad(uint32 Quad){ + try{ + this->WriteBuffer.writeQuad(Quad); + }catch(const char *str){ + error("TQueryManagerConnection::sendQuad: %s.\n", str); + this->QueryOk = false; + } +} + +void TQueryManagerConnection::sendString(const char *String){ + try{ + this->WriteBuffer.writeString(String); + }catch(const char *str){ + error("TQueryManagerConnection::sendString: %s.\n", str); + this->QueryOk = false; + } +} + +void TQueryManagerConnection::sendBytes(const uint8 *Buffer, int Count){ + try{ + this->WriteBuffer.writeBytes(Buffer, Count); + }catch(const char *str){ + error("TQueryManagerConnection::sendBytes: %s.\n", str); + this->QueryOk = false; + } +} + +bool TQueryManagerConnection::getFlag(void){ + return this->getByte() != 0; +} + +uint8 TQueryManagerConnection::getByte(void){ + uint8 Result = 0; + try{ + Result = this->ReadBuffer.readByte(); + }catch(const char *str){ + error("TQueryManagerConnection::getByte: %s.\n", str); + } + return Result; +} + +uint16 TQueryManagerConnection::getWord(void){ + uint16 Result = 0; + try{ + Result = this->ReadBuffer.readWord(); + }catch(const char *str){ + error("TQueryManagerConnection::getWord: %s.\n", str); + } + return Result; +} + +uint32 TQueryManagerConnection::getQuad(void){ + uint32 Result = 0; + try{ + Result = this->ReadBuffer.readQuad(); + }catch(const char *str){ + error("TQueryManagerConnection::getQuad: %s.\n", str); + } + return Result; +} + +void TQueryManagerConnection::getString(char *Buffer, int MaxLength){ + try{ + this->ReadBuffer.readString(Buffer, MaxLength); + }catch(const char *str){ + error("TQueryManagerConnection::getString: %s.\n", str); + if(MaxLength > 0){ + Buffer[0] = 0; + } + } +} + +void TQueryManagerConnection::getBytes(uint8 *Buffer, int Count){ + try{ + this->ReadBuffer.readBytes(Buffer, Count); + }catch(const char *str){ + error("TQueryManagerConnection::getBytes: %s.\n", str); + } +} + +int TQueryManagerConnection::executeQuery(int Timeout, bool AutoReconnect){ + // NOTE(fusion): `prepareQuery` will already leave two extra bytes at the + // beginning of the buffer for writing the request's length. + int PacketSize = this->WriteBuffer.Position; + int PayloadSize = PacketSize - 2; + this->WriteBuffer.Position = 0; + if(PayloadSize < 0xFFFF){ + this->sendWord((uint16)PayloadSize); + }else{ + PacketSize += 4; + if(PacketSize > this->BufferSize){ + error("TQueryManagerConnection::executeQuery: Puffer zu klein.\n"); + return QUERY_FAILED; + } + + memmove(&this->Buffer[6], &this->Buffer[2], PayloadSize); + this->sendWord(0xFFFF); + this->sendQuad((uint32)PayloadSize); + } + + if(!this->QueryOk){ + error("TQueryManagerConnection::executeQuery: Fehler beim Zusammenbauen der Anfrage.\n"); + return QUERY_FAILED; + } + + for(int Attempt = 0; true; Attempt += 1){ + if(!this->isConnected()){ + if(!AutoReconnect){ + return QUERY_FAILED; + } + + // TODO(fusion): There was also a "fast" path that allocated on the + // stack with variable length arrays. It would be a problem to mimic + // that with `alloca` since its memory is only released at the end + // of the function and we're in a loop. + uint8 *TempBuffer = new uint8[PacketSize]; + memcpy(TempBuffer, this->Buffer, PacketSize); + this->connect(); + memcpy(this->Buffer, TempBuffer, PacketSize); + delete[] TempBuffer; + + if(!this->isConnected()){ + return QUERY_FAILED; + } + } + + if(this->write(this->Buffer, PacketSize) != PacketSize){ + this->disconnect(); + if(Attempt > 0){ + error("TQueryManagerConnection::executeQuery: Fehler beim Abschicken der Anfrage.\n"); + return QUERY_FAILED; + } + continue; + } + + uint8 Help[4]; + int BytesRead = this->read(Help, 2, Timeout); + if(BytesRead != 2){ + this->disconnect(); + if(BytesRead == -2 || Attempt > 0){ + return QUERY_FAILED; + } + continue; + } + + int ResponseSize = ((int)Help[0]) | ((int)Help[1] << 8); + if(ResponseSize == 0xFFFF){ + if(this->read(Help, 4, Timeout) != 4){ + this->disconnect(); + return QUERY_FAILED; + } + + ResponseSize = ((int)Help[0]) | ((int)Help[1] << 8) + | ((int)Help[2] << 16) | ((int)Help[3] << 24); + } + + if(ResponseSize <= 0 || ResponseSize > this->BufferSize){ + this->disconnect(); + error("TQueryManagerConnection::executeQuery: Ungültige Datengröße %d.\n", ResponseSize); + return QUERY_FAILED; + } + + if(this->read(this->Buffer, ResponseSize, Timeout) != ResponseSize){ + this->disconnect(); + error("TQueryManagerConnection::executeQuery: Fehler beim Auslesen der Daten.\n"); + return QUERY_FAILED; + } + + int Status = this->getByte(); + if(Status == QUERY_FAILED){ + error("TQueryManagerConnection::executeQuery: Anfrage fehlgeschlagen.\n"); + } + + return Status; + } +} diff --git a/src/query.hh b/src/query.hh index a69413a..8bdd527 100644 --- a/src/query.hh +++ b/src/query.hh @@ -4,8 +4,43 @@ #include "common.hh" #include "threads.hh" +enum : int { + QUERY_OK = 0, + QUERY_ERROR = 1, + QUERY_FAILED = 3, +}; + struct TQueryManagerConnection{ TQueryManagerConnection(int QueryBufferSize); + ~TQueryManagerConnection(void); + + void connect(void); + void disconnect(void); + int write(const uint8 *Buffer, int Size); + int read(uint8 *Buffer, int Size, int Timeout); + bool isConnected(void){ + return this->Socket != -1; + } + + void prepareQuery(int QueryType); + void sendFlag(bool Flag); + void sendByte(uint8 Byte); + void sendWord(uint16 Word); + void sendQuad(uint32 Quad); + void sendString(const char *String); + void sendBytes(const uint8 *Buffer, int Count); + + bool getFlag(void); + uint8 getByte(void); + uint16 getWord(void); + uint32 getQuad(void); + void getString(char *Buffer, int MaxLength); + void getBytes(uint8 *Buffer, int Count); + + int executeQuery(int Timeout, bool AutoReconnect); + +//== + int loadWorldConfig(int *WorldType, int *RebootTime, int *IPAddress, int *Port, int *MaxPlayers, int *PremiumPlayerBuffer, @@ -71,10 +106,6 @@ struct TQueryManagerConnection{ int insertHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); int updateHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); - bool isConnected(void){ - return this->Socket >= 0; - } - // DATA // ================= int BufferSize; diff --git a/src/stubs.hh b/src/stubs.hh deleted file mode 100644 index 0be5c77..0000000 --- a/src/stubs.hh +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TIBIA_STUBS_HH_ -#define TIBIA_STUBS_HH_ 1 - -#include "common.hh" -#include "enums.hh" -#include "cr.hh" -#include "map.hh" - -// IMPORTANT(fusion): These function definitions exist to test compilation. They're -// not yet implemented and will cause the linker to fail with unresolved symbols. - -extern void SavePlayerData(TPlayerData *Slot); -extern bool LoadPlayerData(TPlayerData *Slot); -extern bool PlayerDataExists(uint32 CharacterID); - -#endif //TIBIA_STUBS_HH_ -- cgit v1.2.3