2023-01-02 13:17:18 -06:00
|
|
|
#include "net/connection/NetClient.hpp"
|
|
|
|
|
#include "net/connection/WowConnection.hpp"
|
2023-02-11 20:46:32 -06:00
|
|
|
#include <cstdlib>
|
2023-01-02 13:17:18 -06:00
|
|
|
#include <cstring>
|
|
|
|
|
#include <new>
|
2023-02-24 19:41:07 -06:00
|
|
|
#include <common/DataStore.hpp>
|
2023-01-02 13:17:18 -06:00
|
|
|
#include <common/Prop.hpp>
|
2023-02-25 13:40:32 -06:00
|
|
|
#include <common/SHA1.hpp>
|
2023-02-18 17:43:35 -06:00
|
|
|
#include <common/Time.hpp>
|
2023-01-02 13:17:18 -06:00
|
|
|
#include <storm/Error.hpp>
|
2023-02-11 20:46:32 -06:00
|
|
|
#include <storm/String.hpp>
|
2023-01-02 13:17:18 -06:00
|
|
|
|
|
|
|
|
HPROPCONTEXT s_propContext;
|
|
|
|
|
|
|
|
|
|
int32_t NetClient::s_clientCount;
|
|
|
|
|
|
|
|
|
|
void InitializePropContext() {
|
|
|
|
|
if (PropGetSelectedContext() != s_propContext) {
|
|
|
|
|
PropSelectContext(s_propContext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-18 17:43:35 -06:00
|
|
|
void NETEVENTQUEUE::AddEvent(EVENTID eventId, void* conn, NetClient* client, const void* data, uint32_t bytes) {
|
2023-02-25 13:56:08 -06:00
|
|
|
this->m_critSect.Enter();
|
|
|
|
|
|
|
|
|
|
auto node = this->m_eventQueue.NewNode(2, 0, 0x0);
|
|
|
|
|
|
|
|
|
|
node->m_eventId = eventId;
|
|
|
|
|
|
|
|
|
|
if (bytes) {
|
|
|
|
|
node->m_data = SMemAlloc(bytes, __FILE__, __LINE__, 0x0);
|
|
|
|
|
memcpy(node->m_data, data, bytes);
|
|
|
|
|
node->m_dataSize = bytes;
|
|
|
|
|
} else {
|
|
|
|
|
node->m_data = nullptr;
|
|
|
|
|
node->m_dataSize = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node->m_timeReceived = OsGetAsyncTimeMsPrecise();
|
|
|
|
|
|
2023-02-25 15:59:30 -06:00
|
|
|
client->AddRef();
|
2023-02-25 13:56:08 -06:00
|
|
|
|
|
|
|
|
this->m_critSect.Leave();
|
2023-02-18 17:43:35 -06:00
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:59:30 -06:00
|
|
|
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<AuthenticationChallenge*>(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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-24 19:41:07 -06:00
|
|
|
void NetClient::AuthChallengeHandler(WowConnection* conn, CDataStore* msg) {
|
2023-02-25 13:40:32 -06:00
|
|
|
auto challenge = static_cast<AuthenticationChallenge*>(SMemAlloc(sizeof(AuthenticationChallenge), __FILE__, __LINE__, 0x0));
|
|
|
|
|
|
|
|
|
|
uint32_t v14;
|
|
|
|
|
msg->Get(v14);
|
|
|
|
|
|
|
|
|
|
msg->Get(challenge->uint0);
|
|
|
|
|
|
|
|
|
|
// TODO calculate client seed?
|
|
|
|
|
|
|
|
|
|
if (conn == this->m_serverConnection) {
|
|
|
|
|
this->m_netEventQueue->AddEvent(EVENT_ID_NET_AUTH_CHALLENGE, conn, this, challenge, sizeof(AuthenticationChallenge));
|
|
|
|
|
} else if (conn == this->m_redirectConnection) {
|
|
|
|
|
// TODO
|
|
|
|
|
} else {
|
|
|
|
|
conn->Disconnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete challenge;
|
2023-02-24 19:41:07 -06:00
|
|
|
}
|
|
|
|
|
|
2023-02-11 20:46:32 -06:00
|
|
|
void NetClient::Connect(const char* addrStr) {
|
|
|
|
|
if (this->m_netState != NS_INITIALIZED) {
|
|
|
|
|
SErrDisplayAppFatal("Expected (m_netState == NS_INITIALIZED), got %d", this->m_netState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t port = 9090;
|
|
|
|
|
|
|
|
|
|
char host[1024];
|
|
|
|
|
SStrCopy(host, addrStr, sizeof(host));
|
|
|
|
|
|
|
|
|
|
auto portDelim = SStrChr(host, ':');
|
|
|
|
|
if (portDelim) {
|
|
|
|
|
*portDelim = '\0';
|
|
|
|
|
port = atoi(portDelim + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->m_serverConnection->SetEncryptionType(WC_ENCRYPT_0);
|
|
|
|
|
this->m_netState = NS_INITIALIZED;
|
|
|
|
|
this->ConnectInternal(host, port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t NetClient::ConnectInternal(const char* host, uint16_t port) {
|
|
|
|
|
if (this->m_netState != NS_INITIALIZED) {
|
|
|
|
|
SErrDisplayAppFatal("Expected (m_netState == NS_INITIALIZED), got %d", this->m_netState);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-11 20:59:36 -06:00
|
|
|
this->m_netState = NS_CONNECTING;
|
2023-02-11 20:46:32 -06:00
|
|
|
this->m_serverConnection->Connect(host, port, -1);
|
|
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:59:30 -06:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-02 13:17:18 -06:00
|
|
|
int32_t NetClient::Initialize() {
|
|
|
|
|
STORM_ASSERT(this->m_netState == NS_UNINITIALIZED);
|
|
|
|
|
|
|
|
|
|
if (NetClient::s_clientCount == 0) {
|
|
|
|
|
s_propContext = PropGetSelectedContext();
|
|
|
|
|
|
|
|
|
|
if (!WowConnection::InitOsNet(nullptr, InitializePropContext, 1, false)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetClient::s_clientCount++;
|
|
|
|
|
|
|
|
|
|
auto queueMem = SMemAlloc(sizeof(NETEVENTQUEUE), __FILE__, __LINE__, 0x0);
|
|
|
|
|
auto queue = new (queueMem) NETEVENTQUEUE(this);
|
|
|
|
|
this->m_netEventQueue = queue;
|
|
|
|
|
|
|
|
|
|
memset(this->m_handlers, 0, sizeof(this->m_handlers));
|
|
|
|
|
memset(this->m_handlerParams, 0, sizeof(this->m_handlerParams));
|
|
|
|
|
|
|
|
|
|
auto connectionMem = SMemAlloc(sizeof(WowConnection), __FILE__, __LINE__, 0x0);
|
|
|
|
|
auto connection = new (connectionMem) WowConnection(this, nullptr);
|
|
|
|
|
this->m_serverConnection = connection;
|
|
|
|
|
|
|
|
|
|
this->m_netState = NS_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:59:30 -06:00
|
|
|
void NetClient::PollEventQueue() {
|
|
|
|
|
this->m_netEventQueue->Poll();
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-24 19:41:07 -06:00
|
|
|
void NetClient::PongHandler(WowConnection* conn, CDataStore* msg) {
|
|
|
|
|
// TODO
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:59:30 -06:00
|
|
|
void NetClient::SetDelete() {
|
|
|
|
|
this->m_deleteMe = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-07 12:57:25 -06:00
|
|
|
void NetClient::SetLoginData(LoginData* loginData) {
|
|
|
|
|
memcpy(&this->m_loginData, loginData, sizeof(this->m_loginData));
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-02 13:17:18 -06:00
|
|
|
void NetClient::SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param) {
|
|
|
|
|
this->m_handlers[msgId] = handler;
|
|
|
|
|
this->m_handlerParams[msgId] = param;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetClient::WCCantConnect(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) {
|
|
|
|
|
// TODO
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetClient::WCConnected(WowConnection* conn, WowConnection* inbound, uint32_t timeStamp, const NETCONNADDR* addr) {
|
2023-02-18 17:43:35 -06:00
|
|
|
if (conn != this->m_serverConnection) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->m_pingLock.Enter();
|
|
|
|
|
|
2023-01-02 13:17:18 -06:00
|
|
|
// TODO
|
2023-02-18 17:43:35 -06:00
|
|
|
|
|
|
|
|
this->m_latencyStart = 0;
|
|
|
|
|
this->m_latencyEnd = 0;
|
|
|
|
|
this->m_pingSent = OsGetAsyncTimeMsPrecise();
|
|
|
|
|
|
|
|
|
|
this->m_pingLock.Leave();
|
|
|
|
|
|
|
|
|
|
this->m_netEventQueue->AddEvent(EVENT_ID_NET_CONNECT, conn, this, nullptr, 0);
|
2023-01-02 13:17:18 -06:00
|
|
|
}
|
|
|
|
|
|
2023-02-21 08:52:19 -06:00
|
|
|
void NetClient::WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) {
|
2023-01-02 13:17:18 -06:00
|
|
|
// TODO
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-24 19:41:07 -06:00
|
|
|
void NetClient::WCMessageReady(WowConnection* conn, uint32_t timeStamp, CDataStore* msg) {
|
|
|
|
|
uint8_t* data;
|
|
|
|
|
msg->GetDataInSitu(reinterpret_cast<void*&>(data), msg->m_size);
|
|
|
|
|
|
|
|
|
|
// TODO increment byte counter
|
|
|
|
|
// SInterlockedExchangeAdd(this->m_bytesReceived, msg->m_size);
|
|
|
|
|
|
|
|
|
|
msg->m_read = 0;
|
|
|
|
|
|
|
|
|
|
uint16_t msgId;
|
|
|
|
|
msg->Get(msgId);
|
|
|
|
|
|
|
|
|
|
// TODO SMSG_SUSPEND_COMMS (0x50F)
|
|
|
|
|
// TODO SMSG_FORCE_SEND_QUEUED_PACKETS (0x511)
|
|
|
|
|
// TODO SMSG_REDIRECT_CLIENT (0x50D)
|
|
|
|
|
|
|
|
|
|
if (msgId == SMSG_PONG) {
|
|
|
|
|
this->PongHandler(conn, msg);
|
|
|
|
|
return;
|
|
|
|
|
} else if (msgId == SMSG_AUTH_CHALLENGE) {
|
|
|
|
|
this->AuthChallengeHandler(conn, msg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (conn == this->m_serverConnection && !this->m_suspended) {
|
|
|
|
|
msg->m_read = msg->m_size;
|
|
|
|
|
this->m_netEventQueue->AddEvent(EVENT_ID_NET_DATA, conn, this, data, msg->m_size);
|
|
|
|
|
} else {
|
|
|
|
|
conn->Disconnect();
|
|
|
|
|
}
|
2023-01-02 13:17:18 -06:00
|
|
|
}
|