aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-19 03:13:48 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-19 03:13:48 -0300
commitbd3a6a04601749cbde007eaabf803fb602ee2783 (patch)
tree476b89932627aa73ad88de22d37e4617bbdb1795 /src
parente5b8aadd493b8b5df4ed661f2491de33d634b001 (diff)
downloadgame-bd3a6a04601749cbde007eaabf803fb602ee2783.tar.gz
game-bd3a6a04601749cbde007eaabf803fb602ee2783.zip
beginning of `communication.cc`
Diffstat (limited to 'src')
-rw-r--r--src/common.hh2
-rw-r--r--src/communication.cc335
-rw-r--r--src/communication.hh31
-rw-r--r--src/connections.hh (renamed from src/connection.hh)13
-rw-r--r--src/cr.hh2
-rw-r--r--src/crmain.cc1
-rw-r--r--src/crplayer.cc2
-rw-r--r--src/crypto.cc3
-rw-r--r--src/crypto.hh58
-rw-r--r--src/main.cc19
-rw-r--r--src/operate.cc13
-rw-r--r--src/query.hh6
-rw-r--r--src/shm.cc2
-rw-r--r--src/strings.cc2
-rw-r--r--src/stubs.hh5
-rw-r--r--src/threads.cc (renamed from src/thread.cc)2
-rw-r--r--src/threads.hh (renamed from src/thread.hh)6
-rw-r--r--src/utils.cc (renamed from src/util.cc)0
18 files changed, 459 insertions, 43 deletions
diff --git a/src/common.hh b/src/common.hh
index 384d76e..e0bfb81 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -150,7 +150,7 @@ void GetAmbiente(int *Brightness, int *Color);
uint32 GetRoundAtTime(int Hour, int Minute);
uint32 GetRoundForNextMinute(void);
-// util.cc
+// utils.cc
// =============================================================================
typedef void TErrorFunction(const char *Text);
typedef void TPrintFunction(int Level, const char *Text);
diff --git a/src/communication.cc b/src/communication.cc
new file mode 100644
index 0000000..dc28566
--- /dev/null
+++ b/src/communication.cc
@@ -0,0 +1,335 @@
+#include "communication.hh"
+#include "config.hh"
+#include "connections.hh"
+#include "containers.hh"
+#include "crypto.hh"
+#include "query.hh"
+#include "threads.hh"
+
+#include "stubs.hh"
+
+#include <signal.h>
+
+#define MAX_COMMUNICATION_THREADS 1100
+#define THREAD_OWN_STACK_SIZE ((int)KB(64))
+
+static int TERMINAL_VERSION[3] = {770, 770, 770};
+static int TCPSocket;
+static ThreadHandle AcceptorThread;
+static pid_t AcceptorThreadPID;
+static int ActiveConnections;
+
+static Semaphore RSAMutex(1);
+static TRSAPrivateKey PrivateKey;
+
+static TQueryManagerConnectionPool QueryManagerConnectionPool(10);
+static int LoadHistory[360];
+static int LoadHistoryPointer;
+static int TotalLoad;
+static int TotalSend;
+static int TotalRecv;
+static uint32 LagEnd;
+static uint32 EarliestFreeAccountAdmissionRound;
+static store<TWaitinglistEntry, 100> Waitinglist;
+static TWaitinglistEntry *WaitinglistHead;
+
+static Semaphore CommunicationThreadMutex(1);
+static bool UseOwnStacks;
+static uint8 CommunicationThreadStacks[MAX_COMMUNICATION_THREADS][THREAD_OWN_STACK_SIZE];
+static pid_t LastUsingCommunicationThread[MAX_COMMUNICATION_THREADS];
+static int FreeCommunicationThreadStacks[MAX_COMMUNICATION_THREADS];
+static int NumberOfFreeCommunicationThreadStacks;
+
+// Communication Thread Stacks
+// =============================================================================
+void GetCommunicationThreadStack(int *StackNumber, void **Stack){
+ *StackNumber = -1;
+ *Stack = NULL;
+
+ if(!UseOwnStacks){
+ error("GetCommunicationThreadStack: Bibliothek unterstützt keine eigenen Stacks.\n");
+ return;
+ }
+
+ CommunicationThreadMutex.down();
+ for(int i = 0; i < NumberOfFreeCommunicationThreadStacks; i += 1){
+ int FreeStack = FreeCommunicationThreadStacks[i];
+ if(LastUsingCommunicationThread[FreeStack] == 0
+ || kill(LastUsingCommunicationThread[FreeStack], 0) == -1){
+ // NOTE(fusion): A little swap and pop action.
+ NumberOfFreeCommunicationThreadStacks -= 1;
+ FreeCommunicationThreadStacks[i] = FreeCommunicationThreadStacks[NumberOfFreeCommunicationThreadStacks];
+
+ *StackNumber = FreeStack;
+ *Stack = CommunicationThreadStacks[FreeStack];
+ break;
+ }
+ }
+ CommunicationThreadMutex.up();
+}
+
+void AttachCommunicationThreadStack(int StackNumber){
+ LastUsingCommunicationThread[StackNumber] = getpid();
+}
+
+void ReleaseCommunicationThreadStack(int StackNumber){
+ CommunicationThreadMutex.down();
+ FreeCommunicationThreadStacks[NumberOfFreeCommunicationThreadStacks] = StackNumber;
+ NumberOfFreeCommunicationThreadStacks += 1;
+ CommunicationThreadMutex.up();
+}
+
+void InitCommunicationThreadStacks(void){
+ if(UseOwnStacks){
+ memset(CommunicationThreadStacks, 0xAA, sizeof(CommunicationThreadStacks));
+ for(int i = 0; i < MAX_COMMUNICATION_THREADS; i += 1){
+ LastUsingCommunicationThread[i] = 0;
+ FreeCommunicationThreadStacks[i] = i;
+ }
+ NumberOfFreeCommunicationThreadStacks = MAX_COMMUNICATION_THREADS;
+ }
+}
+
+void ExitCommunicationThreadStacks(void){
+ if(UseOwnStacks){
+ if(NumberOfFreeCommunicationThreadStacks != MAX_COMMUNICATION_THREADS){
+ error("FreeCommunicationThreadStacks: Nicht alle Stacks freigegeben.\n");
+ }
+
+ int HighestStackAddress = -1;
+ int LowestStackAddress = THREAD_OWN_STACK_SIZE;
+ for(int i = 0; i < MAX_COMMUNICATION_THREADS; i += 1){
+ for(int Addr = 0; Addr < THREAD_OWN_STACK_SIZE; Addr += 1){
+ if(CommunicationThreadStacks[i][Addr] != 0xAA){
+ if(Addr < LowestStackAddress){
+ LowestStackAddress = Addr;
+ }
+
+ if(Addr > HighestStackAddress){
+ HighestStackAddress = Addr;
+ }
+ }
+ }
+ }
+
+ // NOTE(fusion): It seems we want to track whether the stack size is
+ // too small but I'd argue the method is not very robust.
+ if((HighestStackAddress - LowestStackAddress) > (THREAD_OWN_STACK_SIZE / 2)){
+ error("Maximale Stack-Ausdehnung: %d..%d\n", LowestStackAddress, HighestStackAddress);
+ }
+ }
+}
+
+// Load History
+// =============================================================================
+void InitLoadHistory(void){
+ for(int i = 0; i < NARRAY(LoadHistory); i += 1){
+ LoadHistory[i] = 0;
+ }
+ LoadHistoryPointer = 0;
+ TotalLoad = 0;
+ TotalSend = 0;
+ TotalRecv = 0;
+ LagEnd = 0;
+ EarliestFreeAccountAdmissionRound = 0;
+ InitLog("netload");
+}
+
+bool LagDetected(void){
+ return RoundNr <= LagEnd;
+}
+
+void NetLoad(int Amount, bool Send){
+ CommunicationThreadMutex.down();
+ if(Send){
+ TotalSend += Amount;
+ }else{
+ TotalRecv += Amount;
+ }
+ CommunicationThreadMutex.up();
+}
+
+void NetLoadSummary(void){
+ CommunicationThreadMutex.down();
+ Log("netload", "gesendet: %d Bytes.\n", TotalSend);
+ Log("netload", "empfangen: %d Bytes.\n", TotalRecv);
+ TotalSend = 0;
+ TotalRecv = 0;
+ CommunicationThreadMutex.up();
+}
+
+void NetLoadCheck(void){
+ static int LastRecv;
+
+ int DeltaRecv = TotalRecv - LastRecv;
+ LastRecv = TotalRecv;
+ if(DeltaRecv < 0){
+ return;
+ }
+
+ int DeltaRecvPerPlayer = 0;
+ int PlayersOnline = GetPlayersOnline();
+ if(PlayersOnline > 0){
+ DeltaRecvPerPlayer = DeltaRecv / PlayersOnline;
+ }
+
+ TotalLoad -= LoadHistory[LoadHistoryPointer];
+ TotalLoad += DeltaRecvPerPlayer;
+ LoadHistory[LoadHistoryPointer] = DeltaRecvPerPlayer;
+ LoadHistoryPointer += 1;
+ if(LoadHistoryPointer >= NARRAY(LoadHistory)){
+ LoadHistoryPointer = 0;
+ }
+
+ // NOTE(fusion): Running this lag check only makes sense if `LoadHistory`
+ // is filled up which won't be the case until this function executes at
+ // least as many times as there are entries in `LoadHistory`.
+ // Looking at `AdvanceGame`, we see that this function is called every
+ // 10 rounds, giving us the value of `EarliestLagCheckRound`.
+ constexpr uint32 EarliestLagCheckRound = 10 * NARRAY(LoadHistory);
+ if(RoundNr >= EarliestLagCheckRound && PlayersOnline >= 50){
+ int AvgDeltaRecvPerPlayer = (TotalLoad / NARRAY(LoadHistory));
+ if(DeltaRecvPerPlayer < (AvgDeltaRecvPerPlayer / 2)){
+ Log("game", "Lag erkannt!\n");
+ LagEnd = RoundNr + 30;
+
+ // NOTE(fusion): This formula looks weird but when we take `MaxPlayers`
+ // and `PremiumPlayerBuffer` to be 950 and 150 (taken from the config
+ // file, although their values are now loaded from the database), we
+ // get a line with negative values when the number of players online
+ // is less than 650, and exactly 60 when it is 950. Since the delay
+ // is 60 when `PremiumPlayerBuffer` is zero, I don't think this is a
+ // coincidence.
+ int FreeAccountAdmissionDelay = 60;
+ if(PremiumPlayerBuffer != 0){
+ FreeAccountAdmissionDelay = (PlayersOnline + PremiumPlayerBuffer * 2 - MaxPlayers);
+ FreeAccountAdmissionDelay = (FreeAccountAdmissionDelay * 30) / PremiumPlayerBuffer;
+ if(FreeAccountAdmissionDelay < 0){
+ FreeAccountAdmissionDelay = 0;
+ }
+ }
+
+ uint32 FreeAccountAdmissionRound = RoundNr + (uint32)FreeAccountAdmissionDelay;
+ if(EarliestFreeAccountAdmissionRound < FreeAccountAdmissionRound){
+ EarliestFreeAccountAdmissionRound = FreeAccountAdmissionRound;
+ }
+
+ TConnection *Connection = GetFirstConnection();
+ while(Connection != NULL){
+ if(Connection->Live()){
+ Connection->EmergencyPing();
+ }
+ Connection = GetNextConnection();
+ }
+ }
+ }
+}
+
+// Communication Handling
+// =============================================================================
+bool WriteToSocket(TConnection *Connection, uint8 *Buffer, int Size){
+ // TODO(fusion): I think `Size` refers to the payload but `Buffer` also has
+ // room for writing the packet's length at the beginning and enough room for
+ // padding (supposedly).
+
+ while((Size % 8) != 0){
+ Buffer[Size + 2] = rand_r(&Connection->RandomSeed);
+ Size += 1;
+ }
+
+ for(int i = 0; i < Size; i += 8){
+ Connection->SymmetricKey.encrypt(&Buffer[i + 2]);
+ }
+
+ TWriteBuffer WriteBuffer(Buffer, 2);
+ WriteBuffer.writeWord((uint16)Size);
+
+ int Attempts = 50;
+ 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){
+ // TODO(fusion): Can this even happen?
+ error("WriteToSocket: Fehler %d beim Senden an Socket %d.\n",
+ errno, Connection->GetSocket());
+ return false;
+ }else{
+ if(errno == EINTR){
+ continue;
+ }
+
+ if(errno != EAGAIN || Attempts <= 0){
+ if(errno == ECONNRESET || errno == EPIPE || errno == EAGAIN){
+ Log("game", "Verbindung an Socket %d zusammengebrochen.\n",
+ Connection->GetSocket());
+ }else{
+ error("WriteToSocket: Fehler %d beim Senden an Socket %d.\n",
+ errno, Connection->GetSocket());
+ }
+ return false;
+ }
+
+ DelayThread(0, 100000);
+ Attempts -= 1;
+ }
+ }
+
+ // TODO(fusion): Do we add 50 extra bytes to account for TCP segment headers?
+ // This does make sense If we assume packets are split into ~2.5 segments on
+ // average, with each segment header being 20 bytes.
+ NetLoad(Size + 50, true);
+ return true;
+}
+
+bool SendLoginMessage(TConnection *Connection, int Type, char *Message, int WaitingTime){
+ // TODO(fusion):
+ // LOGIN_MESSAGE_ERROR = 20
+ // LOGIN_MESSAGE_? = 21
+ // LOGIN_MESSAGE_WAITING_LIST = 22
+ if(Type != 20 && Type != 21 && Type != 22){
+ error("SendLoginMessage: Ungültiger Meldungstyp %d.\n", Type);
+ return true;
+ }
+
+ if(Message == NULL){
+ error("SendLoginMessage: Message ist NULL.\n");
+ return true;
+ }
+
+ if(Type == 22 && (WaitingTime < 0 || WaitingTime > UINT8_MAX)){
+ error("SendLoginMessage: Ungültige Wartezeit %d.\n", WaitingTime);
+ return true;
+ }
+
+ if(strlen(Message) > 290){
+ error("SendLoginMessage: Botschaft zu lang (%s).\n", Message);
+ return true;
+ }
+
+ // TODO(fusion): Writing output messages should have more robust helpers
+ // to avoid all sorts of memory bugs but since we're only doing it in two
+ // places from what I've seen, I'm not actually gonna bother (for now at
+ // least).
+
+ // NOTE(fusion): We make sure we leave two extra bytes at the beginning so
+ // `WriteToSocket` can write the packet size. We also make sure that the
+ // remainder of the buffer has a size that is multiple of 8 so `WriteToSocket`
+ // can add any necessary padding for XTEA encryption without overflowing it.
+ uint8 Data[302]; // 2 + 300
+ TWriteBuffer WriteBuffer(Data + 2, sizeof(Data) - 2);
+ WriteBuffer.writeWord(0);
+ WriteBuffer.writeByte((uint8)Type);
+ WriteBuffer.writeString(Message);
+ if(Type == 22){
+ WriteBuffer.writeByte(WaitingTime);
+ }
+
+ int Size = WriteBuffer.Position;
+ WriteBuffer.Position = 0;
+ WriteBuffer.writeWord((uint16)(Size - 2));
+ return WriteToSocket(Connection, Data, Size);
+}
diff --git a/src/communication.hh b/src/communication.hh
new file mode 100644
index 0000000..a54f704
--- /dev/null
+++ b/src/communication.hh
@@ -0,0 +1,31 @@
+#ifndef TIBIA_COMMUNICATION_HH_
+#define TIBIA_COMMUNICATION_HH_ 1
+
+#include "common.hh"
+#include "connections.hh"
+
+struct TWaitinglistEntry {
+ TWaitinglistEntry *Next;
+ char Name[30];
+ uint32 NextTry;
+ bool FreeAccount;
+ bool Newbie;
+ bool Sleeping;
+};
+
+void GetCommunicationThreadStack(int *StackNumber, void **Stack);
+void AttachCommunicationThreadStack(int StackNumber);
+void ReleaseCommunicationThreadStack(int StackNumber);
+void InitCommunicationThreadStacks(void);
+void ExitCommunicationThreadStacks(void);
+
+void InitLoadHistory(void);
+bool LagDetected(void);
+void NetLoad(int Amount, bool Send);
+void NetLoadSummary(void);
+void NetLoadCheck(void);
+
+bool WriteToSocket(TConnection *Connection, uint8 *Buffer, int Size);
+bool SendLoginMessage(TConnection *Connection, int Type, char *Message, int WaitingTime);
+
+#endif //TIBIA_COMMUNICATION_HH_
diff --git a/src/connection.hh b/src/connections.hh
index 5e2b1ba..0aef82b 100644
--- a/src/connection.hh
+++ b/src/connections.hh
@@ -2,6 +2,7 @@
#define TIBIA_CONNECTION_HH_ 1
#include "common.hh"
+#include "crypto.hh"
#include "enums.hh"
struct TConnection;
@@ -22,6 +23,16 @@ struct TConnection {
const char *GetIPAddress(void);
void Die(void);
KNOWNCREATURESTATE KnownCreature(uint32 CreatureID, bool UpdateFollows);
+ int GetSocket(void);
+ void EmergencyPing(void);
+
+ // TODO(fusion): Maybe rename this later?
+ bool Live(void) const {
+ return this->State == CONNECTION_LOGIN
+ || this->State == CONNECTION_GAME
+ || this->State == CONNECTION_DEAD
+ || this->State == CONNECTION_LOGOUT;
+ }
// DATA
// =================
@@ -45,7 +56,7 @@ struct TConnection {
pid_t PID;
int Socket;
char IPAddress[16];
- // TXTEASymmetricKey SymmetricKey; // TODO
+ TXTEASymmetricKey SymmetricKey;
bool ConnectionIsOk;
bool ClosingIsDelayed;
uint8 field23_0x4852;
diff --git a/src/cr.hh b/src/cr.hh
index 37671b8..a971b3b 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -2,7 +2,7 @@
#define TIBIA_CREATURE_HH_ 1
#include "common.hh"
-#include "connection.hh"
+#include "connections.hh"
#include "containers.hh"
#include "enums.hh"
#include "map.hh"
diff --git a/src/crmain.cc b/src/crmain.cc
index a98f33e..6193515 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -1,4 +1,5 @@
#include "cr.hh"
+#include "communication.hh"
#include "config.hh"
#include "enums.hh"
#include "info.hh"
diff --git a/src/crplayer.cc b/src/crplayer.cc
index 24fcd56..5c28855 100644
--- a/src/crplayer.cc
+++ b/src/crplayer.cc
@@ -3,7 +3,7 @@
#include "info.hh"
#include "operate.hh"
#include "query.hh"
-#include "thread.hh"
+#include "threads.hh"
#include "stubs.hh"
diff --git a/src/crypto.cc b/src/crypto.cc
new file mode 100644
index 0000000..b6df866
--- /dev/null
+++ b/src/crypto.cc
@@ -0,0 +1,3 @@
+#include "crypto.hh"
+
+// TODO
diff --git a/src/crypto.hh b/src/crypto.hh
new file mode 100644
index 0000000..e90996c
--- /dev/null
+++ b/src/crypto.hh
@@ -0,0 +1,58 @@
+#ifndef TIBIA_CRYPTO_HH_
+#define TIBIA_CRYPTO_HH_ 1
+
+#include "common.hh"
+
+// TODO(fusion): We might want to scrap this implementation and use OpenSSL instead.
+
+struct vlong_flex_unit{
+ uint32 n;
+ uint32 *a;
+ uint32 z;
+};
+
+struct vlong_value: vlong_flex_unit {
+ uint32 share;
+};
+
+struct vlong{
+ vlong_value *value;
+ int negative;
+};
+
+struct vlong_montgomery{
+ vlong R;
+ vlong R1;
+ vlong m;
+ vlong n1;
+ vlong T;
+ vlong k;
+ uint32 N;
+};
+
+struct TRSAPrivateKey{
+ TRSAPrivateKey(void);
+ ~TRSAPrivateKey(void);
+ void decrypt(uint8 *Data); // single 128 bytes block
+
+ // DATA
+ // =================
+ vlong m_PrimeP;
+ vlong m_PrimeQ;
+ vlong m_U;
+ vlong m_DP;
+ vlong m_DQ;
+};
+
+struct TXTEASymmetricKey{
+ TXTEASymmetricKey(void);
+ ~TXTEASymmetricKey(void);
+ void encrypt(uint8 *Data); // single 8 bytes block
+ void decrypt(uint8 *Data); // single 8 bytes block
+
+ // DATA
+ // =================
+ uint32 m_SymmetricKey[4];
+};
+
+#endif //TIBIA_CRYPTO_HH_
diff --git a/src/main.cc b/src/main.cc
index c0180c2..8d5fcf5 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,4 +1,5 @@
#include "common.hh"
+#include "communication.hh"
#include "config.hh"
#include "info.hh"
#include "map.hh"
@@ -327,23 +328,7 @@ static void AdvanceGame(int Delay){
OldAmbiente = Brightness;
TConnection *Connection = GetFirstConnection();
while(Connection != NULL){
- // TODO(fusion): This is probably an inlined function that checks
- // whether the connection is still going. The exact decompiled condition
- // was `Connection->State - CONDITION_LOGIN < 4` but I think that's
- // just a compiler optimization that wouldn't work properly on the
- // decompiled version. That comparison in the disassembly is unsigned
- // (`JBE`) but the enum is signed which would probably generate an
- // invalid signed comparison (`JLE`).
- //
- // MOV EAX, dword ptr [Connection + Connection->State]
- // SUB EAX, 0x3
- // CMP EAX, 0x3
- // JBE ... -> SendAmbiente(Connection)
- //
- if(Connection->State == CONNECTION_LOGIN
- || Connection->State == CONNECTION_GAME
- || Connection->State == CONNECTION_DEAD
- || Connection->State == CONNECTION_LOGOUT){
+ if(Connection->Live()){
SendAmbiente(Connection);
}
Connection = GetNextConnection();
diff --git a/src/operate.cc b/src/operate.cc
index 7dc1fef..aa061a8 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -2393,12 +2393,7 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
uint32 StatementID = LogCommunication(CreatureID, Mode, 0, Text);
TConnection *Connection = GetFirstConnection();
while(Connection != NULL){
- // TODO(fusion): Same as `AdvanceGame`. Definitely some inlined
- // function to check whether the connection is in a valid state.
- if(Connection->State == CONNECTION_LOGIN
- || Connection->State == CONNECTION_GAME
- || Connection->State == CONNECTION_DEAD
- || Connection->State == CONNECTION_LOGOUT){
+ if(Connection->Live()){
SendTalk(Connection,
LogListener(StatementID, Connection->GetPlayer()),
Creature->Name, Mode, Text, 0);
@@ -2409,11 +2404,7 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
}else if(Mode == TALK_ANONYMOUS_BROADCAST){
TConnection *Connection = GetFirstConnection();
while(Connection != NULL){
- // TODO(fusion): Same as above.
- if(Connection->State == CONNECTION_LOGIN
- || Connection->State == CONNECTION_GAME
- || Connection->State == CONNECTION_DEAD
- || Connection->State == CONNECTION_LOGOUT){
+ if(Connection->Live()){
SendMessage(Connection, TALK_ADMIN_MESSAGE, Text);
}
diff --git a/src/query.hh b/src/query.hh
index f9cd8de..7d3c2a8 100644
--- a/src/query.hh
+++ b/src/query.hh
@@ -2,7 +2,7 @@
#define TIBIA_QUERY_HH_ 1
#include "common.hh"
-#include "thread.hh"
+#include "threads.hh"
struct TQueryManagerConnection{
TQueryManagerConnection(int QueryBufferSize);
@@ -28,6 +28,10 @@ struct TQueryManagerConnection{
};
struct TQueryManagerConnectionPool{
+ TQueryManagerConnectionPool(int Connections);
+
+ // DATA
+ // =================
int NumberOfConnections;
TQueryManagerConnection *QueryManagerConnection;
bool *QueryManagerConnectionFree;
diff --git a/src/shm.cc b/src/shm.cc
index c68ce1f..ff5f603 100644
--- a/src/shm.cc
+++ b/src/shm.cc
@@ -1,7 +1,7 @@
#include "common.hh"
#include "config.hh"
#include "enums.hh"
-#include "thread.hh"
+#include "threads.hh"
#include "stubs.hh"
diff --git a/src/strings.cc b/src/strings.cc
index aef9a81..d0bfe70 100644
--- a/src/strings.cc
+++ b/src/strings.cc
@@ -218,7 +218,7 @@ void ExitStrings(void){
// String Utility
// =============================================================================
// TODO(fusion): I'm not sure why we have these separate from the other string
-// utility defined in `util.cc`. We should probably just move them all here.
+// utility defined in `utils.cc`. We should probably just move them all here.
bool IsCountable(const char *s){
if(strncmp(s, "some ", 5) == 0){
diff --git a/src/stubs.hh b/src/stubs.hh
index 561fc95..4363b0a 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -3,7 +3,7 @@
#include "common.hh"
#include "enums.hh"
-#include "connection.hh"
+#include "connections.hh"
#include "cr.hh"
#include "magic.hh"
#include "map.hh"
@@ -36,12 +36,9 @@ extern void InitLog(const char *ProtocolName);
extern bool IsInvited(uint16 HouseID, TPlayer *Player, int TimeStamp);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);
extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures);
-extern bool LagDetected(void);
extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void LogoutOrder(TPlayer *Player);
-extern void NetLoadCheck(void);
-extern void NetLoadSummary(void);
extern void PrepareHouseCleanup(void);
extern void FinishHouseCleanup(void);
extern void PlayerlistOrder(int NumberOfPlayers, char *PlayerNames, int *PlayerLevels, int *PlayerProfessions);
diff --git a/src/thread.cc b/src/threads.cc
index 95ce1a6..a7acb41 100644
--- a/src/thread.cc
+++ b/src/threads.cc
@@ -1,4 +1,4 @@
-#include "thread.hh"
+#include "threads.hh"
struct TThreadStarter {
ThreadFunction *Function;
diff --git a/src/thread.hh b/src/threads.hh
index 17e46e9..9eafe11 100644
--- a/src/thread.hh
+++ b/src/threads.hh
@@ -1,5 +1,5 @@
-#ifndef TIBIA_THREAD_HH_
-#define TIBIA_THREAD_HH_ 1
+#ifndef TIBIA_THREADS_HH_
+#define TIBIA_THREADS_HH_ 1
#include "common.hh"
#include <pthread.h>
@@ -30,4 +30,4 @@ struct Semaphore {
pthread_cond_t condition;
};
-#endif //TIBIA_THREAD_HH_
+#endif //TIBIA_THREADS_HH_
diff --git a/src/util.cc b/src/utils.cc
index 4a3523b..4a3523b 100644
--- a/src/util.cc
+++ b/src/utils.cc