Big Refactor.
General support for encryption and decryption. Game Session creation. Discovery Server. Still broken as hell, but less so?
This commit is contained in:
17
Lobby Server/Event/NotifyClientDiscovered.cpp
Normal file
17
Lobby Server/Event/NotifyClientDiscovered.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../../global_define.h"
|
||||
#include "NotifyClientDiscovered.h"
|
||||
|
||||
NotifyClientDiscovered::NotifyClientDiscovered( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x40 )
|
||||
{
|
||||
m_clientIp = clientIp;
|
||||
m_clientPort = clientPort;
|
||||
}
|
||||
|
||||
ByteStream &NotifyClientDiscovered::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_sz_utf8( m_clientIp );
|
||||
m_stream.write_u32( m_clientPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
11
Lobby Server/Event/NotifyClientDiscovered.h
Normal file
11
Lobby Server/Event/NotifyClientDiscovered.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class NotifyClientDiscovered : public GenericMessage {
|
||||
private:
|
||||
std::string m_clientIp;
|
||||
int32_t m_clientPort;
|
||||
|
||||
public:
|
||||
NotifyClientDiscovered( std::string clientIp, int32_t clientPort );
|
||||
ByteStream &Serialize() override;
|
||||
};
|
||||
17
Lobby Server/Event/NotifyClientReqConnect.cpp
Normal file
17
Lobby Server/Event/NotifyClientReqConnect.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../../global_define.h"
|
||||
#include "NotifyClientReqConnect.h"
|
||||
|
||||
NotifyClientRequestConnect::NotifyClientRequestConnect( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x3F )
|
||||
{
|
||||
m_clientIp = clientIp;
|
||||
m_clientPort = clientPort;
|
||||
}
|
||||
|
||||
ByteStream &NotifyClientRequestConnect::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_sz_utf8( m_clientIp );
|
||||
m_stream.write_u32( m_clientPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
12
Lobby Server/Event/NotifyClientReqConnect.h
Normal file
12
Lobby Server/Event/NotifyClientReqConnect.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
class NotifyClientRequestConnect : public GenericMessage
|
||||
{
|
||||
private:
|
||||
std::string m_clientIp;
|
||||
int32_t m_clientPort;
|
||||
|
||||
public:
|
||||
NotifyClientRequestConnect( std::string clientIp, int32_t clientPort );
|
||||
ByteStream &Serialize() override;
|
||||
};
|
||||
17
Lobby Server/Event/NotifyGameDiscovered.cpp
Normal file
17
Lobby Server/Event/NotifyGameDiscovered.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../../global_define.h"
|
||||
#include "NotifyGameDiscovered.h"
|
||||
|
||||
NotifyGameDiscovered::NotifyGameDiscovered( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x3E )
|
||||
{
|
||||
m_clientIp = clientIp;
|
||||
m_clientPort = clientPort;
|
||||
}
|
||||
|
||||
ByteStream &NotifyGameDiscovered::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_sz_utf8( m_clientIp );
|
||||
m_stream.write_u32( m_clientPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
11
Lobby Server/Event/NotifyGameDiscovered.h
Normal file
11
Lobby Server/Event/NotifyGameDiscovered.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class NotifyGameDiscovered : public GenericMessage {
|
||||
private:
|
||||
std::string m_clientIp;
|
||||
int32_t m_clientPort;
|
||||
|
||||
public:
|
||||
NotifyGameDiscovered( std::string clientIp, int32_t clientPort );
|
||||
ByteStream &Serialize() override;
|
||||
};
|
||||
36
Lobby Server/Event/RequestCancelGame.cpp
Normal file
36
Lobby Server/Event/RequestCancelGame.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestCancelGame.h"
|
||||
|
||||
void RequestCancelGame::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestCancelGame::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
// TODO:
|
||||
// Cancel the game
|
||||
// Notify the players via the Discovery Server
|
||||
|
||||
Log::Debug( "RequestCancelGame : %S", m_sessionId.c_str() );
|
||||
|
||||
return std::make_shared< ResultCancelGame >( this );
|
||||
}
|
||||
|
||||
ResultCancelGame::ResultCancelGame( GenericRequest *request ) : GenericResponse( *request )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ByteStream &ResultCancelGame::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( 0 );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
22
Lobby Server/Event/RequestCancelGame.h
Normal file
22
Lobby Server/Event/RequestCancelGame.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class RequestCancelGame : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestCancelGame > Create()
|
||||
{
|
||||
return std::make_unique< RequestCancelGame >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultCancelGame : public GenericResponse {
|
||||
public:
|
||||
ResultCancelGame( GenericRequest *request );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
47
Lobby Server/Event/RequestCreateAccount.cpp
Normal file
47
Lobby Server/Event/RequestCreateAccount.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestCreateAccount.h"
|
||||
|
||||
void RequestCreateAccount::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
auto username = stream->read_encrypted_utf16();
|
||||
auto password = stream->read_encrypted_utf16();
|
||||
auto emailAddress = stream->read_encrypted_utf16();
|
||||
auto dateOfBirth = stream->read_encrypted_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestCreateAccount::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
Log::Debug( "Account creation isn't supported. Random SessionID generated." );
|
||||
|
||||
auto &userMng = RealmUserManager::Get();
|
||||
auto user = userMng.CreateUser( socket, L"foo", L"bar" );
|
||||
|
||||
if( nullptr == user )
|
||||
{
|
||||
Log::Error( "RequestCreateAccount::ProcessRequest() - User not found!" );
|
||||
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::ERROR_FATAL, L"" );
|
||||
}
|
||||
|
||||
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::SUCCESS, user->m_sessionId );
|
||||
}
|
||||
|
||||
ResultCreateAccount::ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
m_sessionId = sessionId;
|
||||
}
|
||||
|
||||
ByteStream &ResultCreateAccount::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
m_stream.write_encrypted_utf16( m_sessionId );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
34
Lobby Server/Event/RequestCreateAccount.h
Normal file
34
Lobby Server/Event/RequestCreateAccount.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
// Account Creation is used in the Network Beta for CoN
|
||||
// but it isn't used or supported here because retail
|
||||
// uses "foo" and "bar" to login without user data.
|
||||
|
||||
class RequestCreateAccount : public GenericRequest
|
||||
{
|
||||
enum CREATE_ACCOUNT_REPLY {
|
||||
SUCCESS = 0,
|
||||
ERROR_FATAL,
|
||||
ERROR_NOT_EXIST
|
||||
};
|
||||
public:
|
||||
static std::unique_ptr< RequestCreateAccount > Create()
|
||||
{
|
||||
return std::make_unique< RequestCreateAccount >();
|
||||
}
|
||||
|
||||
CREATE_ACCOUNT_REPLY m_reply;
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultCreateAccount : public GenericResponse {
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
int32_t m_reply;
|
||||
|
||||
public:
|
||||
ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
58
Lobby Server/Event/RequestCreatePrivateGame.cpp
Normal file
58
Lobby Server/Event/RequestCreatePrivateGame.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "../../global_define.h"
|
||||
|
||||
#include "RequestCreatePrivateGame.h"
|
||||
|
||||
void RequestCreatePrivateGame::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
m_gameName = stream->read_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestCreatePrivateGame::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
auto user = RealmUserManager::Get().GetUser( socket );
|
||||
|
||||
if( user == nullptr )
|
||||
{
|
||||
Log::Error( "User not found! [%S]", m_sessionId.c_str() );
|
||||
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::FATAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
auto &game_manager = GameSessionManager::Get();
|
||||
|
||||
auto result = game_manager.CreatePrivateGameSession( user, m_gameName, 0, 9999 );
|
||||
|
||||
if( !result )
|
||||
{
|
||||
Log::Error( "RequestCreatePrivateGame::ProcessRequest() - Failed to create private game session!" );
|
||||
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
Log::Info( "[%S] Create Private Game: %S", m_sessionId.c_str(), m_gameName.c_str() );
|
||||
|
||||
// Send the discovery server information to the client
|
||||
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::SUCCESS, "192.168.1.248", 40820 );
|
||||
}
|
||||
|
||||
ResultCreatePrivateGame::ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
m_discoveryIp = discoveryIp;
|
||||
m_discoveryPort = discoveryPort;
|
||||
}
|
||||
|
||||
ByteStream &ResultCreatePrivateGame::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
m_stream.write_sz_utf8( m_discoveryIp );
|
||||
m_stream.write( m_discoveryPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
33
Lobby Server/Event/RequestCreatePrivateGame.h
Normal file
33
Lobby Server/Event/RequestCreatePrivateGame.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
class RequestCreatePrivateGame : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
std::wstring m_gameName;
|
||||
|
||||
enum CREATE_REPLY {
|
||||
SUCCESS = 0,
|
||||
FATAL_ERROR,
|
||||
GENERAL_ERROR,
|
||||
};
|
||||
public:
|
||||
static std::unique_ptr< RequestCreatePrivateGame > Create()
|
||||
{
|
||||
return std::make_unique< RequestCreatePrivateGame >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultCreatePrivateGame : public GenericResponse {
|
||||
private:
|
||||
int32_t m_reply;
|
||||
std::string m_discoveryIp;
|
||||
int32_t m_discoveryPort;
|
||||
|
||||
public:
|
||||
ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
65
Lobby Server/Event/RequestCreatePublicGame.cpp
Normal file
65
Lobby Server/Event/RequestCreatePublicGame.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "../../global_define.h"
|
||||
|
||||
#include "RequestCreatePublicGame.h"
|
||||
|
||||
void RequestCreatePublicGame::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
|
||||
// Some kind of match attributes
|
||||
auto unknown_a = stream->read_u16();
|
||||
auto unknown_b = stream->read_u32();
|
||||
auto unknown_c = stream->read_u32();
|
||||
auto unknown_d = stream->read_u32();
|
||||
|
||||
m_gameName = stream->read_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestCreatePublicGame::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
auto user = RealmUserManager::Get().GetUser( socket );
|
||||
|
||||
if( user == nullptr )
|
||||
{
|
||||
Log::Error( "User not found! [%S]", m_sessionId.c_str() );
|
||||
return std::make_shared< ResultCreatePublicGame >( this, CREATE_REPLY::FATAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
auto &game_manager = GameSessionManager::Get();
|
||||
|
||||
auto result = game_manager.CreatePublicGameSession( user, m_gameName, 0, 9999 );
|
||||
|
||||
if( !result )
|
||||
{
|
||||
Log::Error( "RequestCreatePublicGame::ProcessRequest() - Failed to create public game session!" );
|
||||
return std::make_shared< ResultCreatePublicGame >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
Log::Info( "[%S] Create Public Game: %S", m_sessionId.c_str(), m_gameName.c_str() );
|
||||
|
||||
// Send the discovery server information to the client
|
||||
return std::make_shared< ResultCreatePublicGame >( this, CREATE_REPLY::SUCCESS, "192.168.1.248", 40820 );
|
||||
}
|
||||
|
||||
ResultCreatePublicGame::ResultCreatePublicGame( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
m_discoveryIp = discoveryIp;
|
||||
m_discoveryPort = discoveryPort;
|
||||
}
|
||||
|
||||
ByteStream &ResultCreatePublicGame::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
m_stream.write_sz_utf8( m_discoveryIp );
|
||||
m_stream.write( m_discoveryPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
35
Lobby Server/Event/RequestCreatePublicGame.h
Normal file
35
Lobby Server/Event/RequestCreatePublicGame.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
class RequestCreatePublicGame : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
std::wstring m_gameName;
|
||||
|
||||
int32_t m_minimumLevel;
|
||||
int32_t m_maximumLevel;
|
||||
|
||||
enum CREATE_REPLY {
|
||||
SUCCESS = 0,
|
||||
FATAL_ERROR,
|
||||
GENERAL_ERROR,
|
||||
};
|
||||
public:
|
||||
static std::unique_ptr< RequestCreatePublicGame > Create()
|
||||
{
|
||||
return std::make_unique< RequestCreatePublicGame >();
|
||||
}
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultCreatePublicGame : public GenericResponse {
|
||||
private:
|
||||
int32_t m_reply;
|
||||
std::string m_discoveryIp;
|
||||
int32_t m_discoveryPort;
|
||||
|
||||
public:
|
||||
ResultCreatePublicGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
59
Lobby Server/Event/RequestDoClientDiscovery.cpp
Normal file
59
Lobby Server/Event/RequestDoClientDiscovery.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestDoClientDiscovery.h"
|
||||
#include "NotifyClientReqConnect.h"
|
||||
|
||||
void RequestDoClientDiscovery::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
m_gameId = stream->read_u32();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestDoClientDiscovery::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
auto user = RealmUserManager::Get().GetUser( socket );
|
||||
|
||||
if( user == nullptr )
|
||||
{
|
||||
Log::Error( "User not found! [%s]", m_sessionId.c_str() );
|
||||
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
if( user->m_sessionId != m_sessionId )
|
||||
{
|
||||
Log::Error( "Session ID mismatch! [%s]", m_sessionId.c_str() );
|
||||
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
|
||||
}
|
||||
|
||||
auto result = GameSessionManager::Get().UserJoinGame( m_gameId, user );
|
||||
|
||||
if( result == false )
|
||||
{
|
||||
Log::Error( "Failed to join game! [%d]", m_gameId );
|
||||
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::GAME_FULL, "", 0 );
|
||||
}
|
||||
|
||||
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::SUCCESS, "192.168.1.248", 40820 );
|
||||
}
|
||||
|
||||
ResultDoClientDiscovery::ResultDoClientDiscovery( GenericRequest *request, int32_t reply, std::string ip, int32_t port ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
m_discoveryIP = ip;
|
||||
m_discoveryPort = port;
|
||||
}
|
||||
|
||||
ByteStream &ResultDoClientDiscovery::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
m_stream.write_sz_utf8( m_discoveryIP );
|
||||
m_stream.write( m_discoveryPort );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
34
Lobby Server/Event/RequestDoClientDiscovery.h
Normal file
34
Lobby Server/Event/RequestDoClientDiscovery.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
class RequestDoClientDiscovery : public GenericRequest
|
||||
{
|
||||
private:
|
||||
enum DISCOVERY_REPLY {
|
||||
SUCCESS = 0,
|
||||
FATAL_ERROR = 1,
|
||||
GAME_FULL = 2,
|
||||
};
|
||||
|
||||
std::wstring m_sessionId;
|
||||
int32_t m_gameId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestDoClientDiscovery > Create()
|
||||
{
|
||||
return std::make_unique< RequestDoClientDiscovery >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultDoClientDiscovery : public GenericResponse {
|
||||
private:
|
||||
int32_t m_reply;
|
||||
std::string m_discoveryIP;
|
||||
int32_t m_discoveryPort;
|
||||
|
||||
public:
|
||||
ResultDoClientDiscovery( GenericRequest *request, int32_t reply, std::string ip = "", int32_t port = 0);
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
33
Lobby Server/Event/RequestGetEncryptionKey.cpp
Normal file
33
Lobby Server/Event/RequestGetEncryptionKey.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestGetEncryptionKey.h"
|
||||
|
||||
void RequestGetEncryptionKey::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
}
|
||||
|
||||
sptr_generic_response RequestGetEncryptionKey::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
auto publicKey = stream->read_utf8();
|
||||
auto unknown = stream->read_u32();
|
||||
|
||||
return std::make_shared< ResultGetEncryptionKey >( this );
|
||||
}
|
||||
|
||||
ResultGetEncryptionKey::ResultGetEncryptionKey( GenericRequest *request ) : GenericResponse( *request )
|
||||
{
|
||||
m_symKey = RealmCrypt::getSymmetricKey();
|
||||
}
|
||||
|
||||
ByteStream& ResultGetEncryptionKey::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( 0 );
|
||||
|
||||
m_stream.write_encrypted_bytes( m_symKey );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
21
Lobby Server/Event/RequestGetEncryptionKey.h
Normal file
21
Lobby Server/Event/RequestGetEncryptionKey.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class RequestGetEncryptionKey : public GenericRequest
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr< RequestGetEncryptionKey > Create()
|
||||
{
|
||||
return std::make_unique< RequestGetEncryptionKey >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultGetEncryptionKey : public GenericResponse {
|
||||
public:
|
||||
std::vector< uint8_t > m_symKey;
|
||||
|
||||
ResultGetEncryptionKey( GenericRequest *request );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
35
Lobby Server/Event/RequestGetRules.cpp
Normal file
35
Lobby Server/Event/RequestGetRules.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestGetRules.h"
|
||||
|
||||
void RequestGetRules::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_language = stream->read_sz_utf8();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestGetRules::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
// TODO: Get rules/eula based on language
|
||||
std::wstring rules = L"Welcome to the Norrath Emulated Server!\n\n";
|
||||
|
||||
return std::make_shared< ResultGetRules >( this, rules );
|
||||
}
|
||||
|
||||
ResultGetRules::ResultGetRules( GenericRequest *request, std::wstring rules ) : GenericResponse( *request )
|
||||
{
|
||||
m_rules = rules;
|
||||
}
|
||||
|
||||
ByteStream &ResultGetRules::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( 0 );
|
||||
|
||||
m_stream.write_utf16( m_rules );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
25
Lobby Server/Event/RequestGetRules.h
Normal file
25
Lobby Server/Event/RequestGetRules.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
class RequestGetRules : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::string m_language;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestGetRules > Create()
|
||||
{
|
||||
return std::make_unique< RequestGetRules >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultGetRules : public GenericResponse {
|
||||
private:
|
||||
std::wstring m_rules;
|
||||
|
||||
public:
|
||||
ResultGetRules( GenericRequest *request, std::wstring rules );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
56
Lobby Server/Event/RequestLogin.cpp
Normal file
56
Lobby Server/Event/RequestLogin.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "../../global_define.h"
|
||||
|
||||
#include "RequestLogin.h"
|
||||
|
||||
void RequestLogin::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_username = stream->read_encrypted_utf16();
|
||||
m_password = stream->read_encrypted_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestLogin::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
if( m_username.empty() || m_password.empty() )
|
||||
{
|
||||
Log::Error( "RequestLogin::ProcessRequest() - Username or password is empty" );
|
||||
return std::make_shared< ResultLogin >( this, LOGIN_REPLY::NOT_EXIST, L"" );
|
||||
}
|
||||
|
||||
if( m_username == L"foo" && m_password == L"bar" )
|
||||
{
|
||||
// Retail CoN does not use any login information.
|
||||
Log::Debug( "RequestLogin : Champions of Norrath v2.0" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Network Beta CoN uses login information, but it's invalid because of version 2.0.
|
||||
Log::Debug( "RequestLogin : Champions of Norrath v1.0" );
|
||||
}
|
||||
|
||||
auto &userMng = RealmUserManager::Get();
|
||||
|
||||
auto user = userMng.CreateUser( socket, m_username, m_password );
|
||||
|
||||
return std::make_shared< ResultLogin >( this, LOGIN_REPLY::SUCCESS, user->m_sessionId );
|
||||
}
|
||||
|
||||
ResultLogin::ResultLogin( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
m_sessionId = sessionId;
|
||||
}
|
||||
|
||||
ByteStream &ResultLogin::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
m_stream.write_encrypted_utf16( m_sessionId );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
40
Lobby Server/Event/RequestLogin.h
Normal file
40
Lobby Server/Event/RequestLogin.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
// Account Login is used in the Network Beta for CoN.
|
||||
// In the retail version, the game simply logs in with
|
||||
// "foo" and "bar" as the username and password.
|
||||
//
|
||||
// A unique Session ID is generated and assigned to the player.
|
||||
|
||||
class RequestLogin : public GenericRequest
|
||||
{
|
||||
private:
|
||||
enum LOGIN_REPLY {
|
||||
SUCCESS = 0,
|
||||
FATAL_ERROR,
|
||||
NOT_EXIST,
|
||||
};
|
||||
|
||||
std::wstring m_username;
|
||||
std::wstring m_password;
|
||||
std::wstring m_sessionId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestLogin > Create()
|
||||
{
|
||||
return std::make_unique< RequestLogin >();
|
||||
}
|
||||
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultLogin : public GenericResponse {
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
int32_t m_reply;
|
||||
|
||||
public:
|
||||
ResultLogin( GenericRequest *request, int32_t reply, std::wstring sessionId );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
44
Lobby Server/Event/RequestLogout.cpp
Normal file
44
Lobby Server/Event/RequestLogout.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestLogout.h"
|
||||
|
||||
void RequestLogout::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestLogout::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
auto &userMng = RealmUserManager::Get();
|
||||
|
||||
auto user = userMng.GetUser( m_sessionId );
|
||||
|
||||
if( nullptr == user )
|
||||
{
|
||||
Log::Error( "RequestLogout::ProcessRequest() - User not found!" );
|
||||
return std::make_shared< ResultLogout >( this, 1 );
|
||||
}
|
||||
|
||||
// TODO: Any other cleanup here?
|
||||
Log::Debug( "[%S] Logout", m_sessionId.c_str() );
|
||||
|
||||
userMng.RemoveUser( m_sessionId );
|
||||
|
||||
return std::make_shared< ResultLogout >( this, 0 );
|
||||
}
|
||||
|
||||
ResultLogout::ResultLogout( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
|
||||
{
|
||||
m_reply = reply;
|
||||
}
|
||||
|
||||
ByteStream &ResultLogout::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( m_reply );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
23
Lobby Server/Event/RequestLogout.h
Normal file
23
Lobby Server/Event/RequestLogout.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
class RequestLogout : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestLogout > Create()
|
||||
{
|
||||
return std::make_unique< RequestLogout >();
|
||||
}
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultLogout : public GenericResponse {
|
||||
private:
|
||||
int32_t m_reply;
|
||||
public:
|
||||
ResultLogout( GenericRequest *request, int32_t reply );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
88
Lobby Server/Event/RequestMatchGame.cpp
Normal file
88
Lobby Server/Event/RequestMatchGame.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestMatchGame.h"
|
||||
|
||||
void RequestMatchGame::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
|
||||
auto unknown_a = stream->read_u16();
|
||||
auto unknown_b = stream->read_u32();
|
||||
auto unknown_c = stream->read_u32();
|
||||
auto unknown_d = stream->read_u32();
|
||||
|
||||
auto unknown_e = stream->read_u32();
|
||||
|
||||
// Match Game Node Count
|
||||
for( int i = 0; i < unknown_e; i++ )
|
||||
{
|
||||
auto node_a = stream->read_u16();
|
||||
auto node_b = stream->read_u32();
|
||||
|
||||
auto node_c = stream->read_utf16();
|
||||
|
||||
auto node_d = stream->read_u32();
|
||||
auto node_e = stream->read_u32();
|
||||
auto node_f = stream->read_u32();
|
||||
auto node_g = stream->read_u16();
|
||||
}
|
||||
|
||||
auto unknown_f = stream->read_u8();
|
||||
auto unknown_g = stream->read_u32();
|
||||
auto unknown_h = stream->read_u32();
|
||||
|
||||
int dbg = 0;
|
||||
}
|
||||
|
||||
sptr_generic_response RequestMatchGame::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
Log::Debug( "RequestMatchGame : %S", m_sessionId.c_str() );
|
||||
|
||||
return std::make_shared< ResultMatchGame >( this );
|
||||
}
|
||||
|
||||
ResultMatchGame::ResultMatchGame( GenericRequest *request ) : GenericResponse( *request )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ByteStream &ResultMatchGame::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( 0 ); // Connection State
|
||||
|
||||
m_stream.write_u32( 5 );
|
||||
|
||||
for( int i = 0; i < 5; i++ )
|
||||
{
|
||||
m_stream.write_utf16( L"Unknown_A " + std::to_wstring( i ) );
|
||||
}
|
||||
|
||||
m_stream.write_u32( 5 );
|
||||
|
||||
for( int i = 0; i < 5; i++ )
|
||||
{
|
||||
m_stream.write_utf16( L"Game Name " + std::to_wstring( i ) );
|
||||
}
|
||||
|
||||
m_stream.write_u32( 5 );
|
||||
|
||||
for( int i = 0; i < 5; i++ )
|
||||
{
|
||||
m_stream.write_utf16( L"Unknown_B " + std::to_wstring( i ) );
|
||||
}
|
||||
|
||||
|
||||
// Room Unique ID (Used when selecting)
|
||||
m_stream.write_u32( 5 );
|
||||
for( int i = 0; i < 5; i++ )
|
||||
{
|
||||
m_stream.write_u32( i );
|
||||
}
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
21
Lobby Server/Event/RequestMatchGame.h
Normal file
21
Lobby Server/Event/RequestMatchGame.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class RequestMatchGame : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestMatchGame > Create()
|
||||
{
|
||||
return std::make_unique< RequestMatchGame >();
|
||||
}
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultMatchGame : public GenericResponse {
|
||||
public:
|
||||
ResultMatchGame( GenericRequest *request );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
32
Lobby Server/Event/RequestTouchSession.cpp
Normal file
32
Lobby Server/Event/RequestTouchSession.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "../../global_define.h"
|
||||
#include "RequestTouchSession.h"
|
||||
|
||||
void RequestTouchSession::Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
DeserializeHeader( stream );
|
||||
|
||||
m_sessionId = stream->read_encrypted_utf16();
|
||||
}
|
||||
|
||||
sptr_generic_response RequestTouchSession::ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
Deserialize( socket, stream );
|
||||
|
||||
Log::Debug( "RequestTouchSession : %S", m_sessionId.c_str() );
|
||||
|
||||
return std::make_shared< ResultTouchSession >( this );
|
||||
}
|
||||
|
||||
ResultTouchSession::ResultTouchSession( GenericRequest *request ) : GenericResponse( *request )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ByteStream &ResultTouchSession::Serialize()
|
||||
{
|
||||
m_stream.write_u16( m_packetId );
|
||||
m_stream.write_u32( m_requestId );
|
||||
m_stream.write_u32( 0 );
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
21
Lobby Server/Event/RequestTouchSession.h
Normal file
21
Lobby Server/Event/RequestTouchSession.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class RequestTouchSession : public GenericRequest
|
||||
{
|
||||
private:
|
||||
std::wstring m_sessionId;
|
||||
|
||||
public:
|
||||
static std::unique_ptr< RequestTouchSession > Create()
|
||||
{
|
||||
return std::make_unique< RequestTouchSession >();
|
||||
}
|
||||
sptr_generic_response ProcessRequest( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
void Deserialize( sptr_tcp_socket socket, sptr_byte_stream stream ) override;
|
||||
};
|
||||
|
||||
class ResultTouchSession : public GenericResponse {
|
||||
public:
|
||||
ResultTouchSession( GenericRequest *request );
|
||||
ByteStream &Serialize();
|
||||
};
|
||||
75
Lobby Server/EventLookup.h
Normal file
75
Lobby Server/EventLookup.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
#include "Event/RequestCancelGame.h"
|
||||
#include "Event/RequestCreateAccount.h"
|
||||
#include "Event/RequestCreatePrivateGame.h"
|
||||
#include "Event/RequestCreatePublicGame.h"
|
||||
#include "Event/RequestLogin.h"
|
||||
#include "Event/RequestLogout.h"
|
||||
#include "Event/RequestMatchGame.h"
|
||||
#include "Event/RequestTouchSession.h"
|
||||
#include "Event/RequestDoClientDiscovery.h"
|
||||
#include "Event/RequestGetEncryptionKey.h"
|
||||
#include "Event/RequestGetRules.h"
|
||||
|
||||
const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > > LOBBY_REQUEST_EVENT =
|
||||
{
|
||||
{ 0x0005, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestCancelGame >();
|
||||
}
|
||||
},
|
||||
{ 0x0006, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestCreateAccount >();
|
||||
}
|
||||
},
|
||||
{ 0x0008, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestCreatePrivateGame >();
|
||||
}
|
||||
},
|
||||
{ 0x000A, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestCreatePublicGame >();
|
||||
}
|
||||
},
|
||||
{ 0x0016, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestLogin >();
|
||||
}
|
||||
},
|
||||
{ 0x0017, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestLogout >();
|
||||
}
|
||||
},
|
||||
{ 0x0018, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestMatchGame >();
|
||||
}
|
||||
},
|
||||
{ 0x0024, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestTouchSession >();
|
||||
}
|
||||
},
|
||||
{ 0x0025, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestDoClientDiscovery >();
|
||||
}
|
||||
},
|
||||
{ 0x0027, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestGetEncryptionKey >();
|
||||
}
|
||||
},
|
||||
{ 0x0042, []() -> std::unique_ptr< GenericRequest >
|
||||
{
|
||||
return std::make_unique< RequestGetRules >();
|
||||
}
|
||||
}
|
||||
};
|
||||
255
Lobby Server/LobbyServer.cpp
Normal file
255
Lobby Server/LobbyServer.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
// ╔╗╔╔═╗╦═╗╦═╗╔═╗╔╦╗╦ ╦
|
||||
// ║║║║ ║╠╦╝╠╦╝╠═╣ ║ ╠═╣
|
||||
// ╝╚╝╚═╝╩╚═╩╚═╩ ╩ ╩ ╩ ╩
|
||||
// ╦ ╔═╗╔╗ ╔╗ ╦ ╦ ╔═╗╔═╗╦═╗╦ ╦╔═╗╦═╗
|
||||
// ║ ║ ║╠╩╗╠╩╗╚╦╝ ╚═╗║╣ ╠╦╝╚╗╔╝║╣ ╠╦╝
|
||||
// ╩═╝╚═╝╚═╝╚═╝ ╩ ╚═╝╚═╝╩╚═ ╚╝ ╚═╝╩╚═
|
||||
|
||||
#include "../global_define.h"
|
||||
|
||||
#include "EventLookup.h"
|
||||
#include "LobbyServer.h"
|
||||
|
||||
LobbyServer::LobbyServer()
|
||||
{
|
||||
m_running = false;
|
||||
m_listenSocket = INVALID_SOCKET;
|
||||
|
||||
m_clientSockets.clear();
|
||||
m_recvBuffer.resize( 1024 );
|
||||
}
|
||||
|
||||
LobbyServer::~LobbyServer()
|
||||
{
|
||||
}
|
||||
|
||||
void LobbyServer::Start( std::string ip, int32_t port )
|
||||
{
|
||||
m_listenSocket = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
|
||||
if( m_listenSocket == INVALID_SOCKET )
|
||||
{
|
||||
Log::Error( "WSASocket() failed" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind the socket
|
||||
sockaddr_in service;
|
||||
service.sin_family = AF_INET;
|
||||
service.sin_port = htons( port );
|
||||
service.sin_addr.s_addr = inet_addr( ip.c_str() );
|
||||
|
||||
if( bind( m_listenSocket, ( SOCKADDR * )&service, sizeof( service ) ) == SOCKET_ERROR )
|
||||
{
|
||||
Log::Error( "bind() failed" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen on the socket
|
||||
if( listen( m_listenSocket, SOMAXCONN ) == SOCKET_ERROR )
|
||||
{
|
||||
Log::Error( "listen() failed" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the server
|
||||
m_running = true;
|
||||
m_thread = std::thread( &LobbyServer::Run, this );
|
||||
|
||||
Log::Info( "Lobby Server started on %s:%d", ip.c_str(), port );
|
||||
}
|
||||
|
||||
void LobbyServer::Stop()
|
||||
{
|
||||
m_running = false;
|
||||
if( m_thread.joinable() )
|
||||
{
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyServer::Run()
|
||||
{
|
||||
FD_SET readSet;
|
||||
FD_SET writeSet;
|
||||
|
||||
timeval timeout = { 0, 1000 };
|
||||
|
||||
while( m_running )
|
||||
{
|
||||
FD_ZERO( &readSet );
|
||||
FD_ZERO( &writeSet );
|
||||
|
||||
FD_SET( m_listenSocket, &readSet );
|
||||
|
||||
// Process clients
|
||||
for( auto &client : m_clientSockets )
|
||||
{
|
||||
FD_SET( client->fd, &readSet );
|
||||
FD_SET( client->fd, &writeSet );
|
||||
}
|
||||
|
||||
auto result = select( 0, &readSet, &writeSet, NULL, &timeout );
|
||||
|
||||
if( result == SOCKET_ERROR )
|
||||
{
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( FD_ISSET( m_listenSocket, &readSet ) )
|
||||
{
|
||||
AcceptNewClient();
|
||||
}
|
||||
|
||||
for( auto &client : m_clientSockets )
|
||||
{
|
||||
if( FD_ISSET( client->fd, &readSet ) )
|
||||
{
|
||||
ReadSocket( client );
|
||||
}
|
||||
|
||||
if( FD_ISSET( client->fd, &writeSet ) )
|
||||
{
|
||||
WriteSocket( client );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyServer::AcceptNewClient()
|
||||
{
|
||||
sockaddr_in clientInfo{};
|
||||
int32_t addrSize = sizeof( clientInfo );
|
||||
|
||||
SOCKET clientSocket = accept( m_listenSocket, ( SOCKADDR * )&clientInfo, &addrSize );
|
||||
if( clientSocket == INVALID_SOCKET )
|
||||
{
|
||||
Log::Error( "accept() failed" );
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_socket = std::make_shared< RealmTCPSocket >();
|
||||
new_socket->fd = clientSocket;
|
||||
new_socket->remote_address = clientInfo;
|
||||
new_socket->peer_ip_address = inet_ntoa( clientInfo.sin_addr );
|
||||
|
||||
m_clientSockets.push_back( new_socket );
|
||||
|
||||
Log::Info( "[LOBBY] New client connected : (%s)", new_socket->peer_ip_address.c_str() );
|
||||
}
|
||||
|
||||
void LobbyServer::ReadSocket( sptr_tcp_socket socket )
|
||||
{
|
||||
if( socket->flag.disconnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto bytesReceived = recv( socket->fd, ( char * )m_recvBuffer.data(), m_recvBuffer.size(), 0 );
|
||||
|
||||
if( bytesReceived == SOCKET_ERROR )
|
||||
{
|
||||
auto error = WSAGetLastError();
|
||||
Log::Info( "Socket Error [%d].", error );
|
||||
socket->flag.disconnected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if( bytesReceived == 0 )
|
||||
{
|
||||
Log::Info( "Socket Disconnected." );
|
||||
socket->flag.disconnected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Append the received data to the sockets processing buffer.
|
||||
// There's definitely a more elegant way of handling data here,
|
||||
// but this is just easier for now.
|
||||
socket->m_pendingReadBuffer.insert( socket->m_pendingReadBuffer.end(), m_recvBuffer.begin(), m_recvBuffer.begin() + bytesReceived );
|
||||
|
||||
// Handle valid packets in the buffer.
|
||||
while( socket->m_pendingReadBuffer.size() > 0 )
|
||||
{
|
||||
auto packetSize = htonl( *( int32_t * )&socket->m_pendingReadBuffer[ 0 ] );
|
||||
|
||||
if( packetSize > socket->m_pendingReadBuffer.size() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//Log::Packet( socket->m_pendingReadBuffer, packetSize, false );
|
||||
|
||||
auto stream = std::make_shared< ByteStream >( socket->m_pendingReadBuffer.data() + 4, packetSize - 4 );
|
||||
|
||||
// Erase the packet from the buffer
|
||||
socket->m_pendingReadBuffer.erase( socket->m_pendingReadBuffer.begin(), socket->m_pendingReadBuffer.begin() + packetSize );
|
||||
|
||||
// Process the packet
|
||||
HandleRequest( socket, stream );
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyServer::WriteSocket( sptr_tcp_socket socket )
|
||||
{
|
||||
if( socket->flag.disconnected )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( socket->m_pendingWriteBuffer.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t totalBytesSent = 0;
|
||||
|
||||
//Log::Packet( socket->m_pendingWriteBuffer, socket->m_pendingWriteBuffer.size(), false );
|
||||
|
||||
while( true )
|
||||
{
|
||||
auto chunkSize = std::min< int >( socket->m_pendingWriteBuffer.size(), 1024 );
|
||||
auto bytesSent = send( socket->fd, ( char * )socket->m_pendingWriteBuffer.data(), chunkSize, 0 );
|
||||
|
||||
if( bytesSent == SOCKET_ERROR )
|
||||
{
|
||||
socket->flag.disconnected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
totalBytesSent += bytesSent;
|
||||
|
||||
if( bytesSent < chunkSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( totalBytesSent == socket->m_pendingWriteBuffer.size() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
socket->m_pendingWriteBuffer.erase( socket->m_pendingWriteBuffer.begin(), socket->m_pendingWriteBuffer.begin() + totalBytesSent );
|
||||
}
|
||||
|
||||
void LobbyServer::HandleRequest( sptr_tcp_socket socket, sptr_byte_stream stream )
|
||||
{
|
||||
auto packetId = stream->read< uint16_t >();
|
||||
stream->set_position( 0 );
|
||||
|
||||
auto it = LOBBY_REQUEST_EVENT.find( packetId );
|
||||
if( it == LOBBY_REQUEST_EVENT.end() )
|
||||
{
|
||||
Log::Error( "[LOBBY] Unknown packet id : 0x%04X", packetId );
|
||||
return;
|
||||
}
|
||||
|
||||
Log::Debug( "[LOBBY] Request processed : 0x%04X", packetId );
|
||||
|
||||
auto request = it->second();
|
||||
|
||||
if( auto res = request->ProcessRequest( socket, stream ) )
|
||||
{
|
||||
socket->send( res );
|
||||
}
|
||||
}
|
||||
81
Lobby Server/LobbyServer.h
Normal file
81
Lobby Server/LobbyServer.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
class GameRoom {
|
||||
public:
|
||||
GameRoom()
|
||||
{
|
||||
m_gameType = GameType::PRIVATE;
|
||||
m_roomId = 0;
|
||||
m_ownerSessionId = L"";
|
||||
m_gameName = L"";
|
||||
m_minimumLevel = 0;
|
||||
m_maximumLevel = 0;
|
||||
}
|
||||
|
||||
~GameRoom()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
enum GameType {
|
||||
PRIVATE,
|
||||
PUBLIC
|
||||
} m_gameType;
|
||||
|
||||
int32_t m_roomId;
|
||||
std::wstring m_ownerSessionId;
|
||||
std::wstring m_gameName;
|
||||
int32_t m_minimumLevel;
|
||||
int32_t m_maximumLevel;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< GameRoom > sptr_game_room;
|
||||
|
||||
class LobbyServer
|
||||
{
|
||||
private:
|
||||
static inline std::unique_ptr< LobbyServer > m_instance;
|
||||
static inline std::mutex m_mutex;
|
||||
|
||||
Timer m_timer;
|
||||
std::atomic< bool > m_running;
|
||||
std::thread m_thread;
|
||||
|
||||
public:
|
||||
static LobbyServer& Get()
|
||||
{
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
if( m_instance == nullptr )
|
||||
{
|
||||
m_instance.reset( new LobbyServer() );
|
||||
}
|
||||
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
LobbyServer( const LobbyServer & ) = delete;
|
||||
LobbyServer &operator=( const LobbyServer & ) = delete;
|
||||
LobbyServer();
|
||||
~LobbyServer();
|
||||
|
||||
void Start( std::string ip, int32_t port );
|
||||
void Stop();
|
||||
bool isRunning() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
private:
|
||||
SOCKET m_listenSocket;
|
||||
std::vector< sptr_tcp_socket > m_clientSockets;
|
||||
std::vector< uint8_t > m_recvBuffer;
|
||||
|
||||
void Run();
|
||||
void AcceptNewClient();
|
||||
void ReadSocket( sptr_tcp_socket socket );
|
||||
void WriteSocket( sptr_tcp_socket socket );
|
||||
void HandleRequest( sptr_tcp_socket socket, sptr_byte_stream stream );
|
||||
};
|
||||
Reference in New Issue
Block a user