From 5e2c1e77696953dcadd2e510eed6e5abf13ac760 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 25 Feb 2023 15:59:30 -0600 Subject: [PATCH] feat(net): wire up polling loop for realm connections --- src/client/Client.cpp | 4 +- src/event/Types.hpp | 6 +- src/net/Poll.cpp | 10 +++ src/net/Poll.hpp | 8 ++ src/net/connection/NetClient.cpp | 106 ++++++++++++++++++++++++- src/net/connection/NetClient.hpp | 15 ++++ src/net/connection/RealmConnection.cpp | 21 +++++ src/net/connection/RealmConnection.hpp | 13 +++ 8 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 src/net/Poll.cpp create mode 100644 src/net/Poll.hpp diff --git a/src/client/Client.cpp b/src/client/Client.cpp index b23d7b3..6faf55a 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -8,6 +8,7 @@ #include "gx/Screen.hpp" #include "gx/Texture.hpp" #include "model/Model2.hpp" +#include "net/Poll.hpp" #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" #include "util/BlizzardCore.hpp" @@ -436,5 +437,6 @@ void WowClientInit() { // TODO // CGlueMgr::m_pendingTimerAlert = dword_B2F9D8; // sub_7FC5A0(); - // EventRegister(EVENT_ID_POLL, &PollNet); + + EventRegister(EVENT_ID_POLL, &PollNet); } diff --git a/src/event/Types.hpp b/src/event/Types.hpp index adb25c8..07a72fd 100644 --- a/src/event/Types.hpp +++ b/src/event/Types.hpp @@ -33,9 +33,9 @@ enum EVENTID { EVENT_ID_PAINT = 23, EVENT_ID_NET_DATA = 24, EVENT_ID_NET_CONNECT = 25, - EVENT_ID_26 = 26, - EVENT_ID_27 = 27, - EVENT_ID_28 = 28, + EVENT_ID_NET_DISCONNECT = 26, + EVENT_ID_NET_CANTCONNECT = 27, + EVENT_ID_NET_DESTROY = 28, EVENT_ID_NET_AUTH_CHALLENGE = 29, EVENT_ID_30 = 30, EVENT_ID_31 = 31, diff --git a/src/net/Poll.cpp b/src/net/Poll.cpp new file mode 100644 index 0000000..75aaf3b --- /dev/null +++ b/src/net/Poll.cpp @@ -0,0 +1,10 @@ +#include "net/Poll.hpp" +#include "net/connection/RealmConnection.hpp" + +int32_t PollNet(const void* a1, void* a2) { + RealmConnection::PollNet(); + + // TODO + + return 1; +} diff --git a/src/net/Poll.hpp b/src/net/Poll.hpp new file mode 100644 index 0000000..1c4a86f --- /dev/null +++ b/src/net/Poll.hpp @@ -0,0 +1,8 @@ +#ifndef NET_POLL_HPP +#define NET_POLL_HPP + +#include + +int32_t PollNet(const void* a1, void* a2); + +#endif diff --git a/src/net/connection/NetClient.cpp b/src/net/connection/NetClient.cpp index 6cb09dd..30f0a16 100644 --- a/src/net/connection/NetClient.cpp +++ b/src/net/connection/NetClient.cpp @@ -38,11 +38,71 @@ void NETEVENTQUEUE::AddEvent(EVENTID eventId, void* conn, NetClient* client, con node->m_timeReceived = OsGetAsyncTimeMsPrecise(); - // TODO SInterlockedIncremement(client->uint2E44); + client->AddRef(); this->m_critSect.Leave(); } +void NETEVENTQUEUE::Poll() { + this->m_critSect.Enter(); + + auto deleted = false; + auto client = this->m_client; + + client->AddRef(); + + for (auto node = this->m_eventQueue.Head(); node; node = this->m_eventQueue.Next(node)) { + if (!client->GetDelete()) { + switch (node->m_eventId) { + case EVENT_ID_NET_DATA: + client->HandleData(node->m_timeReceived, node->m_data, node->m_dataSize); + break; + + case EVENT_ID_NET_CONNECT: + client->HandleConnect(); + break; + + case EVENT_ID_NET_DISCONNECT: + client->HandleDisconnect(); + break; + + case EVENT_ID_NET_CANTCONNECT: + client->HandleCantConnect(); + break; + + case EVENT_ID_NET_DESTROY: + client->SetDelete(); + deleted = true; + break; + + case EVENT_ID_NET_AUTH_CHALLENGE: + client->HandleAuthChallenge(static_cast(node->m_data)); + break; + + default: + break; + } + } + + // Matching 1:1 with the ref added by NETEVENTQUEUE::AddEvent + client->DelRef(); + } + + if (!deleted) { + client->HandleIdle(); + } + + client->DelRef(); + + this->m_eventQueue.DeleteAll(); + + this->m_critSect.Leave(); +} + +void NetClient::AddRef() { + SInterlockedIncrement(&this->m_refCount); +} + void NetClient::AuthChallengeHandler(WowConnection* conn, CDataStore* msg) { auto challenge = static_cast(SMemAlloc(sizeof(AuthenticationChallenge), __FILE__, __LINE__, 0x0)); @@ -98,6 +158,42 @@ int32_t NetClient::ConnectInternal(const char* host, uint16_t port) { return 1; } +void NetClient::DelRef() { + auto refCount = SInterlockedDecrement(&this->m_refCount); + + if (refCount == 0 && this->m_deleteMe) { + delete this; + } +} + +bool NetClient::GetDelete() { + return this->m_deleteMe; +} + +int32_t NetClient::HandleCantConnect() { + // TODO + return 1; +} + +int32_t NetClient::HandleConnect() { + // TODO + return 1; +} + +int32_t NetClient::HandleData(uint32_t timeReceived, void* data, int32_t size) { + // TODO + return 1; +} + +int32_t NetClient::HandleDisconnect() { + // TODO + return 1; +} + +void NetClient::HandleIdle() { + // TODO; +} + int32_t NetClient::Initialize() { STORM_ASSERT(this->m_netState == NS_UNINITIALIZED); @@ -127,10 +223,18 @@ int32_t NetClient::Initialize() { return 1; } +void NetClient::PollEventQueue() { + this->m_netEventQueue->Poll(); +} + void NetClient::PongHandler(WowConnection* conn, CDataStore* msg) { // TODO } +void NetClient::SetDelete() { + this->m_deleteMe = true; +} + void NetClient::SetLoginData(LoginData* loginData) { memcpy(&this->m_loginData, loginData, sizeof(this->m_loginData)); } diff --git a/src/net/connection/NetClient.hpp b/src/net/connection/NetClient.hpp index 23d1cea..d14b836 100644 --- a/src/net/connection/NetClient.hpp +++ b/src/net/connection/NetClient.hpp @@ -4,6 +4,7 @@ #include "net/connection/WowConnectionResponse.hpp" #include "event/Event.hpp" #include "net/Types.hpp" +#include #include #include #include @@ -41,6 +42,7 @@ class NETEVENTQUEUE { : m_client(client) {}; void AddEvent(EVENTID eventId, void* conn, NetClient* client, const void* data, uint32_t bytes); + void Poll(); }; class NetClient : public WowConnectionResponse { @@ -57,6 +59,8 @@ class NetClient : public WowConnectionResponse { NETEVENTQUEUE* m_netEventQueue = nullptr; WowConnection* m_serverConnection = nullptr; WowConnection* m_redirectConnection = nullptr; + ATOMIC32 m_refCount = 0; + bool m_deleteMe = false; uint32_t m_pingSent = 0; uint32_t m_pingSequence = 0; uint32_t m_latency[16]; @@ -69,13 +73,24 @@ class NetClient : public WowConnectionResponse { virtual void WCConnected(WowConnection* conn, WowConnection* inbound, uint32_t timeStamp, const NETCONNADDR* addr); virtual void WCCantConnect(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr); virtual void WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr); + virtual int32_t HandleData(uint32_t timeReceived, void* data, int32_t size); + virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge) = 0; + virtual int32_t HandleConnect(); + virtual int32_t HandleDisconnect(); + virtual int32_t HandleCantConnect(); // Member functions + void AddRef(); void AuthChallengeHandler(WowConnection* conn, CDataStore* msg); void Connect(const char* addrStr); int32_t ConnectInternal(const char* host, uint16_t port); + void DelRef(); + bool GetDelete(); + void HandleIdle(); int32_t Initialize(); + void PollEventQueue(); void PongHandler(WowConnection* conn, CDataStore* msg); + void SetDelete(); void SetLoginData(LoginData* loginData); void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param); }; diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index 373156f..9935444 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -1,11 +1,24 @@ #include "net/connection/RealmConnection.hpp" #include "net/Types.hpp" +SCritSect RealmConnection::s_AllRealmConnectionsCrit; +STORM_LIST(RealmConnection::REALMCONNECTIONNODE) RealmConnection::s_AllRealmConnections; + int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { // TODO return 0; } +void RealmConnection::PollNet() { + RealmConnection::s_AllRealmConnectionsCrit.Enter(); + + for (auto node = RealmConnection::s_AllRealmConnections.Head(); node; node = RealmConnection::s_AllRealmConnections.Next(node)) { + node->connection->PollEventQueue(); + } + + RealmConnection::s_AllRealmConnectionsCrit.Leave(); +} + RealmConnection::RealmConnection(RealmResponse* realmResponse) { this->m_realmResponse = realmResponse; @@ -25,7 +38,15 @@ RealmConnection::RealmConnection(RealmResponse* realmResponse) { this->SetMessageHandler(SMSG_DELETE_CHAR, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_CACHE_VERSION, &RealmConnection::MessageHandler, this); + RealmConnection::s_AllRealmConnectionsCrit.Enter(); + auto node = RealmConnection::s_AllRealmConnections.NewNode(2, 0, 0x0); + node->connection = this; + RealmConnection::s_AllRealmConnectionsCrit.Leave(); +} + +int32_t RealmConnection::HandleAuthChallenge(AuthenticationChallenge* challenge) { // TODO + return 1; } void RealmConnection::SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4) { diff --git a/src/net/connection/RealmConnection.hpp b/src/net/connection/RealmConnection.hpp index 7ebeccd..a471710 100644 --- a/src/net/connection/RealmConnection.hpp +++ b/src/net/connection/RealmConnection.hpp @@ -9,12 +9,25 @@ class RealmResponse; class RealmConnection : public NetClient { public: + // Types + struct REALMCONNECTIONNODE : TSLinkedNode { + RealmConnection* connection; + }; + + // Static variables + SCritSect static s_AllRealmConnectionsCrit; + STORM_LIST(REALMCONNECTIONNODE) static s_AllRealmConnections; + // Static functions int32_t static MessageHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + void static PollNet(); // Member variables RealmResponse* m_realmResponse; + // Virtual member functions + virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge); + // Member functions RealmConnection(RealmResponse* realmResponse); void SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4);