mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 11:12:29 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
19
src/net/CMakeLists.txt
Normal file
19
src/net/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
file(GLOB PRIVATE_SOURCES "*.cpp" "connection/*.cpp" "grunt/*.cpp" "login/*.cpp")
|
||||
|
||||
add_library(net STATIC
|
||||
${PRIVATE_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(net
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
target_link_libraries(net
|
||||
PRIVATE
|
||||
client
|
||||
event
|
||||
PUBLIC
|
||||
common
|
||||
storm
|
||||
)
|
||||
7
src/net/Connection.hpp
Normal file
7
src/net/Connection.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef NET_CONNECTION_HPP
|
||||
#define NET_CONNECTION_HPP
|
||||
|
||||
#include "net/connection/ClientConnection.hpp"
|
||||
#include "net/connection/RealmResponse.hpp"
|
||||
|
||||
#endif
|
||||
7
src/net/Grunt.hpp
Normal file
7
src/net/Grunt.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef NET_GRUNT_HPP
|
||||
#define NET_GRUNT_HPP
|
||||
|
||||
#include "net/grunt/ClientLink.hpp"
|
||||
#include "net/grunt/ClientResponse.hpp"
|
||||
|
||||
#endif
|
||||
7
src/net/Login.hpp
Normal file
7
src/net/Login.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef NET_LOGIN_HPP
|
||||
#define NET_LOGIN_HPP
|
||||
|
||||
#include "net/login/BattlenetLogin.hpp"
|
||||
#include "net/login/GruntLogin.hpp"
|
||||
|
||||
#endif
|
||||
1221
src/net/Types.hpp
Normal file
1221
src/net/Types.hpp
Normal file
File diff suppressed because it is too large
Load diff
34
src/net/connection/ClientConnection.cpp
Normal file
34
src/net/connection/ClientConnection.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include "net/connection/ClientConnection.hpp"
|
||||
#include "net/Login.hpp"
|
||||
#include "client/ClientServices.hpp"
|
||||
|
||||
void ClientConnection::Cancel(int32_t errorCode) {
|
||||
this->Cleanup();
|
||||
|
||||
this->m_statusResult = 0;
|
||||
this->m_errorCode = errorCode;
|
||||
this->m_statusComplete = 1;
|
||||
|
||||
// TODO
|
||||
// LogConnectionStatus(this->m_statusCop, errorCode, 0);
|
||||
}
|
||||
|
||||
void ClientConnection::Cleanup() {
|
||||
if (this->m_cleanup) {
|
||||
this->m_cleanup();
|
||||
this->m_cleanup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientConnection::Connect() {
|
||||
// TODO
|
||||
|
||||
this->m_cleanup = nullptr;
|
||||
this->m_statusCop = COP_CONNECT;
|
||||
this->m_errorCode = 7;
|
||||
this->m_statusComplete = 0;
|
||||
|
||||
// TODO
|
||||
|
||||
ClientServices::LoginConnection()->GetRealmList();
|
||||
}
|
||||
27
src/net/connection/ClientConnection.hpp
Normal file
27
src/net/connection/ClientConnection.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef NET_CONNECTION_CLIENT_CONNECTION_HPP
|
||||
#define NET_CONNECTION_CLIENT_CONNECTION_HPP
|
||||
|
||||
#include "net/connection/RealmConnection.hpp"
|
||||
#include "net/Types.hpp"
|
||||
|
||||
class RealmResponse;
|
||||
|
||||
class ClientConnection : public RealmConnection {
|
||||
public:
|
||||
// Member variables
|
||||
int32_t m_statusComplete = 1;
|
||||
int32_t m_statusResult = 1;
|
||||
WOWCS_OPS m_statusCop = COP_NONE;
|
||||
int32_t m_errorCode = 0;
|
||||
void (*m_cleanup)() = nullptr;
|
||||
|
||||
// Member functions
|
||||
ClientConnection(RealmResponse* realmResponse)
|
||||
: RealmConnection(realmResponse)
|
||||
{};
|
||||
void Cancel(int32_t errorCode);
|
||||
void Cleanup();
|
||||
void Connect();
|
||||
};
|
||||
|
||||
#endif
|
||||
66
src/net/connection/NetClient.cpp
Normal file
66
src/net/connection/NetClient.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include "net/connection/NetClient.hpp"
|
||||
#include "net/connection/WowConnection.hpp"
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <common/Prop.hpp>
|
||||
#include <storm/Error.hpp>
|
||||
|
||||
HPROPCONTEXT s_propContext;
|
||||
|
||||
int32_t NetClient::s_clientCount;
|
||||
|
||||
void InitializePropContext() {
|
||||
if (PropGetSelectedContext() != s_propContext) {
|
||||
PropSelectContext(s_propContext);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void NetClient::WCDataReady(WowConnection* conn, uint32_t timeStamp, uint8_t* data, int32_t len) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void NetClient::WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) {
|
||||
// TODO
|
||||
}
|
||||
56
src/net/connection/NetClient.hpp
Normal file
56
src/net/connection/NetClient.hpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef NET_CONNECTION_NET_CLIENT_HPP
|
||||
#define NET_CONNECTION_NET_CLIENT_HPP
|
||||
|
||||
#include "net/connection/WowConnectionResponse.hpp"
|
||||
#include "net/Types.hpp"
|
||||
#include <storm/List.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
class CDataStore;
|
||||
class NetClient;
|
||||
class WowConnection;
|
||||
|
||||
typedef int32_t (*MESSAGE_HANDLER)(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
|
||||
|
||||
class NETEVENTQUEUENODE : public TSLinkedNode<NETEVENTQUEUENODE> {
|
||||
public:
|
||||
};
|
||||
|
||||
class NETEVENTQUEUE {
|
||||
public:
|
||||
// Member variables
|
||||
NetClient* m_client;
|
||||
SCritSect m_critSect;
|
||||
STORM_LIST(NETEVENTQUEUENODE) m_eventQueue;
|
||||
|
||||
// Member functions
|
||||
NETEVENTQUEUE(NetClient* client)
|
||||
: m_client(client)
|
||||
{};
|
||||
};
|
||||
|
||||
class NetClient : public WowConnectionResponse {
|
||||
public:
|
||||
// Static variables
|
||||
static int32_t s_clientCount;
|
||||
|
||||
// Member variables
|
||||
NETSTATE m_netState = NS_UNINITIALIZED;
|
||||
MESSAGE_HANDLER m_handlers[NUM_MSG_TYPES];
|
||||
void* m_handlerParams[NUM_MSG_TYPES];
|
||||
NETEVENTQUEUE* m_netEventQueue = nullptr;
|
||||
WowConnection* m_serverConnection = nullptr;
|
||||
|
||||
// Virtual member functions
|
||||
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 void WCDataReady(WowConnection* conn, uint32_t timeStamp, uint8_t* data, int32_t len);
|
||||
|
||||
// Member functions
|
||||
int32_t Initialize();
|
||||
void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param);
|
||||
};
|
||||
|
||||
#endif
|
||||
29
src/net/connection/RealmConnection.cpp
Normal file
29
src/net/connection/RealmConnection.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "net/connection/RealmConnection.hpp"
|
||||
#include "net/Types.hpp"
|
||||
|
||||
int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
RealmConnection::RealmConnection(RealmResponse* realmResponse) {
|
||||
this->m_realmResponse = realmResponse;
|
||||
|
||||
// TODO
|
||||
|
||||
this->Initialize();
|
||||
|
||||
this->SetMessageHandler(SMSG_AUTH_CHALLENGE, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_AUTH_RESPONSE, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_ADDON_INFO, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_ENUM_CHARACTERS_RESULT, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_CREATE_CHAR, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_CHARACTER_LOGIN_FAILED, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_LOGOUT_COMPLETE, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_LOGOUT_CANCEL_ACK, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_LOGOUT_RESPONSE, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_DELETE_CHAR, &RealmConnection::MessageHandler, this);
|
||||
this->SetMessageHandler(SMSG_CACHE_VERSION, &RealmConnection::MessageHandler, this);
|
||||
|
||||
// TODO
|
||||
}
|
||||
22
src/net/connection/RealmConnection.hpp
Normal file
22
src/net/connection/RealmConnection.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef NET_CONNECTION_REALM_CONNECTION_HPP
|
||||
#define NET_CONNECTION_REALM_CONNECTION_HPP
|
||||
|
||||
#include "net/connection/NetClient.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
class CDataStore;
|
||||
class RealmResponse;
|
||||
|
||||
class RealmConnection : public NetClient {
|
||||
public:
|
||||
// Static functions
|
||||
int32_t static MessageHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg);
|
||||
|
||||
// Member variables
|
||||
RealmResponse* m_realmResponse;
|
||||
|
||||
// Member functions
|
||||
RealmConnection(RealmResponse* realmResponse);
|
||||
};
|
||||
|
||||
#endif
|
||||
8
src/net/connection/RealmResponse.hpp
Normal file
8
src/net/connection/RealmResponse.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef NET_CONNECTION_REALM_RESPONSE_HPP
|
||||
#define NET_CONNECTION_REALM_RESPONSE_HPP
|
||||
|
||||
class RealmResponse {
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
||||
591
src/net/connection/WowConnection.cpp
Normal file
591
src/net/connection/WowConnection.cpp
Normal file
|
|
@ -0,0 +1,591 @@
|
|||
#include "net/connection/WowConnection.hpp"
|
||||
#include "net/connection/WowConnectionNet.hpp"
|
||||
#include "net/connection/WowConnectionResponse.hpp"
|
||||
#include <common/Time.hpp>
|
||||
#include <storm/Error.hpp>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
uint64_t WowConnection::s_countTotalBytes;
|
||||
int32_t WowConnection::s_destroyed;
|
||||
WowConnectionNet* WowConnection::s_network;
|
||||
ATOMIC32 WowConnection::s_numWowConnections;
|
||||
bool (*WowConnection::s_verifyAddr)(const NETADDR*);
|
||||
|
||||
int32_t WowConnection::CreateSocket() {
|
||||
int32_t sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// TODO
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int32_t WowConnection::InitOsNet(bool (*fcn)(const NETADDR*), void (*threadinit)(), int32_t numThreads, bool useEngine) {
|
||||
if (!WowConnection::s_network) {
|
||||
// TODO s_usedSocketBits logic
|
||||
// TODO WDataStore::StaticInitialize();
|
||||
|
||||
WowConnection::s_verifyAddr = fcn;
|
||||
WowConnection::s_destroyed = 0;
|
||||
|
||||
numThreads = std::min(numThreads, 32);
|
||||
|
||||
auto networkMem = SMemAlloc(sizeof(WowConnectionNet), __FILE__, __LINE__, 0x0);
|
||||
auto network = new (networkMem) WowConnectionNet(numThreads, threadinit);
|
||||
|
||||
WowConnection::s_network = network;
|
||||
WowConnection::s_network->PlatformInit(useEngine);
|
||||
WowConnection::s_network->Start();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
WowConnection::WowConnection(WowConnectionResponse* response, void (*func)(void)) {
|
||||
// TODO
|
||||
|
||||
this->Init(response, func);
|
||||
|
||||
this->m_sock = -1;
|
||||
}
|
||||
|
||||
WowConnection::WowConnection(int32_t sock, sockaddr_in* addr, WowConnectionResponse* response) {
|
||||
// TODO
|
||||
|
||||
this->Init(response, nullptr);
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_sock = sock;
|
||||
this->m_connState = WOWC_CONNECTED;
|
||||
}
|
||||
|
||||
void WowConnection::AcquireResponseRef() {
|
||||
this->m_responseLock.Enter();
|
||||
|
||||
STORM_ASSERT(this->m_responseRef == 0 || this->GetState() == WOWC_LISTENING);
|
||||
|
||||
this->m_responseRef++;
|
||||
this->m_responseRefThread = SGetCurrentThreadId();
|
||||
|
||||
this->m_responseLock.Leave();
|
||||
}
|
||||
|
||||
void WowConnection::AddRef() {
|
||||
SInterlockedIncrement(&this->m_refCount);
|
||||
}
|
||||
|
||||
void WowConnection::CheckAccept() {
|
||||
for (int32_t i = 0; i < 10000; i++) {
|
||||
NETADDR addr;
|
||||
socklen_t addrLen = sizeof(addr);
|
||||
|
||||
int32_t sock = accept(this->m_sock, reinterpret_cast<sockaddr*>(&addr), &addrLen);
|
||||
if (sock < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (WowConnection::s_verifyAddr) {
|
||||
NETADDR verifyAddr;
|
||||
socklen_t verifyAddrLen = sizeof(verifyAddr);
|
||||
|
||||
getpeername(sock, reinterpret_cast<sockaddr*>(&verifyAddr), &verifyAddrLen);
|
||||
if (!WowConnection::s_verifyAddr(&verifyAddr)) {
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// RegisterSocket(sock);
|
||||
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
|
||||
auto connMem = SMemAlloc(sizeof(WowConnection), __FILE__, __LINE__, 0x0);
|
||||
auto conn = new (connMem) WowConnection(sock, reinterpret_cast<sockaddr_in*>(&addr), this->m_response);
|
||||
conn->AddRef();
|
||||
|
||||
this->AddRef();
|
||||
this->AcquireResponseRef();
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
if (this->m_response) {
|
||||
this->m_response->WCConnected(this, conn, OsGetAsyncTimeMs(), &conn->m_peer);
|
||||
}
|
||||
|
||||
WowConnection::s_network->Add(conn);
|
||||
WowConnection::s_network->PlatformChangeState(conn, conn->GetState());
|
||||
|
||||
conn->Release();
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
this->ReleaseResponseRef();
|
||||
|
||||
this->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnection::CheckConnect() {
|
||||
int32_t err;
|
||||
socklen_t errLen = sizeof(err);
|
||||
if (getsockopt(this->m_sock, SOL_SOCKET, SO_ERROR, &err, &errLen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
WowConnection::s_network->Remove(this);
|
||||
|
||||
WowConnection::CloseSocket(this->m_sock);
|
||||
this->m_sock = -1;
|
||||
|
||||
this->SetState(WOWC_DISCONNECTED);
|
||||
this->AddRef();
|
||||
this->AcquireResponseRef();
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
if (this->m_response) {
|
||||
this->m_response->WCCantConnect(this, OsGetAsyncTimeMsPrecise(), &this->m_peer);
|
||||
}
|
||||
} else {
|
||||
this->SetState(WOWC_CONNECTED);
|
||||
this->AddRef();
|
||||
this->AcquireResponseRef();
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
socklen_t peerLen = sizeof(this->m_peer.peerAddr);
|
||||
getpeername(this->m_sock, reinterpret_cast<sockaddr*>(&this->m_peer.peerAddr), &peerLen);
|
||||
|
||||
socklen_t selfLen = sizeof(this->m_peer.selfAddr);
|
||||
getsockname(this->m_sock, reinterpret_cast<sockaddr*>(&this->m_peer.selfAddr), &selfLen);
|
||||
|
||||
if (this->m_response) {
|
||||
this->m_response->WCConnected(this, nullptr, OsGetAsyncTimeMsPrecise(), &this->m_peer);
|
||||
}
|
||||
}
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
this->ReleaseResponseRef();
|
||||
this->Release();
|
||||
}
|
||||
|
||||
void WowConnection::CloseSocket(int32_t sock) {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
closesocket(sock);
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
if (sock >= 0) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
bool WowConnection::Connect(char const* address, int32_t retryMs) {
|
||||
char host[256];
|
||||
auto port = SStrChr(address, ':');
|
||||
|
||||
if (port) {
|
||||
this->m_connectPort = SStrToInt(port + 1);
|
||||
|
||||
size_t portIndex = port - address + 1;
|
||||
portIndex = std::min(portIndex, sizeof(host));
|
||||
SStrCopy(host, address, portIndex);
|
||||
} else {
|
||||
this->m_connectPort = 0;
|
||||
|
||||
SStrCopy(host, address, sizeof(host));
|
||||
}
|
||||
|
||||
this->Connect(host, this->m_connectPort, retryMs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WowConnection::Connect(char const* address, uint16_t port, int32_t retryMs) {
|
||||
auto connectAddress = inet_addr(address);
|
||||
|
||||
if (connectAddress == -1 || connectAddress == 0) {
|
||||
auto entry = gethostbyname(address);
|
||||
if (entry) {
|
||||
auto addrs = reinterpret_cast<uint8_t**>(entry->h_addr_list);
|
||||
auto addr0 = addrs[0];
|
||||
this->m_connectAddress = addr0[0]
|
||||
| addr0[1] << 8
|
||||
| addr0[2] << 16
|
||||
| addr0[3] << 24;
|
||||
} else {
|
||||
this->m_connectAddress = 0;
|
||||
}
|
||||
} else {
|
||||
this->m_connectAddress = connectAddress;
|
||||
}
|
||||
|
||||
this->m_connectPort = port;
|
||||
|
||||
this->StartConnect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WowConnection::Disconnect() {
|
||||
this->m_lock.Enter();
|
||||
|
||||
if (this->m_sock >= 0 && this->GetState() == WOWC_CONNECTED) {
|
||||
this->m_connState = WOWC_DISCONNECTING;
|
||||
|
||||
if (WowConnection::s_network) {
|
||||
WowConnection::s_network->PlatformChangeState(this, WOWC_CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
this->m_lock.Leave();
|
||||
}
|
||||
|
||||
void WowConnection::DoDisconnect() {
|
||||
this->m_lock.Enter();
|
||||
|
||||
if (this->m_sock >= 0) {
|
||||
WowConnection::s_network->Remove(this);
|
||||
this->CloseSocket(this->m_sock);
|
||||
}
|
||||
|
||||
this->SetState(WOWC_DISCONNECTED);
|
||||
|
||||
this->AddRef();
|
||||
this->AcquireResponseRef();
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
if (this->m_response && this->m_sock >= 0) {
|
||||
// TODO
|
||||
// this->m_response->Vfunc4(this, OsGetAsyncTimeMsPrecise());
|
||||
}
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
this->m_sock = -1;
|
||||
this->ReleaseResponseRef();
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
this->Release();
|
||||
}
|
||||
|
||||
void WowConnection::DoExceptions() {
|
||||
this->AddRef();
|
||||
this->m_lock.Enter();
|
||||
|
||||
if (this->GetState() == WOWC_CONNECTING) {
|
||||
this->CheckConnect();
|
||||
}
|
||||
|
||||
this->m_lock.Leave();
|
||||
this->Release();
|
||||
}
|
||||
|
||||
void WowConnection::DoMessageReads() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnection::DoReads() {
|
||||
this->AddRef();
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
if (this->m_connState == WOWC_LISTENING) {
|
||||
this->CheckAccept();
|
||||
} else if (this->m_connState == WOWC_CONNECTED) {
|
||||
if (this->m_type == WOWC_TYPE_STREAM) {
|
||||
this->DoStreamReads();
|
||||
} else {
|
||||
this->DoMessageReads();
|
||||
}
|
||||
}
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
this->Release();
|
||||
}
|
||||
|
||||
void WowConnection::DoStreamReads() {
|
||||
uint32_t startTime = OsGetAsyncTimeMsPrecise();
|
||||
uint8_t buf[4096];
|
||||
uint32_t bytesRead;
|
||||
|
||||
while (1) {
|
||||
while (1) {
|
||||
bytesRead = recv(this->m_sock, buf, sizeof(buf), 0);
|
||||
|
||||
if (bytesRead >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
if (WSAGetLastError() != WSAEINTR) {
|
||||
break;
|
||||
}
|
||||
#elif defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
if (errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (bytesRead == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
this->AcquireResponseRef();
|
||||
this->m_lock.Leave();
|
||||
|
||||
if (this->m_response) {
|
||||
this->m_response->WCDataReady(this, OsGetAsyncTimeMs(), buf, bytesRead);
|
||||
}
|
||||
|
||||
this->m_lock.Enter();
|
||||
this->ReleaseResponseRef();
|
||||
|
||||
if (this->GetState() == WOWC_DISCONNECTING || (OsGetAsyncTimeMsPrecise() - startTime) >= 5) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldDisconnect = false;
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
shouldDisconnect = bytesRead >= 0 || WSAGetLastError() != WSAEAGAIN;
|
||||
#elif defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
shouldDisconnect = bytesRead >= 0 || errno != EAGAIN;
|
||||
#endif
|
||||
|
||||
if (shouldDisconnect) {
|
||||
this->AcquireResponseRef();
|
||||
|
||||
WowConnection::s_network->Remove(this);
|
||||
this->CloseSocket(this->m_sock);
|
||||
this->SetState(WOWC_DISCONNECTED);
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
if (this->m_response && this->m_sock >= 0) {
|
||||
this->m_response->WCDisconnected(this, OsGetAsyncTimeMs(), &this->m_peer);
|
||||
}
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
this->m_sock = -1;
|
||||
|
||||
this->ReleaseResponseRef();
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnection::DoWrites() {
|
||||
this->AddRef();
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
if (this->m_connState == WOWC_CONNECTING) {
|
||||
this->CheckConnect();
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
this->Release();
|
||||
}
|
||||
|
||||
WOW_CONN_STATE WowConnection::GetState() {
|
||||
return this->m_connState;
|
||||
}
|
||||
|
||||
void WowConnection::Init(WowConnectionResponse* response, void (*func)(void)) {
|
||||
SInterlockedIncrement(&WowConnection::s_numWowConnections);
|
||||
|
||||
this->m_refCount = 1;
|
||||
this->m_responseRef = 0;
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_connState = WOWC_UNINITIALIZED;
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_response = response;
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_connectAddress = 0;
|
||||
this->m_connectPort = 0;
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_serviceFlags = 0x0;
|
||||
this->m_serviceCount = 0;
|
||||
|
||||
// TODO
|
||||
|
||||
this->SetState(WOWC_INITIALIZED);
|
||||
this->m_type = WOWC_TYPE_MESSAGES;
|
||||
}
|
||||
|
||||
void WowConnection::Release() {
|
||||
if (SInterlockedDecrement(&this->m_refCount) <= 0) {
|
||||
if (WowConnection::s_network) {
|
||||
WowConnection::s_network->Delete(this);
|
||||
} else {
|
||||
// TODO SMemFree
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnection::ReleaseResponseRef() {
|
||||
this->m_responseLock.Enter();
|
||||
|
||||
STORM_ASSERT(this->m_responseRef > 0);
|
||||
|
||||
this->m_responseRef--;
|
||||
|
||||
// TODO
|
||||
// dwordD4 = (void *)this->dwordD4;
|
||||
// if (dwordD4) {
|
||||
// this->m_response = dwordD4;
|
||||
// this->dwordD4 = 0;
|
||||
// }
|
||||
|
||||
this->m_responseLock.Leave();
|
||||
}
|
||||
|
||||
WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
|
||||
WowConnection::s_countTotalBytes += len;
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
// TODO
|
||||
|
||||
if (len > 0 && this->m_connState == WOWC_CONNECTED) {
|
||||
STORM_ASSERT(this->m_sock >= 0);
|
||||
|
||||
#if defined (WHOA_SYSTEM_WIN)
|
||||
// TODO
|
||||
#elif defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
if (this->m_sendList.Head()) {
|
||||
// TODO
|
||||
} else {
|
||||
auto written = write(this->m_sock, data, len);
|
||||
|
||||
if (written <= 0) {
|
||||
// TODO
|
||||
} else if (written == len) {
|
||||
this->m_lock.Leave();
|
||||
return WC_SEND_SENT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
this->m_lock.Leave();
|
||||
|
||||
return WC_SEND_ERROR;
|
||||
}
|
||||
|
||||
void WowConnection::SetState(WOW_CONN_STATE state) {
|
||||
WOW_CONN_STATE oldState = this->m_connState;
|
||||
this->m_connState = state;
|
||||
|
||||
if (WowConnection::s_network) {
|
||||
WowConnection::s_network->PlatformChangeState(this, oldState);
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnection::SetType(WOWC_TYPE type) {
|
||||
this->m_lock.Enter();
|
||||
this->m_type = type;
|
||||
this->m_lock.Leave();
|
||||
}
|
||||
|
||||
void WowConnection::StartConnect() {
|
||||
if (this->m_sock >= 0) {
|
||||
if (this->m_netlink.IsLinked()) {
|
||||
WowConnection::s_network->Remove(this);
|
||||
}
|
||||
|
||||
this->CloseSocket(this->m_sock);
|
||||
this->m_sock = -1;
|
||||
}
|
||||
|
||||
this->m_lock.Enter();
|
||||
|
||||
this->m_sock = WowConnection::CreateSocket();
|
||||
|
||||
if (this->m_sock < 0) {
|
||||
this->SetState(WOWC_ERROR);
|
||||
this->m_lock.Leave();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
fcntl(this->m_sock, F_SETFL, O_NONBLOCK);
|
||||
|
||||
uint32_t opt = 1;
|
||||
setsockopt(this->m_sock, SOL_SOCKET, 4130, &opt, sizeof(opt));
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(this->m_connectPort);
|
||||
addr.sin_addr.s_addr = this->m_connectAddress;
|
||||
|
||||
if (!this->m_netlink.IsLinked()) {
|
||||
WowConnection::s_network->Add(this);
|
||||
}
|
||||
|
||||
this->SetState(WOWC_CONNECTING);
|
||||
|
||||
if (connect(this->m_sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) >= 0) {
|
||||
this->m_lock.Leave();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) {
|
||||
this->m_lock.Leave();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WowConnection::s_network->Remove(this);
|
||||
this->CloseSocket(this->m_sock);
|
||||
this->m_sock = -1;
|
||||
|
||||
this->SetState(WOWC_ERROR);
|
||||
|
||||
this->m_lock.Leave();
|
||||
#endif
|
||||
}
|
||||
87
src/net/connection/WowConnection.hpp
Normal file
87
src/net/connection/WowConnection.hpp
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef NET_CONNECTION_WOW_CONNECTION_HPP
|
||||
#define NET_CONNECTION_WOW_CONNECTION_HPP
|
||||
|
||||
#include "net/Types.hpp"
|
||||
#include <cstdint>
|
||||
#include <storm/Atomic.hpp>
|
||||
#include <storm/List.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
class WowConnectionNet;
|
||||
class WowConnectionResponse;
|
||||
|
||||
class WowConnection {
|
||||
public:
|
||||
// Types
|
||||
struct SENDNODE : public TSLinkedNode<SENDNODE> {
|
||||
uint8_t* data;
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
uint32_t datasize;
|
||||
};
|
||||
|
||||
// Static variables
|
||||
static uint64_t s_countTotalBytes;
|
||||
static int32_t s_destroyed;
|
||||
static WowConnectionNet* s_network;
|
||||
static ATOMIC32 s_numWowConnections;
|
||||
static bool (*s_verifyAddr)(const NETADDR*);
|
||||
|
||||
// Static functions
|
||||
static int32_t CreateSocket();
|
||||
static int32_t InitOsNet(bool (*fcn)(const NETADDR*), void (*threadinit)(), int32_t numThreads, bool useEngine);
|
||||
|
||||
// Member variables
|
||||
ATOMIC32 m_refCount;
|
||||
int32_t m_sock;
|
||||
WOW_CONN_STATE m_connState;
|
||||
WowConnectionResponse* m_response;
|
||||
uint32_t m_connectAddress;
|
||||
uint16_t m_connectPort;
|
||||
NETCONNADDR m_peer;
|
||||
SCritSect m_responseLock;
|
||||
int32_t m_responseRef;
|
||||
uintptr_t m_responseRefThread;
|
||||
STORM_LIST(SENDNODE) m_sendList;
|
||||
uint32_t m_serviceFlags;
|
||||
TSLink<WowConnection> m_netlink;
|
||||
SCritSect m_lock;
|
||||
ATOMIC32 m_serviceCount;
|
||||
WOWC_TYPE m_type;
|
||||
|
||||
// Member functions
|
||||
WowConnection(WowConnectionResponse* response, void (*func)(void));
|
||||
WowConnection(int32_t sock, sockaddr_in* addr, WowConnectionResponse* response);
|
||||
void AcquireResponseRef();
|
||||
void AddRef();
|
||||
void CheckAccept();
|
||||
void CheckConnect();
|
||||
void CloseSocket(int32_t sock);
|
||||
bool Connect(char const* address, int32_t retryMs);
|
||||
bool Connect(char const* address, uint16_t port, int32_t retryMs);
|
||||
void Disconnect();
|
||||
void DoDisconnect();
|
||||
void DoExceptions();
|
||||
void DoMessageReads();
|
||||
void DoReads();
|
||||
void DoStreamReads();
|
||||
void DoWrites();
|
||||
WOW_CONN_STATE GetState();
|
||||
void Init(WowConnectionResponse* response, void (*func)(void));
|
||||
void Release();
|
||||
void ReleaseResponseRef();
|
||||
WC_SEND_RESULT SendRaw(uint8_t* data, int32_t len, bool a4);
|
||||
void SetState(WOW_CONN_STATE state);
|
||||
void SetType(WOWC_TYPE type);
|
||||
void StartConnect();
|
||||
};
|
||||
|
||||
#endif
|
||||
166
src/net/connection/WowConnectionNet.cpp
Normal file
166
src/net/connection/WowConnectionNet.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#include "net/connection/WowConnectionNet.hpp"
|
||||
#include "net/connection/WowConnection.hpp"
|
||||
#include <storm/Atomic.hpp>
|
||||
#include <storm/Error.hpp>
|
||||
#include <storm/String.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
|
||||
uint32_t MainProc(void* param) {
|
||||
auto network = static_cast<WowConnectionNet*>(param);
|
||||
network->Run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t WorkerProc(void* param) {
|
||||
auto worker = static_cast<WowConnectionNet::Worker*>(param);
|
||||
worker->owner->RunWorker(worker->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WowConnectionNet::Add(WowConnection* connection) {
|
||||
this->m_connectionsLock.Enter();
|
||||
|
||||
if (!this->m_connections.IsLinked(connection)) {
|
||||
this->m_connections.LinkToTail(connection);
|
||||
this->PlatformAdd(connection);
|
||||
}
|
||||
|
||||
this->m_connectionsLock.Leave();
|
||||
}
|
||||
|
||||
void WowConnectionNet::Delete(WowConnection* connection) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::Remove(WowConnection* connection) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::Run() {
|
||||
this->PlatformRun();
|
||||
this->m_stopEvent.Set();
|
||||
}
|
||||
|
||||
void WowConnectionNet::RunWorker(int32_t id) {
|
||||
if (this->m_threadinit) {
|
||||
this->m_threadinit();
|
||||
}
|
||||
|
||||
this->m_workerSem.Signal(1);
|
||||
|
||||
auto& worker = this->m_workers[id];
|
||||
|
||||
while (true) {
|
||||
do {
|
||||
// TODO worker.time40 = OsGetAsyncTimeMsPrecise();
|
||||
} while (worker.event.Wait(1000));
|
||||
|
||||
if (worker.quit) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto serviceConn = worker.serviceConn;
|
||||
auto serviceFlags = serviceConn->m_serviceFlags;
|
||||
serviceConn->m_serviceFlags = 0;
|
||||
|
||||
this->Service(worker.serviceConn, serviceFlags);
|
||||
|
||||
worker.lock.Enter();
|
||||
|
||||
SInterlockedDecrement(&serviceConn->m_serviceCount);
|
||||
serviceConn->Release();
|
||||
worker.serviceConn = nullptr;
|
||||
|
||||
worker.lock.Leave();
|
||||
|
||||
this->m_workerSem.Signal(1);
|
||||
this->PlatformWorkerReady();
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnectionNet::Service(WowConnection* connection, uint32_t serviceFlags) {
|
||||
while (serviceFlags) {
|
||||
if (serviceFlags & 0x1) {
|
||||
connection->DoWrites();
|
||||
}
|
||||
|
||||
if (serviceFlags & 0x2) {
|
||||
connection->DoReads();
|
||||
}
|
||||
|
||||
if (serviceFlags & 0x4) {
|
||||
connection->DoExceptions();
|
||||
}
|
||||
|
||||
if (serviceFlags & 0x8) {
|
||||
connection->DoDisconnect();
|
||||
}
|
||||
|
||||
this->m_connectionsLock.Enter();
|
||||
|
||||
serviceFlags = connection->m_serviceFlags;
|
||||
connection->m_serviceFlags = 0;
|
||||
|
||||
this->m_connectionsLock.Leave();
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnectionNet::SignalWorker(WowConnection* connection, uint32_t flags) {
|
||||
if (!this->m_workerSem.Wait(500)) {
|
||||
connection->AddRef();
|
||||
connection->m_serviceFlags = flags;
|
||||
SInterlockedIncrement(&connection->m_serviceCount);
|
||||
|
||||
int32_t i = 0;
|
||||
while (1) {
|
||||
this->m_workers[i].lock.Enter();
|
||||
|
||||
if (!this->m_workers[i].serviceConn) {
|
||||
break;
|
||||
}
|
||||
|
||||
STORM_ASSERT(this->m_workers[i].serviceConn != connection);
|
||||
|
||||
this->m_workers[i].lock.Leave();
|
||||
|
||||
i++;
|
||||
|
||||
STORM_ASSERT(i < this->m_numWorkers);
|
||||
}
|
||||
|
||||
this->m_workers[i].serviceConn = connection;
|
||||
this->m_workers[i].lock.Leave();
|
||||
this->m_workers[i].event.Set();
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnectionNet::Start() {
|
||||
for (int32_t i = 0; i < this->m_numWorkers; i++) {
|
||||
auto worker = &this->m_workers[i];
|
||||
|
||||
worker->id = i;
|
||||
worker->serviceConn = nullptr;
|
||||
worker->quit = 0;
|
||||
worker->owner = this;
|
||||
// TODO worker.time40 = OsGetAsyncTimeMsPrecise();
|
||||
|
||||
char name[32];
|
||||
SStrPrintf(name, sizeof(name), "NetThread %d", i);
|
||||
|
||||
SThread::Create(&WorkerProc, worker, worker->thread, name, 0);
|
||||
}
|
||||
|
||||
char name[32];
|
||||
SStrPrintf(name, sizeof(name), "Network");
|
||||
|
||||
// TODO BYTE1(this->dword8EC) = 0;
|
||||
|
||||
SThread::Create(&MainProc, this, this->m_thread, name, 0);
|
||||
|
||||
// TODO
|
||||
// while (!BYTE1(this->dword8EC)) {
|
||||
// OsSleep(100);
|
||||
// }
|
||||
}
|
||||
55
src/net/connection/WowConnectionNet.hpp
Normal file
55
src/net/connection/WowConnectionNet.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef NET_CONNECTION_WOW_CONNECTION_NET_HPP
|
||||
#define NET_CONNECTION_WOW_CONNECTION_NET_HPP
|
||||
|
||||
#include "net/connection/WowConnection.hpp"
|
||||
#include <cstdint>
|
||||
#include <storm/List.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
|
||||
class WowConnectionNet {
|
||||
public:
|
||||
// Types
|
||||
struct Worker {
|
||||
WowConnectionNet* owner;
|
||||
SThread thread;
|
||||
int32_t id;
|
||||
WowConnection* serviceConn;
|
||||
SEvent event = SEvent(0, 0);
|
||||
int8_t quit;
|
||||
SCritSect lock;
|
||||
};
|
||||
|
||||
// Member variables
|
||||
SThread m_thread;
|
||||
SEvent m_stopEvent = SEvent(1, 0);
|
||||
uint8_t m_stop;
|
||||
int32_t m_numWorkers;
|
||||
Worker m_workers[32];
|
||||
SCritSect m_connectionsLock;
|
||||
STORM_EXPLICIT_LIST(WowConnection, m_netlink) m_connections;
|
||||
SSemaphore m_workerSem;
|
||||
void (*m_threadinit)();
|
||||
|
||||
// Member functions
|
||||
WowConnectionNet(uint32_t numThreads, void (*threadinit)())
|
||||
: m_workerSem(0, numThreads)
|
||||
, m_numWorkers(numThreads)
|
||||
, m_threadinit(threadinit)
|
||||
, m_stop(0)
|
||||
{};
|
||||
void Add(WowConnection* connection);
|
||||
void Delete(WowConnection* connection);
|
||||
void PlatformAdd(WowConnection* connection);
|
||||
void PlatformChangeState(WowConnection* connection, WOW_CONN_STATE state);
|
||||
void PlatformInit(bool useEngine);
|
||||
void PlatformRun();
|
||||
void PlatformWorkerReady();
|
||||
void Remove(WowConnection* connection);
|
||||
void Run();
|
||||
void RunWorker(int32_t id);
|
||||
void Service(WowConnection* connection, uint32_t serviceFlags);
|
||||
void SignalWorker(WowConnection* connection, uint32_t flags);
|
||||
void Start();
|
||||
};
|
||||
|
||||
#endif
|
||||
175
src/net/connection/WowConnectionNetMac.cpp
Normal file
175
src/net/connection/WowConnectionNetMac.cpp
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
|
||||
#include "net/connection/WowConnectionNet.hpp"
|
||||
#include "net/connection/WowConnection.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <storm/Array.hpp>
|
||||
|
||||
int32_t s_workerPipe[2];
|
||||
|
||||
void WowConnectionNet::PlatformAdd(WowConnection* connection) {
|
||||
uint32_t on = 1;
|
||||
setsockopt(connection->m_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
|
||||
|
||||
char buf = '\1';
|
||||
write(s_workerPipe[1], &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformChangeState(WowConnection* connection, WOW_CONN_STATE state) {
|
||||
char buf = '\1';
|
||||
write(s_workerPipe[1], &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformInit(bool useEngine) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformRun() {
|
||||
pipe(s_workerPipe);
|
||||
|
||||
if (fcntl(s_workerPipe[0], F_SETFL, O_NONBLOCK) < 0) {
|
||||
perror("fcntl(worker pipe)");
|
||||
}
|
||||
|
||||
TSGrowableArray<WowConnection*> connections;
|
||||
char buf[25];
|
||||
|
||||
while (!this->m_stop) {
|
||||
timeval timeout = { 30, 0 };
|
||||
|
||||
fd_set readFds = {};
|
||||
fd_set writeFds = {};
|
||||
fd_set errorFds = {};
|
||||
|
||||
readFds.fds_bits[s_workerPipe[0] >> 5] |= 1 << (s_workerPipe[0] & 0x1F);
|
||||
|
||||
auto fdCount = s_workerPipe[0];
|
||||
|
||||
int32_t v39 = 0;
|
||||
int32_t v41 = 0;
|
||||
|
||||
this->m_connectionsLock.Enter();
|
||||
|
||||
for (auto connection = this->m_connections.Head(); connection; connection = this->m_connections.Link(connection)->Next()) {
|
||||
if (connection->m_serviceCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (connection->m_connState) {
|
||||
case WOWC_CONNECTING: {
|
||||
errorFds.fds_bits[connection->m_sock >> 5] |= 1 << (connection->m_sock & 0x1F);
|
||||
writeFds.fds_bits[connection->m_sock >> 5] |= 1 << (connection->m_sock & 0x1F);
|
||||
|
||||
connections.Add(1, &connection);
|
||||
connection->AddRef();
|
||||
fdCount = std::max(fdCount, connection->m_sock);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WOWC_LISTENING: {
|
||||
readFds.fds_bits[connection->m_sock >> 5] |= 1 << (connection->m_sock & 0x1F);
|
||||
|
||||
connections.Add(1, &connection);
|
||||
connection->AddRef();
|
||||
fdCount = std::max(fdCount, connection->m_sock);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WOWC_CONNECTED: {
|
||||
readFds.fds_bits[connection->m_sock >> 5] |= 1 << (connection->m_sock & 0x1F);
|
||||
errorFds.fds_bits[connection->m_sock >> 5] |= 1 << (connection->m_sock & 0x1F);
|
||||
|
||||
// TODO
|
||||
|
||||
connections.Add(1, &connection);
|
||||
connection->AddRef();
|
||||
fdCount = std::max(fdCount, connection->m_sock);
|
||||
}
|
||||
|
||||
case WOWC_DISCONNECTING: {
|
||||
// TODO
|
||||
|
||||
v41++;
|
||||
connections.Add(1, &connection);
|
||||
connection->AddRef();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->m_connectionsLock.Leave();
|
||||
|
||||
if (v41 > 0) {
|
||||
timeout = { 0, 0 };
|
||||
}
|
||||
|
||||
if (connections.Count() > 0) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
select(fdCount + 1, &readFds, &writeFds, &errorFds, &timeout);
|
||||
|
||||
auto v1 = s_workerPipe[0];
|
||||
if (((1 << (s_workerPipe[0] & 0x1F)) & readFds.fds_bits[s_workerPipe[0] >> 5]) != 0) {
|
||||
while (read(v1, buf, 1u) > 0) {
|
||||
v1 = s_workerPipe[0];
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < connections.Count(); i++) {
|
||||
auto connection = connections[i];
|
||||
uint32_t signalFlags = 0x0;
|
||||
|
||||
if (!(connection->m_sock & 0x80000000)) {
|
||||
if (FD_ISSET(connection->m_sock, &writeFds)) {
|
||||
signalFlags |= 0x1;
|
||||
}
|
||||
|
||||
if (FD_ISSET(connection->m_sock, &readFds)) {
|
||||
signalFlags |= 0x2;
|
||||
}
|
||||
|
||||
if (FD_ISSET(connection->m_sock, &errorFds)) {
|
||||
signalFlags |= 0x4;
|
||||
}
|
||||
}
|
||||
|
||||
if (connection->m_connState == WOWC_DISCONNECTING) {
|
||||
signalFlags |= 0x8;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// auto v15 = connection->dword10C;
|
||||
// if (!(v15 & 1) && v15) {
|
||||
// signalFlags |= 0x2;
|
||||
// }
|
||||
|
||||
if (signalFlags) {
|
||||
this->SignalWorker(connection, signalFlags);
|
||||
}
|
||||
|
||||
connection->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformWorkerReady() {
|
||||
char buf = '\1';
|
||||
write(s_workerPipe[1], &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
#endif
|
||||
25
src/net/connection/WowConnectionNetWin.cpp
Normal file
25
src/net/connection/WowConnectionNetWin.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#if defined(WHOA_SYSTEM_WIN)
|
||||
|
||||
#include "net/connection/WowConnectionNet.hpp"
|
||||
|
||||
void WowConnectionNet::PlatformAdd(WowConnection* connection) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformChangeState(WowConnection* connection, WOW_CONN_STATE state) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformInit(bool useEngine) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformRun() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WowConnectionNet::PlatformWorkerReady() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#endif
|
||||
17
src/net/connection/WowConnectionResponse.hpp
Normal file
17
src/net/connection/WowConnectionResponse.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef NET_CONNECTION_WOW_CONNECTION_RESPONSE_HPP
|
||||
#define NET_CONNECTION_WOW_CONNECTION_RESPONSE_HPP
|
||||
|
||||
#include "net/Types.hpp"
|
||||
|
||||
class WowConnection;
|
||||
|
||||
class WowConnectionResponse {
|
||||
public:
|
||||
// Virtual member functions
|
||||
virtual void WCConnected(WowConnection* conn, WowConnection* inbound, uint32_t timeStamp, const NETCONNADDR* addr) = 0;
|
||||
virtual void WCCantConnect(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) = 0;
|
||||
virtual void WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) {};
|
||||
virtual void WCDataReady(WowConnection* conn, uint32_t timeStamp, uint8_t* data, int32_t len) {};
|
||||
};
|
||||
|
||||
#endif
|
||||
165
src/net/grunt/ClientLink.cpp
Normal file
165
src/net/grunt/ClientLink.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include "net/grunt/ClientLink.hpp"
|
||||
#include "net/connection/WowConnection.hpp"
|
||||
#include "net/grunt/ClientResponse.hpp"
|
||||
#include <new>
|
||||
#include <common/DataStore.hpp>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
|
||||
Grunt::ClientLink::ClientLink(Grunt::ClientResponse& clientResponse) {
|
||||
// TODO
|
||||
|
||||
this->m_clientResponse = &clientResponse;
|
||||
|
||||
this->SetState(0);
|
||||
|
||||
if (this->m_timer.m_thread.Valid()) {
|
||||
this->m_interval = 100;
|
||||
this->m_timer.Insert(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::Call() {
|
||||
// TODO
|
||||
// this->CheckExpired(false);
|
||||
|
||||
this->m_critSect.Enter();
|
||||
|
||||
if (this->m_state == 2) {
|
||||
this->m_clientResponse->GetLogonMethod();
|
||||
} else if (this->m_state == 6 && !this->m_clientResponse->OnlineIdle()) {
|
||||
this->Disconnect();
|
||||
}
|
||||
|
||||
this->m_critSect.Leave();
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::Connect(const char* a2) {
|
||||
if (this->m_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->SetState(1);
|
||||
|
||||
auto connectionMem = SMemAlloc(sizeof(WowConnection), __FILE__, __LINE__, 0x0);
|
||||
auto connection = new (connectionMem) WowConnection(this, nullptr);
|
||||
|
||||
this->m_connection = connection;
|
||||
this->m_connection->SetType(WOWC_TYPE_STREAM);
|
||||
|
||||
auto port = SStrChr(a2, ':');
|
||||
if (port) {
|
||||
this->m_connection->Connect(a2, 5000);
|
||||
} else {
|
||||
this->m_connection->Connect(a2, 3724, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::Disconnect() {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
if (this->m_connection) {
|
||||
this->m_connection->Disconnect();
|
||||
}
|
||||
|
||||
this->m_critSect.Leave();
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::LogonNewSession(const Grunt::ClientLink::Logon& logon) {
|
||||
this->SetState(3);
|
||||
|
||||
SStrCopy(this->m_accountName, logon.accountName, sizeof(this->m_accountName));
|
||||
SStrUpper(this->m_accountName);
|
||||
|
||||
char* password = static_cast<char*>(alloca(SStrLen(logon.password) + 1));
|
||||
SStrCopy(password, logon.password, STORM_MAX_STR);
|
||||
SStrUpper(password);
|
||||
|
||||
static char accountNameUnDecorated[1280];
|
||||
SStrCopy(accountNameUnDecorated, this->m_accountName, STORM_MAX_STR);
|
||||
auto decoration = const_cast<char*>(SStrChr(accountNameUnDecorated, '#'));
|
||||
if (decoration) {
|
||||
*decoration = '\0';
|
||||
}
|
||||
|
||||
// TODO SRP6_Client::BeginAuthentication
|
||||
|
||||
CDataStoreCache<1024> clientChallenge;
|
||||
|
||||
uint8_t opcode = 0;
|
||||
clientChallenge.Put(opcode);
|
||||
|
||||
uint8_t protocol = 8;
|
||||
clientChallenge.Put(protocol);
|
||||
|
||||
this->PackLogon(clientChallenge, logon);
|
||||
clientChallenge.Finalize();
|
||||
|
||||
this->Send(clientChallenge);
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::PackLogon(CDataStore& msg, const Logon& logon) {
|
||||
uint32_t startPos = msg.m_size;
|
||||
uint16_t tmpSize = 0;
|
||||
msg.Put(tmpSize);
|
||||
|
||||
msg.Put(logon.programID);
|
||||
msg.Put(logon.version[0]);
|
||||
msg.Put(logon.version[1]);
|
||||
msg.Put(logon.version[2]);
|
||||
msg.Put(logon.build);
|
||||
msg.Put(logon.processorID);
|
||||
msg.Put(logon.osID);
|
||||
msg.Put(logon.locale);
|
||||
msg.Put(logon.tz);
|
||||
|
||||
msg.Put(this->m_clientIP);
|
||||
|
||||
uint32_t accountNameLen = SStrLen(this->m_accountName);
|
||||
msg.Put(accountNameLen);
|
||||
msg.PutData(this->m_accountName, accountNameLen);
|
||||
|
||||
msg.Set(startPos, msg.m_size - startPos - 2);
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::Send(CDataStore& msg) {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
if (this->m_connection) {
|
||||
void* data;
|
||||
msg.GetDataInSitu(data, msg.m_size);
|
||||
|
||||
this->m_connection->SendRaw(static_cast<uint8_t*>(data), msg.m_size, false);
|
||||
}
|
||||
|
||||
this->m_critSect.Leave();
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::SetState(int32_t state) {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
this->m_state = state;
|
||||
|
||||
this->m_critSect.Leave();
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::WCCantConnect(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Grunt::ClientLink::WCConnected(WowConnection* conn, WowConnection* inbound, uint32_t timeStamp, const NETCONNADDR* addr) {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
this->SetState(2);
|
||||
|
||||
int32_t connected = this->m_clientResponse->Connected(addr->peerAddr);
|
||||
|
||||
// TODO
|
||||
// this->m_clientIP = OsNetAddrGetAddress(&addr->selfAddr, 0);
|
||||
|
||||
this->m_critSect.Leave();
|
||||
|
||||
if (!connected) {
|
||||
this->Disconnect();
|
||||
}
|
||||
}
|
||||
54
src/net/grunt/ClientLink.hpp
Normal file
54
src/net/grunt/ClientLink.hpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef NET_GRUNT_CLIENT_LINK_HPP
|
||||
#define NET_GRUNT_CLIENT_LINK_HPP
|
||||
|
||||
#include "net/grunt/Grunt.hpp"
|
||||
#include "net/connection/WowConnectionResponse.hpp"
|
||||
#include "net/grunt/Pending.hpp"
|
||||
#include "net/grunt/Timer.hpp"
|
||||
#include "net/Types.hpp"
|
||||
#include <storm/Thread.hpp>
|
||||
|
||||
class CDataStore;
|
||||
class WowConnection;
|
||||
|
||||
class Grunt::ClientLink : public WowConnectionResponse, Grunt::Pending, Grunt::Timer::Event {
|
||||
public:
|
||||
// Types
|
||||
struct Logon {
|
||||
const char* accountName;
|
||||
const char* password;
|
||||
uint32_t programID;
|
||||
uint32_t processorID;
|
||||
uint32_t osID;
|
||||
uint8_t version[4];
|
||||
uint16_t build;
|
||||
uint16_t uint1A;
|
||||
uint32_t locale;
|
||||
uint32_t tz;
|
||||
};
|
||||
|
||||
// Member variables
|
||||
Grunt::Timer m_timer;
|
||||
uint32_t m_clientIP = 0;
|
||||
int32_t m_state;
|
||||
SCritSect m_critSect;
|
||||
WowConnection* m_connection = nullptr;
|
||||
ClientResponse* m_clientResponse;
|
||||
char m_accountName[1280];
|
||||
|
||||
// Virtual member functions
|
||||
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 Call();
|
||||
|
||||
// Member functions
|
||||
ClientLink(Grunt::ClientResponse& clientResponse);
|
||||
void Connect(const char* a2);
|
||||
void Disconnect();
|
||||
void LogonNewSession(const Logon& logon);
|
||||
void PackLogon(CDataStore& msg, const Logon& logon);
|
||||
void Send(CDataStore& msg);
|
||||
void SetState(int32_t state);
|
||||
};
|
||||
|
||||
#endif
|
||||
20
src/net/grunt/ClientResponse.hpp
Normal file
20
src/net/grunt/ClientResponse.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef NET_GRUNT_CLIENT_RESPONSE_HPP
|
||||
#define NET_GRUNT_CLIENT_RESPONSE_HPP
|
||||
|
||||
#include "net/grunt/Grunt.hpp"
|
||||
#include "net/Types.hpp"
|
||||
|
||||
class LoginResponse;
|
||||
|
||||
class Grunt::ClientResponse {
|
||||
public:
|
||||
virtual bool Connected(const NETADDR& addr) = 0;
|
||||
virtual bool OnlineIdle() = 0;
|
||||
virtual void GetLogonMethod() = 0;
|
||||
virtual void GetRealmList() = 0;
|
||||
virtual void Logon(const char* a2, const char* a3) = 0;
|
||||
virtual void Logoff() = 0;
|
||||
virtual void Init(LoginResponse* loginResponse) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
11
src/net/grunt/Grunt.hpp
Normal file
11
src/net/grunt/Grunt.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef NET_GRUNT_GRUNT_HPP
|
||||
#define NET_GRUNT_GRUNT_HPP
|
||||
|
||||
namespace Grunt {
|
||||
class ClientLink;
|
||||
class ClientResponse;
|
||||
class Pending;
|
||||
class Timer;
|
||||
}
|
||||
|
||||
#endif
|
||||
10
src/net/grunt/Pending.hpp
Normal file
10
src/net/grunt/Pending.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef NET_GRUNT_PENDING_HPP
|
||||
#define NET_GRUNT_PENDING_HPP
|
||||
|
||||
#include "net/Grunt.hpp"
|
||||
|
||||
class Grunt::Pending {
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
||||
70
src/net/grunt/Timer.cpp
Normal file
70
src/net/grunt/Timer.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include "net/grunt/Timer.hpp"
|
||||
#include <common/Time.hpp>
|
||||
|
||||
uint32_t Grunt::Timer::ThreadProc(void* param) {
|
||||
auto timer = static_cast<Timer*>(param);
|
||||
|
||||
while (true) {
|
||||
auto timeout = timer->Pump();
|
||||
|
||||
if (timer->m_event.Wait(timeout) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Grunt::Timer::Timer() {
|
||||
SThread::Create(Grunt::Timer::ThreadProc, this, this->m_thread, "GruntTimerEvt", 0);
|
||||
}
|
||||
|
||||
void Grunt::Timer::Insert(Grunt::Timer::Event& newEvent) {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
newEvent.m_schedTime = OsGetAsyncTimeMsPrecise() + newEvent.m_interval;
|
||||
|
||||
for (auto event = this->m_eventList.Head(); event; event = this->m_eventList.Link(event)->Next()) {
|
||||
// Keep event listed sorted by scheduled time
|
||||
if (newEvent.m_schedTime - event->m_schedTime < 0) {
|
||||
this->m_eventList.LinkNode(&newEvent, 2, event);
|
||||
|
||||
this->m_critSect.Leave();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_eventList.LinkToTail(&newEvent);
|
||||
|
||||
this->m_critSect.Leave();
|
||||
}
|
||||
|
||||
uint32_t Grunt::Timer::Pump() {
|
||||
this->m_critSect.Enter();
|
||||
|
||||
auto* event = this->m_eventList.Head();
|
||||
|
||||
if (!event) {
|
||||
this->m_critSect.Leave();
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
int32_t timeUntilSched = event->m_schedTime - OsGetAsyncTimeMsPrecise();
|
||||
|
||||
if (timeUntilSched <= 0) {
|
||||
this->m_eventList.UnlinkNode(event);
|
||||
|
||||
this->m_critSect.Leave();
|
||||
|
||||
event->Call();
|
||||
this->Insert(*event);
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
this->m_critSect.Leave();
|
||||
|
||||
return timeUntilSched;
|
||||
}
|
||||
37
src/net/grunt/Timer.hpp
Normal file
37
src/net/grunt/Timer.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef NET_GRUNT_TIMER_HPP
|
||||
#define NET_GRUNT_TIMER_HPP
|
||||
|
||||
#include "net/grunt/Grunt.hpp"
|
||||
#include "storm/List.hpp"
|
||||
#include "storm/Thread.hpp"
|
||||
|
||||
class Grunt::Timer {
|
||||
public:
|
||||
// Types
|
||||
class Event {
|
||||
public:
|
||||
// Member variables
|
||||
TSLink<Event> m_link;
|
||||
uint32_t m_schedTime;
|
||||
uint32_t m_interval;
|
||||
|
||||
// Virtual methods
|
||||
virtual void Call() = 0;
|
||||
};
|
||||
|
||||
// Static functions
|
||||
static uint32_t ThreadProc(void* param);
|
||||
|
||||
// Member variables
|
||||
SEvent m_event = SEvent(0, 0);
|
||||
SThread m_thread;
|
||||
SCritSect m_critSect;
|
||||
STORM_EXPLICIT_LIST(Event, m_link) m_eventList;
|
||||
|
||||
// Member functions
|
||||
Timer();
|
||||
void Insert(Event&);
|
||||
uint32_t Pump();
|
||||
};
|
||||
|
||||
#endif
|
||||
10
src/net/login/BattlenetLogin.hpp
Normal file
10
src/net/login/BattlenetLogin.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef NET_LOGIN_BATTLENET_LOGIN_HPP
|
||||
#define NET_LOGIN_BATTLENET_LOGIN_HPP
|
||||
|
||||
#include "net/login/Login.hpp"
|
||||
|
||||
class BattlenetLogin : public Login {
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
||||
126
src/net/login/GruntLogin.cpp
Normal file
126
src/net/login/GruntLogin.cpp
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include "net/login/GruntLogin.hpp"
|
||||
#include "net/grunt/ClientLink.hpp"
|
||||
#include "net/login/LoginResponse.hpp"
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
|
||||
GruntLogin::~GruntLogin() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool GruntLogin::Connected(const NETADDR& addr) {
|
||||
this->m_loggedOn = true;
|
||||
|
||||
this->m_loginResponse->m_loginState = LOGIN_STATE_15;
|
||||
this->m_loginResponse->m_loginResult = LOGIN_OK;
|
||||
|
||||
char addrStr[32];
|
||||
// TODO
|
||||
// OsNetAddrToStr(addr, addrStr, sizeof(addrStr));
|
||||
|
||||
char stateStr[64];
|
||||
// TODO
|
||||
// SStrCopy(stateStr, g_LoginStateStringNames[LOGIN_STATE_15], sizeof(stateStr));
|
||||
|
||||
char resultStr[64];
|
||||
// TODO
|
||||
// SStrCopy(resultStr, g_LoginResultStringNames[LOGIN_OK], sizeof(resultStr));
|
||||
|
||||
// TODO
|
||||
this->m_loginResponse->LoginServerStatus(LOGIN_STATE_15, LOGIN_OK, addrStr, stateStr, resultStr, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GruntLogin::GetLogonMethod() {
|
||||
Grunt::ClientLink::Logon logon;
|
||||
|
||||
logon.accountName = nullptr;
|
||||
logon.password = nullptr;
|
||||
|
||||
// TODO
|
||||
|
||||
// TODO Pull build info into something common
|
||||
logon.version[0] = 3;
|
||||
logon.version[1] = 3;
|
||||
logon.version[2] = 5;
|
||||
logon.build = 12340;
|
||||
|
||||
// TODO
|
||||
|
||||
if (this->IsReconnect()) {
|
||||
// TODO
|
||||
} else if (this->m_password) {
|
||||
this->m_loginResponse->m_loginState = LOGIN_STATE_AUTHENTICATING;
|
||||
this->m_loginResponse->m_loginResult = LOGIN_OK;
|
||||
|
||||
char stateStr[64];
|
||||
// TODO
|
||||
// SStrCopy(stateStr, g_LoginStateStringNames[LOGIN_STATE_AUTHENTICATING], sizeof(stateStr));
|
||||
|
||||
char resultStr[64];
|
||||
// TODO
|
||||
// SStrCopy(resultStr, g_LoginResultStringNames[LOGIN_OK], sizeof(resultStr));
|
||||
|
||||
this->m_loginResponse->LoginServerStatus(
|
||||
LOGIN_STATE_AUTHENTICATING,
|
||||
LOGIN_OK,
|
||||
nullptr,
|
||||
stateStr,
|
||||
resultStr,
|
||||
0
|
||||
);
|
||||
|
||||
logon.password = this->m_password;
|
||||
logon.accountName = this->m_accountName;
|
||||
this->m_clientLink->LogonNewSession(logon);
|
||||
|
||||
auto passwordLen = SStrLen(this->m_password);
|
||||
memset(this->m_password, 0, passwordLen);
|
||||
SMemFree(this->m_password, __FILE__, __LINE__, 0);
|
||||
this->m_password = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GruntLogin::GetRealmList() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GruntLogin::Init(LoginResponse* loginResponse) {
|
||||
this->m_loginResponse = loginResponse;
|
||||
|
||||
auto clientLinkMem = SMemAlloc(sizeof(Grunt::ClientLink), __FILE__, __LINE__, 0x0);
|
||||
auto clientLink = new (clientLinkMem) Grunt::ClientLink(*this);
|
||||
this->m_clientLink = clientLink;
|
||||
}
|
||||
|
||||
void GruntLogin::Logoff() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GruntLogin::Logon(const char* a2, const char* a3) {
|
||||
if (this->m_loggedOn) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_reconnect = false;
|
||||
|
||||
// TODO
|
||||
|
||||
this->m_loginResponse->m_loginState = LOGIN_STATE_CONNECTING;
|
||||
this->m_loginResponse->m_loginResult = LOGIN_OK;
|
||||
|
||||
// TODO
|
||||
// char v6[64], v7[64];
|
||||
// SStrCopy(v6, g_LoginStateStringNames[1], sizeof(v6));
|
||||
// SStrCopy(v7, g_LoginResultStringNames[0], sizeof(v7));
|
||||
// this->m_loginResponse->Vfunc6(1, 0, 0, v6, v7, 0);
|
||||
|
||||
if (!a2) {
|
||||
a2 = "us.logon.worldofwarcraft.com:3724";
|
||||
}
|
||||
|
||||
this->m_clientLink->Connect(a2);
|
||||
}
|
||||
23
src/net/login/GruntLogin.hpp
Normal file
23
src/net/login/GruntLogin.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef NET_LOGIN_GRUNT_LOGIN_HPP
|
||||
#define NET_LOGIN_GRUNT_LOGIN_HPP
|
||||
|
||||
#include "net/grunt/Grunt.hpp"
|
||||
#include "net/grunt/ClientResponse.hpp"
|
||||
#include "net/login/Login.hpp"
|
||||
|
||||
class GruntLogin : public Login {
|
||||
public:
|
||||
// Member variables
|
||||
Grunt::ClientLink* m_clientLink = nullptr;
|
||||
|
||||
// Virtual member functions
|
||||
virtual ~GruntLogin();
|
||||
virtual bool Connected(const NETADDR& addr);
|
||||
virtual void GetLogonMethod();
|
||||
virtual void GetRealmList();
|
||||
virtual void Logon(const char* a2, const char* a3);
|
||||
virtual void Logoff();
|
||||
virtual void Init(LoginResponse* loginResponse);
|
||||
};
|
||||
|
||||
#endif
|
||||
29
src/net/login/Login.cpp
Normal file
29
src/net/login/Login.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "net/login/Login.hpp"
|
||||
#include <cstring>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
|
||||
Login::~Login() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool Login::IsReconnect() {
|
||||
return this->m_reconnect;
|
||||
}
|
||||
|
||||
bool Login::OnlineIdle() {
|
||||
// TODO
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Login::SetLogonCreds(const char* accountName, const char* password) {
|
||||
SStrCopy(this->m_accountName, accountName, 1280);
|
||||
|
||||
if (this->m_password) {
|
||||
memset(this->m_password, 0, SStrLen(this->m_password));
|
||||
SMemFree(this->m_password, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
|
||||
this->m_password = SStrDupA(password, __FILE__, __LINE__);
|
||||
}
|
||||
27
src/net/login/Login.hpp
Normal file
27
src/net/login/Login.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef NET_LOGIN_LOGIN_HPP
|
||||
#define NET_LOGIN_LOGIN_HPP
|
||||
|
||||
#include "net/grunt/ClientResponse.hpp"
|
||||
|
||||
class LoginResponse;
|
||||
|
||||
class Login : public Grunt::ClientResponse {
|
||||
public:
|
||||
// Member variables
|
||||
bool m_loggedOn = false;
|
||||
bool m_reconnect = false;
|
||||
char m_accountName[1280] = {};
|
||||
char m_rawAccountName[1280] = {};
|
||||
char* m_password = nullptr;
|
||||
LoginResponse* m_loginResponse = nullptr;
|
||||
|
||||
// Virtual member functions
|
||||
virtual ~Login();
|
||||
virtual bool OnlineIdle();
|
||||
virtual bool IsReconnect();
|
||||
|
||||
// Member functions
|
||||
void SetLogonCreds(const char* accountName, const char* password);
|
||||
};
|
||||
|
||||
#endif
|
||||
16
src/net/login/LoginResponse.hpp
Normal file
16
src/net/login/LoginResponse.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef NET_LOGIN_LOGIN_RESPONSE_HPP
|
||||
#define NET_LOGIN_LOGIN_RESPONSE_HPP
|
||||
|
||||
#include "net/Types.hpp"
|
||||
|
||||
class LoginResponse {
|
||||
public:
|
||||
// Member variables
|
||||
LOGIN_STATE m_loginState;
|
||||
LOGIN_RESULT m_loginResult;
|
||||
|
||||
// Virtual member functions
|
||||
virtual void LoginServerStatus(LOGIN_STATE state, LOGIN_RESULT result, const char* addrStr, const char* stateStr, const char* resultStr, uint16_t a7) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue