mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-21 21:17:25 +00:00
Initial work on TCP transport layer:
* Optionally compiled additional TCP transport layer. * Config to enable it. * Tested and functional with lcdr's tcpudp dll, udp being disabled in the dll due to port issues. * Removed unused RakNet replica manager and id manager. We've got our own replica manager since pre-open-source. * Utilizes async boost behavior. Todo: * Figure out how to do ping calculations. * Fix crashes on universe shutdown. * Test TLS on a VPS. * Remove unnecessary logging. * Test with lots of clients. * Finish "master" to "manager" naming refactor.
This commit is contained in:
parent
8d54db7851
commit
4004534732
@ -16,6 +16,8 @@ class EntityManager;
|
|||||||
class dZoneManager;
|
class dZoneManager;
|
||||||
class PlayerContainer;
|
class PlayerContainer;
|
||||||
|
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
using signal_t = volatile std::sig_atomic_t;
|
using signal_t = volatile std::sig_atomic_t;
|
||||||
extern Logger* logger;
|
extern Logger* logger;
|
||||||
@ -24,7 +26,7 @@ namespace Game {
|
|||||||
extern dChatFilter* chatFilter;
|
extern dChatFilter* chatFilter;
|
||||||
extern dConfig* config;
|
extern dConfig* config;
|
||||||
extern std::mt19937 randomEngine;
|
extern std::mt19937 randomEngine;
|
||||||
extern RakPeerInterface* chatServer;
|
extern TransportPeerInterface* chatServer;
|
||||||
extern AssetManager* assetManager;
|
extern AssetManager* assetManager;
|
||||||
extern SystemAddress chatSysAddr;
|
extern SystemAddress chatSysAddr;
|
||||||
extern signal_t lastSignal;
|
extern signal_t lastSignal;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef __EMASTERMESSAGETYPE__H__
|
#ifndef __EMANAGERMESSAGETYPE__H__
|
||||||
#define __EMASTERMESSAGETYPE__H__
|
#define __EMANAGERMESSAGETYPE__H__
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
enum class eMasterMessageType : uint32_t {
|
enum class eManagerMessageType : uint32_t {
|
||||||
REQUEST_PERSISTENT_ID = 1,
|
REQUEST_PERSISTENT_ID = 1,
|
||||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||||
REQUEST_ZONE_TRANSFER,
|
REQUEST_ZONE_TRANSFER,
|
||||||
@ -33,4 +33,4 @@ enum class eMasterMessageType : uint32_t {
|
|||||||
NEW_SESSION_ALERT
|
NEW_SESSION_ALERT
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__EMASTERMESSAGETYPE__H__
|
#endif //!__EMANAGERMESSAGETYPE__H__
|
@ -18,7 +18,7 @@
|
|||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "eObjectWorldState.h"
|
#include "eObjectWorldState.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||||
@ -137,7 +137,7 @@ LWOCLONEID RocketLaunchpadControlComponent::GetSelectedCloneId(LWOOBJID player)
|
|||||||
|
|
||||||
void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) {
|
void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PREP_ZONE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::PREP_ZONE);
|
||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
#include "dServer.h"
|
||||||
|
|
||||||
//! The persistent ID request
|
//! The persistent ID request
|
||||||
struct PersistentIDRequest {
|
struct PersistentIDRequest {
|
||||||
@ -25,7 +26,7 @@ namespace {
|
|||||||
void ObjectIDManager::RequestPersistentID(const std::function<void(uint32_t)> callback) {
|
void ObjectIDManager::RequestPersistentID(const std::function<void(uint32_t)> callback) {
|
||||||
const auto& request = Requests.emplace_back(++CurrentRequestID, callback);
|
const auto& request = Requests.emplace_back(++CurrentRequestID, callback);
|
||||||
|
|
||||||
MasterPackets::SendPersistentIDRequest(Game::server, request.requestID);
|
MasterPackets::SendPersistentIDRequest(Game::server->GetTransportLayerPtr(), request.requestID);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Handles a persistent ID response
|
//! Handles a persistent ID response
|
||||||
|
@ -45,9 +45,10 @@
|
|||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
#include "eInventoryType.h"
|
#include "eInventoryType.h"
|
||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
|
#include <RakNetTransportLayer.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DEVGMCommands {
|
namespace DEVGMCommands {
|
||||||
@ -503,7 +504,7 @@ namespace DEVGMCommands {
|
|||||||
void ShutdownUniverse(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
void ShutdownUniverse(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||||
//Tell the master server that we're going to be shutting down whole "universe":
|
//Tell the master server that we're going to be shutting down whole "universe":
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_UNIVERSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN_UNIVERSE);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Sent universe shutdown notification to master.");
|
ChatPackets::SendSystemMessage(sysAddr, u"Sent universe shutdown notification to master.");
|
||||||
|
|
||||||
@ -1247,8 +1248,16 @@ namespace DEVGMCommands {
|
|||||||
|
|
||||||
scriptedActivityComponent->ReloadConfig();
|
scriptedActivityComponent->ReloadConfig();
|
||||||
}
|
}
|
||||||
Game::server->UpdateMaximumMtuSize();
|
|
||||||
Game::server->UpdateBandwidthLimit();
|
if (Game::server->GetTransportType() == TransportType::RakNet) {
|
||||||
|
const auto& transport = Game::server->GetTransportLayer();
|
||||||
|
|
||||||
|
auto* raknetTransport = static_cast<RakNetTransportLayer*>(transport.get());
|
||||||
|
|
||||||
|
raknetTransport->UpdateMaximumMtuSize();
|
||||||
|
raknetTransport->UpdateBandwidthLimit();
|
||||||
|
}
|
||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Successfully reloaded config for world!");
|
ChatPackets::SendSystemMessage(sysAddr, u"Successfully reloaded config for world!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "MasterPackets.h"
|
#include "MasterPackets.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
#include "Start.h"
|
#include "Start.h"
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ void InstanceManager::ReadyInstance(Instance* instance) {
|
|||||||
LOG("Responding to pending request %llu -> %i (%i)", request, zoneId.GetMapID(), zoneId.GetCloneID());
|
LOG("Responding to pending request %llu -> %i (%i)", request, zoneId.GetMapID(), zoneId.GetCloneID());
|
||||||
|
|
||||||
MasterPackets::SendZoneTransferResponse(
|
MasterPackets::SendZoneTransferResponse(
|
||||||
Game::server,
|
Game::server->GetTransportLayerPtr(),
|
||||||
request.sysAddr,
|
request.sysAddr,
|
||||||
request.id,
|
request.id,
|
||||||
request.mythranShift,
|
request.mythranShift,
|
||||||
@ -177,7 +177,7 @@ void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstan
|
|||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::AFFIRM_TRANSFER_REQUEST);
|
||||||
|
|
||||||
bitStream.Write(request.id);
|
bitStream.Write(request.id);
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transfer
|
|||||||
const auto& zoneId = instance->GetZoneID();
|
const auto& zoneId = instance->GetZoneID();
|
||||||
|
|
||||||
MasterPackets::SendZoneTransferResponse(
|
MasterPackets::SendZoneTransferResponse(
|
||||||
Game::server,
|
Game::server->GetTransportLayerPtr(),
|
||||||
request.sysAddr,
|
request.sysAddr,
|
||||||
request.id,
|
request.id,
|
||||||
request.mythranShift,
|
request.mythranShift,
|
||||||
@ -359,7 +359,7 @@ bool Instance::GetShutdownComplete() const {
|
|||||||
void Instance::Shutdown() {
|
void Instance::Shutdown() {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN);
|
||||||
|
|
||||||
Game::server->Send(bitStream, this->m_SysAddr, false);
|
Game::server->Send(bitStream, this->m_SysAddr, false);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
//RakNet includes:
|
//RakNet includes:
|
||||||
#include "RakNetDefines.h"
|
#include "RakNetDefines.h"
|
||||||
@ -295,7 +295,7 @@ int main(int argc, char** argv) {
|
|||||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||||
|
|
||||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal);
|
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Manager, Game::config, &Game::lastSignal);
|
||||||
|
|
||||||
std::string master_server_ip = "localhost";
|
std::string master_server_ip = "localhost";
|
||||||
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
||||||
@ -473,8 +473,8 @@ void HandlePacket(Packet* packet) {
|
|||||||
if (packet->length < 4) return;
|
if (packet->length < 4) return;
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||||
case eMasterMessageType::REQUEST_PERSISTENT_ID: {
|
case eManagerMessageType::REQUEST_PERSISTENT_ID: {
|
||||||
LOG("A persistent ID req");
|
LOG("A persistent ID req");
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
@ -482,11 +482,11 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read(requestID);
|
inStream.Read(requestID);
|
||||||
|
|
||||||
uint32_t objID = PersistentIDManager::GeneratePersistentID();
|
uint32_t objID = PersistentIDManager::GeneratePersistentID();
|
||||||
MasterPackets::SendPersistentIDResponse(Game::server, packet->systemAddress, requestID, objID);
|
MasterPackets::SendPersistentIDResponse(Game::server->GetTransportLayerPtr(), packet->systemAddress, requestID, objID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::REQUEST_ZONE_TRANSFER: {
|
case eManagerMessageType::REQUEST_ZONE_TRANSFER: {
|
||||||
LOG("Received zone transfer req");
|
LOG("Received zone transfer req");
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
@ -522,7 +522,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SERVER_INFO: {
|
case eManagerMessageType::SERVER_INFO: {
|
||||||
//MasterPackets::HandleServerInfo(packet);
|
//MasterPackets::HandleServerInfo(packet);
|
||||||
|
|
||||||
//This is here because otherwise we'd have to include IM in
|
//This is here because otherwise we'd have to include IM in
|
||||||
@ -543,6 +543,8 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read(theirServerType);
|
inStream.Read(theirServerType);
|
||||||
inStream.Read(theirIP);
|
inStream.Read(theirIP);
|
||||||
|
|
||||||
|
LOG("Received server info, %i %i %i %i %s", theirPort, theirZoneID, theirInstanceID, theirServerType, theirIP.string.c_str());
|
||||||
|
|
||||||
if (theirServerType == ServerType::World) {
|
if (theirServerType == ServerType::World) {
|
||||||
if (!Game::im->IsPortInUse(theirPort)) {
|
if (!Game::im->IsPortInUse(theirPort)) {
|
||||||
Instance* in = new Instance(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12);
|
Instance* in = new Instance(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12);
|
||||||
@ -551,12 +553,18 @@ void HandlePacket(Packet* packet) {
|
|||||||
copy.binaryAddress = packet->systemAddress.binaryAddress;
|
copy.binaryAddress = packet->systemAddress.binaryAddress;
|
||||||
copy.port = packet->systemAddress.port;
|
copy.port = packet->systemAddress.port;
|
||||||
|
|
||||||
|
LOG("Adding instance %i %i on %s:%i (%s:%i)", theirZoneID, theirInstanceID, packet->systemAddress.ToString(false), packet->systemAddress.port, theirIP.string.c_str(), theirPort);
|
||||||
|
|
||||||
in->SetSysAddr(copy);
|
in->SetSysAddr(copy);
|
||||||
Game::im->AddInstance(in);
|
Game::im->AddInstance(in);
|
||||||
} else {
|
} else {
|
||||||
auto instance = Game::im->FindInstance(
|
auto* instance = Game::im->FindInstance(
|
||||||
theirZoneID, static_cast<uint16_t>(theirInstanceID));
|
theirZoneID, static_cast<uint16_t>(theirInstanceID));
|
||||||
if (instance) {
|
if (instance) {
|
||||||
|
LOG("Setting address of instance %i %i from %s:%i to %s:%i (%s:%i)",
|
||||||
|
theirZoneID, theirInstanceID, instance->GetIP().c_str(), instance->GetPort(), packet->systemAddress.ToString(false), packet->systemAddress.port, theirIP.string.c_str(), theirPort
|
||||||
|
);
|
||||||
|
|
||||||
instance->SetSysAddr(packet->systemAddress);
|
instance->SetSysAddr(packet->systemAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -583,7 +591,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SET_SESSION_KEY: {
|
case eManagerMessageType::SET_SESSION_KEY: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
uint32_t sessionKey = 0;
|
uint32_t sessionKey = 0;
|
||||||
inStream.Read(sessionKey);
|
inStream.Read(sessionKey);
|
||||||
@ -595,7 +603,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
activeSessions.erase(it.first);
|
activeSessions.erase(it.first);
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::NEW_SESSION_ALERT);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::NEW_SESSION_ALERT);
|
||||||
bitStream.Write(sessionKey);
|
bitStream.Write(sessionKey);
|
||||||
bitStream.Write(username);
|
bitStream.Write(username);
|
||||||
SEND_PACKET_BROADCAST;
|
SEND_PACKET_BROADCAST;
|
||||||
@ -609,7 +617,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::REQUEST_SESSION_KEY: {
|
case eManagerMessageType::REQUEST_SESSION_KEY: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LUWString username;
|
LUWString username;
|
||||||
inStream.Read(username);
|
inStream.Read(username);
|
||||||
@ -617,7 +625,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
for (auto key : activeSessions) {
|
for (auto key : activeSessions) {
|
||||||
if (key.second == username.GetAsString()) {
|
if (key.second == username.GetAsString()) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SESSION_KEY_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SESSION_KEY_RESPONSE);
|
||||||
bitStream.Write(key.first);
|
bitStream.Write(key.first);
|
||||||
bitStream.Write(username);
|
bitStream.Write(username);
|
||||||
Game::server->Send(bitStream, packet->systemAddress, false);
|
Game::server->Send(bitStream, packet->systemAddress, false);
|
||||||
@ -627,7 +635,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::PLAYER_ADDED: {
|
case eManagerMessageType::PLAYER_ADDED: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -647,7 +655,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::PLAYER_REMOVED: {
|
case eManagerMessageType::PLAYER_REMOVED: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -665,7 +673,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::CREATE_PRIVATE_ZONE: {
|
case eManagerMessageType::CREATE_PRIVATE_ZONE: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -689,7 +697,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::REQUEST_PRIVATE_ZONE: {
|
case eManagerMessageType::REQUEST_PRIVATE_ZONE: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -719,12 +727,12 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
const auto& zone = instance->GetZoneID();
|
const auto& zone = instance->GetZoneID();
|
||||||
|
|
||||||
MasterPackets::SendZoneTransferResponse(Game::server, packet->systemAddress, requestID, static_cast<bool>(mythranShift), zone.GetMapID(), instance->GetInstanceID(), zone.GetCloneID(), instance->GetIP(), instance->GetPort());
|
MasterPackets::SendZoneTransferResponse(Game::server->GetTransportLayerPtr(), packet->systemAddress, requestID, static_cast<bool>(mythranShift), zone.GetMapID(), instance->GetInstanceID(), zone.GetCloneID(), instance->GetIP(), instance->GetPort());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::WORLD_READY: {
|
case eManagerMessageType::WORLD_READY: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -748,7 +756,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::PREP_ZONE: {
|
case eManagerMessageType::PREP_ZONE: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -764,7 +772,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::AFFIRM_TRANSFER_RESPONSE: {
|
case eManagerMessageType::AFFIRM_TRANSFER_RESPONSE: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -784,7 +792,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SHUTDOWN_RESPONSE: {
|
case eManagerMessageType::SHUTDOWN_RESPONSE: {
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
@ -799,7 +807,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SHUTDOWN_UNIVERSE: {
|
case eManagerMessageType::SHUTDOWN_UNIVERSE: {
|
||||||
LOG("Received shutdown universe command, shutting down in 10 minutes.");
|
LOG("Received shutdown universe command, shutting down in 10 minutes.");
|
||||||
Game::universeShutdownRequested = true;
|
Game::universeShutdownRequested = true;
|
||||||
break;
|
break;
|
||||||
@ -829,7 +837,7 @@ int ShutdownSequence(int32_t signal) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN);
|
||||||
Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
LOG("Triggered master shutdown");
|
LOG("Triggered master shutdown");
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "eLoginResponse.h"
|
#include "eLoginResponse.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eServerMessageType.h"
|
#include "eServerMessageType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
namespace {
|
namespace {
|
||||||
@ -60,7 +60,7 @@ void AuthPackets::HandleHandshake(dServer* server, Packet* packet) {
|
|||||||
|
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
inStream.Read(port);
|
inStream.Read(port);
|
||||||
if (port != packet->systemAddress.port) LOG("WARNING: Port written in packet does not match the port the client is connecting over!");
|
if (port != packet->systemAddress.port) LOG("WARNING: Port written in packet does not match the port the client is connecting over, %i != %i!", port, packet->systemAddress.port);
|
||||||
|
|
||||||
inStream.IgnoreBytes(33);
|
inStream.IgnoreBytes(33);
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd
|
|||||||
//Inform the master server that we've created a session for this user:
|
//Inform the master server that we've created a session for this user:
|
||||||
if (responseCode == eLoginResponse::SUCCESS) {
|
if (responseCode == eLoginResponse::SUCCESS) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SET_SESSION_KEY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SET_SESSION_KEY);
|
||||||
bitStream.Write(sessionKey);
|
bitStream.Write(sessionKey);
|
||||||
bitStream.Write(LUString(username));
|
bitStream.Write(LUString(username));
|
||||||
server->SendToMaster(bitStream);
|
server->SendToMaster(bitStream);
|
||||||
|
@ -5,10 +5,33 @@ set(DNET_SOURCES "AuthPackets.cpp"
|
|||||||
"MasterPackets.cpp"
|
"MasterPackets.cpp"
|
||||||
"PacketUtils.cpp"
|
"PacketUtils.cpp"
|
||||||
"WorldPackets.cpp"
|
"WorldPackets.cpp"
|
||||||
|
"RakNetTransportLayer.cpp"
|
||||||
|
"RakNetPeer.cpp"
|
||||||
"ZoneInstanceManager.cpp")
|
"ZoneInstanceManager.cpp")
|
||||||
|
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
|
# Find boost for asio
|
||||||
|
cmake_policy(SET CMP0167 NEW)
|
||||||
|
find_package(Boost QUIET COMPONENTS system)
|
||||||
|
|
||||||
|
if(Boost_FOUND)
|
||||||
|
message(STATUS "Boost found, enabling TCP transport support")
|
||||||
|
|
||||||
|
# Add to source list
|
||||||
|
list(APPEND DNET_SOURCES "TcpTransportLayer.cpp" "TcpPeer.cpp" "TcpSession.cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(dNet STATIC ${DNET_SOURCES})
|
add_library(dNet STATIC ${DNET_SOURCES})
|
||||||
target_link_libraries(dNet PRIVATE bcrypt MD5)
|
|
||||||
|
if(Boost_FOUND)
|
||||||
|
target_compile_definitions(dNet PRIVATE NET_ENABLE_TCP_TRANSPORT)
|
||||||
|
|
||||||
|
target_link_libraries(dNet PRIVATE bcrypt MD5 OpenSSL::SSL OpenSSL::Crypto OpenSSL::applink Boost::system)
|
||||||
|
else()
|
||||||
|
target_link_libraries(dNet PRIVATE bcrypt MD5)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(dNet PRIVATE
|
target_include_directories(dNet PRIVATE
|
||||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
#include "MasterPackets.h"
|
#include "MasterPackets.h"
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dServer.h"
|
#include "TransportLayer.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
void MasterPackets::SendPersistentIDRequest(dServer* server, uint64_t requestID) {
|
void MasterPackets::SendPersistentIDRequest(TransportLayer* server, uint64_t requestID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_PERSISTENT_ID);
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendPersistentIDResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID) {
|
void MasterPackets::SendPersistentIDResponse(TransportLayer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_PERSISTENT_ID_RESPONSE);
|
||||||
|
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
bitStream.Write(objID);
|
bitStream.Write(objID);
|
||||||
@ -25,21 +25,21 @@ void MasterPackets::SendPersistentIDResponse(dServer* server, const SystemAddres
|
|||||||
server->Send(bitStream, sysAddr, false);
|
server->Send(bitStream, sysAddr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendZoneTransferRequest(dServer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID) {
|
void MasterPackets::SendZoneTransferRequest(TransportLayer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_ZONE_TRANSFER);
|
||||||
|
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
bitStream.Write<uint8_t>(mythranShift);
|
bitStream.Write<uint8_t>(mythranShift);
|
||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
bitStream.Write(cloneID);
|
bitStream.Write(cloneID);
|
||||||
|
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint32_t cloneID, const std::string& password) {
|
void MasterPackets::SendZoneCreatePrivate(TransportLayer* server, uint32_t zoneID, uint32_t cloneID, const std::string& password) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::CREATE_PRIVATE_ZONE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::CREATE_PRIVATE_ZONE);
|
||||||
|
|
||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
bitStream.Write(cloneID);
|
bitStream.Write(cloneID);
|
||||||
@ -49,12 +49,12 @@ void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint
|
|||||||
bitStream.Write<char>(character);
|
bitStream.Write<char>(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID, bool mythranShift, const std::string& password) {
|
void MasterPackets::SendZoneRequestPrivate(TransportLayer* server, uint64_t requestID, bool mythranShift, const std::string& password) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PRIVATE_ZONE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_PRIVATE_ZONE);
|
||||||
|
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
bitStream.Write<uint8_t>(mythranShift);
|
bitStream.Write<uint8_t>(mythranShift);
|
||||||
@ -64,22 +64,22 @@ void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID,
|
|||||||
bitStream.Write<char>(character);
|
bitStream.Write<char>(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendWorldReady(dServer* server, LWOMAPID zoneId, LWOINSTANCEID instanceId) {
|
void MasterPackets::SendWorldReady(TransportLayer* server, LWOMAPID zoneId, LWOINSTANCEID instanceId) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::WORLD_READY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::WORLD_READY);
|
||||||
|
|
||||||
bitStream.Write(zoneId);
|
bitStream.Write(zoneId);
|
||||||
bitStream.Write(instanceId);
|
bitStream.Write(instanceId);
|
||||||
|
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendZoneTransferResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort) {
|
void MasterPackets::SendZoneTransferResponse(TransportLayer* server, const SystemAddress& sysAddr, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_ZONE_TRANSFER_RESPONSE);
|
||||||
|
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
bitStream.Write<uint8_t>(mythranShift);
|
bitStream.Write<uint8_t>(mythranShift);
|
||||||
@ -109,9 +109,9 @@ void MasterPackets::HandleServerInfo(Packet* packet) {
|
|||||||
//TODO: Actually mark this server as an available server in the manager
|
//TODO: Actually mark this server as an available server in the manager
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterPackets::SendServerInfo(dServer* server, Packet* packet) {
|
void MasterPackets::SendServerInfo(TransportLayer* server, Packet* packet) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SERVER_INFO);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SERVER_INFO);
|
||||||
|
|
||||||
bitStream.Write(server->GetPort());
|
bitStream.Write(server->GetPort());
|
||||||
bitStream.Write(server->GetZoneID());
|
bitStream.Write(server->GetZoneID());
|
||||||
@ -119,5 +119,5 @@ void MasterPackets::SendServerInfo(dServer* server, Packet* packet) {
|
|||||||
bitStream.Write(server->GetServerType());
|
bitStream.Write(server->GetServerType());
|
||||||
bitStream.Write(LUString(server->GetIP()));
|
bitStream.Write(LUString(server->GetIP()));
|
||||||
|
|
||||||
server->SendToMaster(bitStream);
|
server->SendToManager(bitStream);
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,23 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "RakNetTypes.h"
|
#include "RakNetTypes.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
class dServer;
|
class TransportLayer;
|
||||||
|
|
||||||
namespace MasterPackets {
|
namespace MasterPackets {
|
||||||
void SendPersistentIDRequest(dServer* server, uint64_t requestID); //Called from the World server
|
void SendPersistentIDRequest(TransportLayer* server, uint64_t requestID); //Called from the World server
|
||||||
void SendPersistentIDResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID);
|
void SendPersistentIDResponse(TransportLayer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID);
|
||||||
|
|
||||||
void SendZoneTransferRequest(dServer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID);
|
void SendZoneTransferRequest(TransportLayer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID);
|
||||||
void SendZoneTransferResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort);
|
void SendZoneTransferResponse(TransportLayer* server, const SystemAddress& sysAddr, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort);
|
||||||
|
|
||||||
void HandleServerInfo(Packet* packet);
|
void HandleServerInfo(Packet* packet);
|
||||||
void SendServerInfo(dServer* server, Packet* packet);
|
void SendServerInfo(TransportLayer* server, Packet* packet);
|
||||||
|
|
||||||
void SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint32_t cloneID, const std::string& password);
|
void SendZoneCreatePrivate(TransportLayer* server, uint32_t zoneID, uint32_t cloneID, const std::string& password);
|
||||||
|
|
||||||
void SendZoneRequestPrivate(dServer* server, uint64_t requestID, bool mythranShift, const std::string& password);
|
void SendZoneRequestPrivate(TransportLayer* server, uint64_t requestID, bool mythranShift, const std::string& password);
|
||||||
|
|
||||||
void SendWorldReady(dServer* server, LWOMAPID zoneId, LWOINSTANCEID instanceId);
|
void SendWorldReady(TransportLayer* server, LWOMAPID zoneId, LWOINSTANCEID instanceId);
|
||||||
|
|
||||||
void HandleSetSessionKey(Packet* packet);
|
void HandleSetSessionKey(Packet* packet);
|
||||||
}
|
}
|
||||||
|
48
dNet/RakNetPeer.cpp
Normal file
48
dNet/RakNetPeer.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "RakNetPeer.h"
|
||||||
|
|
||||||
|
#include "RakPeerInterface.h"
|
||||||
|
|
||||||
|
RakNetPeer::RakNetPeer(RakPeerInterface* peer, const std::string& ip, int port, const std::string& password)
|
||||||
|
{
|
||||||
|
m_Peer = peer;
|
||||||
|
m_IP = ip;
|
||||||
|
m_Port = port;
|
||||||
|
m_Password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNetPeer::~RakNetPeer()
|
||||||
|
{
|
||||||
|
delete m_Peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetPeer::Send(
|
||||||
|
const RakNet::BitStream* bitStream,
|
||||||
|
PacketPriority priority,
|
||||||
|
PacketReliability reliability,
|
||||||
|
char orderingChannel,
|
||||||
|
SystemAddress systemAddress,
|
||||||
|
bool broadcast
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_Peer->Send(bitStream, priority, reliability, orderingChannel, systemAddress, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetPeer::Disconnect()
|
||||||
|
{
|
||||||
|
m_Peer->Shutdown(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetPeer::Reconnect()
|
||||||
|
{
|
||||||
|
m_Peer->Connect(m_IP.c_str(), m_Port, m_Password.c_str(), m_Password.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* RakNetPeer::Receive()
|
||||||
|
{
|
||||||
|
return m_Peer->Receive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetPeer::DeallocatePacket(Packet* packet)
|
||||||
|
{
|
||||||
|
m_Peer->DeallocatePacket(packet);
|
||||||
|
}
|
32
dNet/RakNetPeer.h
Normal file
32
dNet/RakNetPeer.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
|
||||||
|
class RakNetPeer : public TransportPeerInterface {
|
||||||
|
public:
|
||||||
|
RakNetPeer(RakPeerInterface* peer, const std::string& ip, int port, const std::string& password);
|
||||||
|
~RakNetPeer();
|
||||||
|
|
||||||
|
void Send(
|
||||||
|
const RakNet::BitStream* bitStream,
|
||||||
|
PacketPriority priority,
|
||||||
|
PacketReliability reliability,
|
||||||
|
char orderingChannel,
|
||||||
|
SystemAddress systemAddress,
|
||||||
|
bool broadcast
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void Disconnect() override;
|
||||||
|
|
||||||
|
void Reconnect() override;
|
||||||
|
|
||||||
|
Packet* Receive() override;
|
||||||
|
|
||||||
|
void DeallocatePacket(Packet* packet) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RakPeerInterface* m_Peer;
|
||||||
|
std::string m_IP;
|
||||||
|
int m_Port;
|
||||||
|
std::string m_Password;
|
||||||
|
};
|
272
dNet/RakNetTransportLayer.cpp
Normal file
272
dNet/RakNetTransportLayer.cpp
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
#define _VARIADIC_MAX 10
|
||||||
|
#include "RakNetTransportLayer.h"
|
||||||
|
#include "dNetCommon.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
|
#include "RakNetworkFactory.h"
|
||||||
|
#include "MessageIdentifiers.h"
|
||||||
|
#include "eConnectionType.h"
|
||||||
|
#include "eServerMessageType.h"
|
||||||
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "MasterPackets.h"
|
||||||
|
#include "ZoneInstanceManager.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
#include "RakNetPeer.h"
|
||||||
|
|
||||||
|
//! Replica Constructor class
|
||||||
|
class ReplicaConstructor : public ReceiveConstructionInterface {
|
||||||
|
public:
|
||||||
|
ReplicaReturnResult ReceiveConstruction(RakNet::BitStream* inBitStream, RakNetTime timestamp, NetworkID networkID, NetworkIDObject* existingObject, SystemAddress senderId, ReplicaManager* caller) {
|
||||||
|
return REPLICA_PROCESSING_DONE;
|
||||||
|
}
|
||||||
|
} ConstructionCB;
|
||||||
|
|
||||||
|
//! Replica Download Sender class
|
||||||
|
class ReplicaSender : public SendDownloadCompleteInterface {
|
||||||
|
public:
|
||||||
|
ReplicaReturnResult SendDownloadComplete(RakNet::BitStream* outBitStream, RakNetTime currentTime, SystemAddress senderId, ReplicaManager* caller) {
|
||||||
|
return REPLICA_PROCESSING_DONE;
|
||||||
|
}
|
||||||
|
} SendDownloadCompleteCB;
|
||||||
|
|
||||||
|
//! Replica Download Receiver class
|
||||||
|
class ReplicaReceiever : public ReceiveDownloadCompleteInterface {
|
||||||
|
public:
|
||||||
|
ReplicaReturnResult ReceiveDownloadComplete(RakNet::BitStream* inBitStream, SystemAddress senderId, ReplicaManager* caller) {
|
||||||
|
return REPLICA_PROCESSING_DONE;
|
||||||
|
}
|
||||||
|
} ReceiveDownloadCompleteCB;
|
||||||
|
|
||||||
|
RakNetTransportLayer::RakNetTransportLayer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string ManagerIP, int ManagerPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
|
||||||
|
mIP = ip;
|
||||||
|
mPort = port;
|
||||||
|
mZoneID = zoneID;
|
||||||
|
mInstanceID = instanceID;
|
||||||
|
mMaxConnections = maxConnections;
|
||||||
|
mIsInternal = isInternal;
|
||||||
|
mUseEncryption = useEncryption;
|
||||||
|
mLogger = logger;
|
||||||
|
mManagerIP = ManagerIP;
|
||||||
|
mManagerPort = ManagerPort;
|
||||||
|
mManagerConnectionActive = false;
|
||||||
|
mNetIDManager = nullptr;
|
||||||
|
mReplicaManager = nullptr;
|
||||||
|
mServerType = serverType;
|
||||||
|
mConfig = config;
|
||||||
|
mShouldShutdown = lastSignal;
|
||||||
|
mIsOkay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNetTransportLayer::~RakNetTransportLayer() {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* RakNetTransportLayer::ReceiveFromManager() {
|
||||||
|
if (!mManagerPeer) return nullptr;
|
||||||
|
if (!mManagerConnectionActive) ConnectToManager();
|
||||||
|
|
||||||
|
Packet* packet = mManagerPeer->Receive();
|
||||||
|
if (packet) {
|
||||||
|
if (packet->length < 1) { mManagerPeer->DeallocatePacket(packet); return nullptr; }
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
|
LOG("Lost our connection to Manager, shutting DOWN!");
|
||||||
|
mManagerConnectionActive = false;
|
||||||
|
//ConnectToManager(); //We'll just shut down now
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
||||||
|
LOG("Established connection to Manager, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
||||||
|
mManagerConnectionActive = true;
|
||||||
|
mManagerSystemAddress = packet->systemAddress;
|
||||||
|
MasterPackets::SendServerInfo(this, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||||
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||||
|
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||||
|
case eManagerMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
||||||
|
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eManagerMessageType::SHUTDOWN:
|
||||||
|
*mShouldShutdown = -2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//When we handle these packets in World instead RakNetTransportLayer, we just return the packet's pointer.
|
||||||
|
default:
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mManagerPeer->DeallocatePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* RakNetTransportLayer::Receive() {
|
||||||
|
return mPeer->Receive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::DeallocatePacket(Packet* packet) {
|
||||||
|
mPeer->DeallocatePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::DeallocateManagerPacket(Packet* packet) {
|
||||||
|
mManagerPeer->DeallocatePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) {
|
||||||
|
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::SendToManager(RakNet::BitStream& bitStream) {
|
||||||
|
if (!mManagerConnectionActive) ConnectToManager();
|
||||||
|
mManagerPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, mManagerSystemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) {
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY);
|
||||||
|
bitStream.Write(disconNotifyID);
|
||||||
|
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, false);
|
||||||
|
|
||||||
|
mPeer->CloseConnection(sysAddr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RakNetTransportLayer::IsConnected(const SystemAddress& sysAddr) {
|
||||||
|
return mPeer->IsConnected(sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RakNetTransportLayer::Startup() {
|
||||||
|
mIsOkay = StartPeer();
|
||||||
|
|
||||||
|
//Forcibly log to both the console and our file what ip, port and possibly zoneID / instanceID we're running on:
|
||||||
|
bool prevLogSetting = mLogger->GetLogToConsole();
|
||||||
|
mLogger->SetLogToConsole(true);
|
||||||
|
|
||||||
|
if (mIsOkay) {
|
||||||
|
if (mZoneID == 0)
|
||||||
|
LOG("%s Server is listening on %s:%i with encryption: %i", StringifiedEnum::ToString(mServerType).data(), mIP.c_str(), mPort, int(mUseEncryption));
|
||||||
|
else
|
||||||
|
LOG("%s Server is listening on %s:%i with encryption: %i, running zone %i / %i", StringifiedEnum::ToString(mServerType).data(), mIP.c_str(), mPort, int(mUseEncryption), mZoneID, mInstanceID);
|
||||||
|
} else { LOG("FAILED TO START SERVER ON IP/PORT: %s:%i", mIP.c_str(), mPort); return false; }
|
||||||
|
|
||||||
|
mLogger->SetLogToConsole(prevLogSetting);
|
||||||
|
|
||||||
|
//Connect to Manager if we are not Manager:
|
||||||
|
if (mServerType != ServerType::Manager) {
|
||||||
|
SetupForManagerConnection();
|
||||||
|
if (!ConnectToManager()) {
|
||||||
|
LOG("Failed ConnectToManager!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set up Replica if we're a world server:
|
||||||
|
if (mServerType == ServerType::World) {
|
||||||
|
/*
|
||||||
|
mNetIDManager = new NetworkIDManager();
|
||||||
|
mNetIDManager->SetIsNetworkIDAuthority(true);
|
||||||
|
|
||||||
|
mReplicaManager = new ReplicaManager();
|
||||||
|
mReplicaManager->SetAutoParticipateNewConnections(false);
|
||||||
|
mReplicaManager->SetAutoConstructToNewParticipants(false);
|
||||||
|
mReplicaManager->SetAutoSerializeInScope(true);
|
||||||
|
mReplicaManager->SetReceiveConstructionCB(&ConstructionCB);
|
||||||
|
mReplicaManager->SetDownloadCompleteCB(&SendDownloadCompleteCB, &ReceiveDownloadCompleteCB);
|
||||||
|
|
||||||
|
mPeer->AttachPlugin(mReplicaManager);
|
||||||
|
mPeer->SetNetworkIDManager(mNetIDManager);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return mIsOkay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::UpdateMaximumMtuSize() {
|
||||||
|
auto maxMtuSize = mConfig->GetValue("maximum_mtu_size");
|
||||||
|
mPeer->SetMTUSize(maxMtuSize.empty() ? 1228 : std::stoi(maxMtuSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::UpdateBandwidthLimit() {
|
||||||
|
auto newBandwidth = mConfig->GetValue("maximum_outgoing_bandwidth");
|
||||||
|
mPeer->SetPerConnectionOutgoingBandwidthLimit(!newBandwidth.empty() ? std::stoi(newBandwidth) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::Shutdown() {
|
||||||
|
if (mPeer) {
|
||||||
|
mPeer->Shutdown(1000);
|
||||||
|
RakNetworkFactory::DestroyRakPeerInterface(mPeer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNetIDManager) {
|
||||||
|
delete mNetIDManager;
|
||||||
|
mNetIDManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReplicaManager) {
|
||||||
|
delete mReplicaManager;
|
||||||
|
mReplicaManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mServerType != ServerType::Manager && mManagerPeer) {
|
||||||
|
mManagerPeer->Shutdown(1000);
|
||||||
|
RakNetworkFactory::DestroyRakPeerInterface(mManagerPeer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RakNetTransportLayer::StartPeer() {
|
||||||
|
mSocketDescriptor = SocketDescriptor(uint16_t(mPort), 0);
|
||||||
|
mPeer = RakNetworkFactory::GetRakPeerInterface();
|
||||||
|
|
||||||
|
if (!mPeer) return false;
|
||||||
|
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
||||||
|
|
||||||
|
if (mIsInternal) {
|
||||||
|
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
||||||
|
} else {
|
||||||
|
UpdateBandwidthLimit();
|
||||||
|
UpdateMaximumMtuSize();
|
||||||
|
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
||||||
|
if (mUseEncryption) mPeer->InitializeSecurity(NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RakNetTransportLayer::SetupForManagerConnection() {
|
||||||
|
mManagerSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
|
||||||
|
mManagerPeer = RakNetworkFactory::GetRakPeerInterface();
|
||||||
|
bool ret = mManagerPeer->Startup(1, 30, &mManagerSocketDescriptor, 1);
|
||||||
|
if (!ret) LOG("Failed ManagerPeer Startup!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RakNetTransportLayer::ConnectToManager() {
|
||||||
|
//LOG("Connection to Manager %s:%d", mManagerIP.c_str(), mManagerPort);
|
||||||
|
return mManagerPeer->Connect(mManagerIP.c_str(), mManagerPort, "3.25 DARKFLAME1", 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RakNetTransportLayer::GetPing(const SystemAddress& sysAddr) const {
|
||||||
|
return mPeer->GetAveragePing(sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RakNetTransportLayer::GetLatestPing(const SystemAddress& sysAddr) const {
|
||||||
|
return mPeer->GetLastPing(sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportPeerInterface* RakNetTransportLayer::CreateOutgoingTransport(uint32_t peerPort, const std::string& ip, uint32_t port, const std::string& password) const {
|
||||||
|
auto sock = SocketDescriptor(static_cast<uint16_t>(peerPort), 0);
|
||||||
|
auto* peer = RakNetworkFactory::GetRakPeerInterface();
|
||||||
|
peer->Startup(1, 30, &sock, 1);
|
||||||
|
peer->Connect(ip.c_str(), port, "3.25 ND1", 8);
|
||||||
|
|
||||||
|
return new RakNetPeer(peer, ip, port, password);
|
||||||
|
}
|
103
dNet/RakNetTransportLayer.h
Normal file
103
dNet/RakNetTransportLayer.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <csignal>
|
||||||
|
#include "RakPeerInterface.h"
|
||||||
|
#include "ReplicaManager.h"
|
||||||
|
#include "NetworkIDManager.h"
|
||||||
|
|
||||||
|
#include "TransportLayer.h"
|
||||||
|
|
||||||
|
class RakNetTransportLayer : public TransportLayer {
|
||||||
|
public:
|
||||||
|
RakNetTransportLayer(
|
||||||
|
const std::string& ip,
|
||||||
|
int port,
|
||||||
|
int instanceID,
|
||||||
|
int maxConnections,
|
||||||
|
bool isInternal,
|
||||||
|
bool useEncryption,
|
||||||
|
Logger* logger,
|
||||||
|
const std::string managerIP,
|
||||||
|
int managerPort,
|
||||||
|
ServerType serverType,
|
||||||
|
dConfig* config,
|
||||||
|
Game::signal_t* shouldShutdown,
|
||||||
|
unsigned int zoneID = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
~RakNetTransportLayer();
|
||||||
|
|
||||||
|
Packet* ReceiveFromManager() override;
|
||||||
|
Packet* Receive() override;
|
||||||
|
void DeallocatePacket(Packet* packet) override;
|
||||||
|
void DeallocateManagerPacket(Packet* packet) override;
|
||||||
|
void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) override;
|
||||||
|
void SendToManager(RakNet::BitStream& bitStream) override;
|
||||||
|
|
||||||
|
void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) override;
|
||||||
|
|
||||||
|
bool IsConnected(const SystemAddress& sysAddr) override;
|
||||||
|
const std::string& GetIP() const override { return mIP; }
|
||||||
|
const int GetPort() const override { return mPort; }
|
||||||
|
const int GetMaxConnections() const override { return mMaxConnections; }
|
||||||
|
const bool GetIsEncrypted() const override { return mUseEncryption; }
|
||||||
|
const bool GetIsInternal() const override { return mIsInternal; }
|
||||||
|
const bool GetIsOkay() const override { return mIsOkay; }
|
||||||
|
Logger* GetLogger() const override { return mLogger; }
|
||||||
|
const bool GetIsConnectedToManager() const override { return mManagerConnectionActive; }
|
||||||
|
const unsigned int GetZoneID() const override { return mZoneID; }
|
||||||
|
const int GetInstanceID() const override { return mInstanceID; }
|
||||||
|
int GetPing(const SystemAddress& sysAddr) const override;
|
||||||
|
int GetLatestPing(const SystemAddress& sysAddr) const override;
|
||||||
|
|
||||||
|
const ServerType GetServerType() const override { return mServerType; }
|
||||||
|
|
||||||
|
void UpdateBandwidthLimit();
|
||||||
|
void UpdateMaximumMtuSize();
|
||||||
|
|
||||||
|
TransportPeerInterface* CreateOutgoingTransport(
|
||||||
|
uint32_t peerPort,
|
||||||
|
const std::string& ip,
|
||||||
|
uint32_t port,
|
||||||
|
const std::string& password
|
||||||
|
) const override;
|
||||||
|
|
||||||
|
bool Startup() override;
|
||||||
|
void Shutdown() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool StartPeer();
|
||||||
|
|
||||||
|
void SetupForManagerConnection();
|
||||||
|
bool ConnectToManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger* mLogger = nullptr;
|
||||||
|
dConfig* mConfig = nullptr;
|
||||||
|
RakPeerInterface* mPeer = nullptr;
|
||||||
|
ReplicaManager* mReplicaManager = nullptr;
|
||||||
|
NetworkIDManager* mNetIDManager = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to shut down the server. Pointer to Game::lastSignal.
|
||||||
|
*/
|
||||||
|
Game::signal_t* mShouldShutdown = nullptr;
|
||||||
|
SocketDescriptor mSocketDescriptor;
|
||||||
|
std::string mIP;
|
||||||
|
int mPort;
|
||||||
|
int mMaxConnections;
|
||||||
|
unsigned int mZoneID;
|
||||||
|
int mInstanceID;
|
||||||
|
bool mUseEncryption;
|
||||||
|
bool mIsInternal;
|
||||||
|
bool mIsOkay;
|
||||||
|
bool mManagerConnectionActive;
|
||||||
|
ServerType mServerType;
|
||||||
|
|
||||||
|
RakPeerInterface* mManagerPeer = nullptr;
|
||||||
|
SocketDescriptor mManagerSocketDescriptor;
|
||||||
|
SystemAddress mManagerSystemAddress;
|
||||||
|
std::string mManagerIP;
|
||||||
|
int mManagerPort;
|
||||||
|
};
|
269
dNet/TcpPeer.cpp
Normal file
269
dNet/TcpPeer.cpp
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#include "TcpPeer.h"
|
||||||
|
|
||||||
|
#include <RakNetTypes.h>
|
||||||
|
#include <BitStream.h>
|
||||||
|
#include <random>
|
||||||
|
#include <MessageIdentifiers.h>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
|
||||||
|
TcpPeer::TcpPeer(const std::string& ip, int port, const std::string& password, bool useTls, bool verifyCertificate)
|
||||||
|
: m_IP(ip), m_Port(port), m_Password(password), m_UseTls(useTls), m_VerifyCertificate(verifyCertificate),
|
||||||
|
m_Resolver(m_IOService), m_Work(m_IOService), m_IsConnected(false)
|
||||||
|
{
|
||||||
|
if (m_IP == "localhost") {
|
||||||
|
m_IP = "127.0.0.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the I/O thread for asynchronous operations
|
||||||
|
m_IOThread = std::thread([this]() {
|
||||||
|
m_IOService.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
Reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
TcpPeer::~TcpPeer() {
|
||||||
|
Disconnect();
|
||||||
|
|
||||||
|
// Ensure the I/O thread joins
|
||||||
|
if (m_IOThread.joinable()) {
|
||||||
|
m_IOThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::Reconnect() {
|
||||||
|
Disconnect();
|
||||||
|
|
||||||
|
std::scoped_lock lock(m_ConnectMutex);
|
||||||
|
|
||||||
|
boost::asio::ip::tcp::resolver::query query(m_IP, std::to_string(m_Port));
|
||||||
|
auto endpointIterator = m_Resolver.resolve(query);
|
||||||
|
|
||||||
|
if (!endpointIterator->endpoint().address().is_v4()) {
|
||||||
|
LOG("Failed to resolve IP address!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print out the resolved IP and port
|
||||||
|
LOG("Resolved IP: %s, Port: %d", endpointIterator->endpoint().address().to_v4().to_string().c_str(), endpointIterator->endpoint().port());
|
||||||
|
|
||||||
|
// Just use a random 32-bit integer for the system address
|
||||||
|
m_PeerSystemAddress.binaryAddress = endpointIterator->endpoint().address().to_v4().to_uint();
|
||||||
|
m_PeerSystemAddress.port = endpointIterator->endpoint().port();
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLContext = std::make_unique<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
|
||||||
|
m_SSLContext->set_verify_mode(m_VerifyCertificate ? boost::asio::ssl::verify_peer : boost::asio::ssl::verify_none);
|
||||||
|
m_SSLStream = std::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>(m_IOService, *m_SSLContext);
|
||||||
|
m_SSLStream->set_verify_callback(boost::asio::ssl::rfc2818_verification(m_IP));
|
||||||
|
|
||||||
|
boost::asio::async_connect(m_SSLStream->lowest_layer(), endpointIterator,
|
||||||
|
[this, &lock](const boost::system::error_code& ec, auto) { HandleConnect(ec); });
|
||||||
|
} else {
|
||||||
|
m_Socket = std::make_unique<boost::asio::ip::tcp::socket>(m_IOService);
|
||||||
|
boost::asio::async_connect(*m_Socket, endpointIterator,
|
||||||
|
[this, &lock](const boost::system::error_code& ec, auto) { HandleConnect(ec); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::HandleConnect(const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLStream->async_handshake(boost::asio::ssl::stream_base::client,
|
||||||
|
[this](const boost::system::error_code& handshakeError) {
|
||||||
|
if (!handshakeError) {
|
||||||
|
SendConnectionRequest();
|
||||||
|
StartAsyncRead();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG("Handshake error: %s", handshakeError.message().c_str());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SendConnectionRequest();
|
||||||
|
StartAsyncRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_IsConnected = false;
|
||||||
|
|
||||||
|
m_Condition.notify_all();
|
||||||
|
|
||||||
|
LOG("Connect error: %s", ec.message().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::SendConnectionRequest() {
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
bitStream.Write<uint8_t>(ID_CONNECTION_REQUEST);
|
||||||
|
for (const auto& c : m_Password) {
|
||||||
|
bitStream.Write<uint8_t>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, m_PeerSystemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::OnReceive(Packet* packet) {
|
||||||
|
if (packet->length == 0) {
|
||||||
|
delete[] packet->data;
|
||||||
|
delete packet;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
else if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
||||||
|
m_IsConnected = true;
|
||||||
|
m_Condition.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
|
m_ReceiveBuffer.push(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TcpPeer::IsConnected() {
|
||||||
|
std::scoped_lock lock(m_ConnectMutex);
|
||||||
|
|
||||||
|
return m_IsConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TcpPeer::WaitForConnection() {
|
||||||
|
std::unique_lock<std::mutex> lock(m_ConnectMutex);
|
||||||
|
|
||||||
|
if (m_IsConnected) {
|
||||||
|
LOG("Already connected to the server!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_Condition.wait_for(lock, std::chrono::seconds(5), [this]() { return m_IsConnected; })) {
|
||||||
|
LOG("Failed to connect to the server!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_IsConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::StartAsyncRead() {
|
||||||
|
m_HeaderBuffer.resize(sizeof(uint32_t));
|
||||||
|
|
||||||
|
auto readHeaderCallback = [this](const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
OnReadHeader(ec, bytesTransferred);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
boost::asio::async_read(*m_SSLStream, boost::asio::buffer(m_HeaderBuffer), readHeaderCallback);
|
||||||
|
} else {
|
||||||
|
boost::asio::async_read(*m_Socket, boost::asio::buffer(m_HeaderBuffer), readHeaderCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::OnReadHeader(const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
if (!ec) {
|
||||||
|
uint32_t size = 0;
|
||||||
|
std::memcpy(&size, m_HeaderBuffer.data(), sizeof(size));
|
||||||
|
|
||||||
|
m_BodyBuffer.resize(size);
|
||||||
|
|
||||||
|
auto readBodyCallback = [this](const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
OnReadBody(ec, bytesTransferred);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
boost::asio::async_read(*m_SSLStream, boost::asio::buffer(m_BodyBuffer), readBodyCallback);
|
||||||
|
} else {
|
||||||
|
boost::asio::async_read(*m_Socket, boost::asio::buffer(m_BodyBuffer), readBodyCallback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG("Read header error: %s", ec.message().c_str());
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::OnReadBody(const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
if (!ec) {
|
||||||
|
auto* packet = new Packet();
|
||||||
|
packet->data = new uint8_t[m_BodyBuffer.size()];
|
||||||
|
std::memcpy(packet->data, m_BodyBuffer.data(), m_BodyBuffer.size());
|
||||||
|
packet->length = m_BodyBuffer.size();
|
||||||
|
packet->bitSize = packet->length * 8;
|
||||||
|
packet->systemAddress = m_PeerSystemAddress;
|
||||||
|
|
||||||
|
OnReceive(packet);
|
||||||
|
|
||||||
|
// Start reading the next packet
|
||||||
|
StartAsyncRead();
|
||||||
|
} else {
|
||||||
|
LOG("Read body error: %s", ec.message().c_str());
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::Send(
|
||||||
|
const RakNet::BitStream* bitStream,
|
||||||
|
PacketPriority priority,
|
||||||
|
PacketReliability reliability,
|
||||||
|
char orderingChannel,
|
||||||
|
SystemAddress systemAddress,
|
||||||
|
bool broadcast
|
||||||
|
) {
|
||||||
|
auto* data = bitStream->GetData();
|
||||||
|
uint32_t size = bitStream->GetNumberOfBytesUsed();
|
||||||
|
std::vector<uint8_t> sendBuffer(sizeof(uint32_t) + size);
|
||||||
|
|
||||||
|
std::memcpy(sendBuffer.data(), &size, sizeof(size));
|
||||||
|
std::memcpy(sendBuffer.data() + sizeof(uint32_t), data, size);
|
||||||
|
|
||||||
|
auto sendCallback = [](const boost::system::error_code& ec, std::size_t /*bytesTransferred*/) {
|
||||||
|
if (ec) {
|
||||||
|
LOG("Send error: %s", ec.message().c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
boost::asio::async_write(*m_SSLStream, boost::asio::buffer(sendBuffer), sendCallback);
|
||||||
|
} else {
|
||||||
|
boost::asio::async_write(*m_Socket, boost::asio::buffer(sendBuffer), sendCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* TcpPeer::Receive() {
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
|
||||||
|
if (m_ReceiveBuffer.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* packet = m_ReceiveBuffer.front();
|
||||||
|
m_ReceiveBuffer.pop();
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::Disconnect() {
|
||||||
|
std::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
|
if (m_IsConnected) {
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLStream->lowest_layer().close();
|
||||||
|
} else {
|
||||||
|
m_Socket->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpPeer::DeallocatePacket(Packet* packet) {
|
||||||
|
delete[] packet->data;
|
||||||
|
delete packet;
|
||||||
|
}
|
73
dNet/TcpPeer.h
Normal file
73
dNet/TcpPeer.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/ssl.hpp>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <memory>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
|
||||||
|
class TcpPeer : public TransportPeerInterface {
|
||||||
|
public:
|
||||||
|
TcpPeer(const std::string& ip, int port, const std::string& password, bool useTls, bool verifyCertificate);
|
||||||
|
~TcpPeer();
|
||||||
|
|
||||||
|
void Send(
|
||||||
|
const RakNet::BitStream* bitStream,
|
||||||
|
PacketPriority priority,
|
||||||
|
PacketReliability reliability,
|
||||||
|
char orderingChannel,
|
||||||
|
SystemAddress systemAddress,
|
||||||
|
bool broadcast
|
||||||
|
) override;
|
||||||
|
|
||||||
|
void Disconnect() override;
|
||||||
|
void Reconnect() override;
|
||||||
|
|
||||||
|
Packet* Receive() override;
|
||||||
|
void DeallocatePacket(Packet* packet) override;
|
||||||
|
|
||||||
|
bool IsConnected();
|
||||||
|
bool WaitForConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void StartAsyncRead();
|
||||||
|
void OnReadHeader(const boost::system::error_code& ec, std::size_t bytesTransferred);
|
||||||
|
void OnReadBody(const boost::system::error_code& ec, std::size_t bytesTransferred);
|
||||||
|
void HandleConnect(const boost::system::error_code& ec);
|
||||||
|
|
||||||
|
void SendConnectionRequest();
|
||||||
|
|
||||||
|
void OnReceive(Packet* packet);
|
||||||
|
|
||||||
|
boost::asio::io_service m_IOService;
|
||||||
|
boost::asio::ip::tcp::resolver m_Resolver;
|
||||||
|
std::unique_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
||||||
|
std::unique_ptr<boost::asio::ssl::context> m_SSLContext;
|
||||||
|
std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_SSLStream;
|
||||||
|
|
||||||
|
|
||||||
|
std::string m_IP;
|
||||||
|
int m_Port;
|
||||||
|
std::string m_Password;
|
||||||
|
bool m_UseTls;
|
||||||
|
bool m_VerifyCertificate;
|
||||||
|
SystemAddress m_PeerSystemAddress;
|
||||||
|
bool m_IsConnected;
|
||||||
|
|
||||||
|
std::mutex m_ConnectMutex;
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
std::condition_variable m_Condition;
|
||||||
|
|
||||||
|
std::queue<Packet*> m_ReceiveBuffer;
|
||||||
|
|
||||||
|
std::vector<uint8_t> m_HeaderBuffer;
|
||||||
|
std::vector<uint8_t> m_BodyBuffer;
|
||||||
|
|
||||||
|
std::thread m_IOThread;
|
||||||
|
boost::asio::io_service::work m_Work;
|
||||||
|
};
|
307
dNet/TcpSession.cpp
Normal file
307
dNet/TcpSession.cpp
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
#include "TcpSession.h"
|
||||||
|
|
||||||
|
#include "TcpTransportLayer.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "MessageIdentifiers.h"
|
||||||
|
|
||||||
|
#include <boost/endian/conversion.hpp>
|
||||||
|
|
||||||
|
TcpSession::TcpSession(boost::asio::io_service& io_service, boost::asio::ssl::context* sslContext, TcpTransportLayer* server):
|
||||||
|
m_PingTimerObject(io_service) {
|
||||||
|
m_Server = server;
|
||||||
|
|
||||||
|
m_UseTls = server->GetIsEncrypted();
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLStream = std::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>(io_service, *sslContext);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_Socket = std::make_unique<boost::asio::ip::tcp::socket>(io_service);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
m_ReadyForUserPackets = false;
|
||||||
|
m_PingCount = 0;
|
||||||
|
m_CumulativePing = 0;
|
||||||
|
m_LastPing = 0;
|
||||||
|
m_PingTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::Start() {
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLStream->async_handshake(boost::asio::ssl::stream_base::server,
|
||||||
|
[this](const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
m_SystemAddress.port = m_SSLStream->lowest_layer().remote_endpoint().port();
|
||||||
|
if (m_SSLStream->lowest_layer().remote_endpoint().address().is_v4()) {
|
||||||
|
m_SystemAddress.binaryAddress = m_SSLStream->lowest_layer().remote_endpoint().address().to_v4().to_uint();
|
||||||
|
} else {
|
||||||
|
m_SystemAddress.binaryAddress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsConnected = true;
|
||||||
|
|
||||||
|
StartAsyncRead();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
m_SystemAddress.port = m_Socket->remote_endpoint().port();
|
||||||
|
if (m_Socket->remote_endpoint().address().is_v4()) {
|
||||||
|
uint32_t address = m_Socket->remote_endpoint().address().to_v4().to_uint();
|
||||||
|
m_SystemAddress.binaryAddress = boost::endian::endian_reverse(address);
|
||||||
|
} else {
|
||||||
|
m_SystemAddress.binaryAddress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsConnected = true;
|
||||||
|
|
||||||
|
StartAsyncRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the ping timer in 5 seconds using boost
|
||||||
|
m_PingTimerObject.expires_after(std::chrono::seconds(5));
|
||||||
|
m_PingTimerObject.async_wait([this](const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
DoPing();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::Send(const std::vector<uint8_t>& data) {
|
||||||
|
auto self(shared_from_this());
|
||||||
|
auto writeCallback = [this, self](const boost::system::error_code& ec, std::size_t /*bytesTransferred*/) {
|
||||||
|
OnWrite(ec, 0); // Handle the write result
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t size = data.size();
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
// Write the size of the message
|
||||||
|
boost::asio::async_write(*m_SSLStream, boost::asio::buffer(&size, sizeof(size)), writeCallback);
|
||||||
|
boost::asio::async_write(*m_SSLStream, boost::asio::buffer(data), writeCallback);
|
||||||
|
} else {
|
||||||
|
// Write the size of the message
|
||||||
|
boost::asio::async_write(*m_Socket, boost::asio::buffer(&size, sizeof(size)), writeCallback);
|
||||||
|
boost::asio::async_write(*m_Socket, boost::asio::buffer(data), writeCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::Send(const RakNet::BitStream& data) {
|
||||||
|
auto self(shared_from_this());
|
||||||
|
auto writeCallback = [this, self](const boost::system::error_code& ec, std::size_t /*bytesTransferred*/) {
|
||||||
|
OnWrite(ec, 0); // Handle the write result
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t size = data.GetNumberOfBytesUsed();
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
// Write the size of the message
|
||||||
|
boost::asio::async_write(*m_SSLStream, boost::asio::buffer(&size, sizeof(size)), writeCallback);
|
||||||
|
boost::asio::async_write(*m_SSLStream, boost::asio::buffer(data.GetData(), size), writeCallback);
|
||||||
|
} else {
|
||||||
|
// Write the size of the message
|
||||||
|
boost::asio::async_write(*m_Socket, boost::asio::buffer(&size, sizeof(size)), writeCallback);
|
||||||
|
boost::asio::async_write(*m_Socket, boost::asio::buffer(data.GetData(), size), writeCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>& TcpSession::GetSocket() {
|
||||||
|
if (m_UseTls) {
|
||||||
|
return m_SSLStream->lowest_layer();
|
||||||
|
} else {
|
||||||
|
return *m_Socket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::StartAsyncRead() {
|
||||||
|
if (!m_IsConnected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_HeaderBuffer.resize(sizeof(uint32_t));
|
||||||
|
|
||||||
|
auto readHeaderCallback = [this](const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
OnReadHeader(ec, bytesTransferred);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (m_UseTls) {
|
||||||
|
boost::asio::async_read(*m_SSLStream, boost::asio::buffer(m_HeaderBuffer), readHeaderCallback);
|
||||||
|
} else {
|
||||||
|
boost::asio::async_read(*m_Socket, boost::asio::buffer(m_HeaderBuffer), readHeaderCallback);
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG("Exception: %s", e.what());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::OnReadHeader(const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
if (!ec) {
|
||||||
|
uint32_t size = 0;
|
||||||
|
std::memcpy(&size, m_HeaderBuffer.data(), sizeof(size));
|
||||||
|
|
||||||
|
m_BodyBuffer.resize(size);
|
||||||
|
|
||||||
|
auto readBodyCallback = [this](const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
OnReadBody(ec, bytesTransferred);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
boost::asio::async_read(*m_SSLStream, boost::asio::buffer(m_BodyBuffer), readBodyCallback);
|
||||||
|
} else {
|
||||||
|
boost::asio::async_read(*m_Socket, boost::asio::buffer(m_BodyBuffer), readBodyCallback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG("Read header error: %s", ec.message().c_str());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::OnReadBody(const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
if (!ec) {
|
||||||
|
auto* packet = new Packet();
|
||||||
|
packet->data = new uint8_t[m_BodyBuffer.size()];
|
||||||
|
std::memcpy(packet->data, m_BodyBuffer.data(), m_BodyBuffer.size());
|
||||||
|
packet->length = m_BodyBuffer.size();
|
||||||
|
packet->bitSize = packet->length * 8;
|
||||||
|
packet->systemAddress = m_SystemAddress;
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_USER_PACKET_ENUM && !m_ReadyForUserPackets) {
|
||||||
|
LOG("Received early user packet from %s:%d", m_SystemAddress.ToString(false), m_SystemAddress.port);
|
||||||
|
m_UserPacketQueue.push(packet);
|
||||||
|
}
|
||||||
|
else if (packet->data[0] == ID_INTERNAL_PING) {
|
||||||
|
HandlePing(packet);
|
||||||
|
}
|
||||||
|
else if (packet->data[0] == ID_CONNECTED_PONG) {
|
||||||
|
HandlePong(packet);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_Server->OnReceive(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
StartAsyncRead();
|
||||||
|
} else {
|
||||||
|
LOG("Read body error: %s", ec.message().c_str());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::OnWrite(const boost::system::error_code& ec, std::size_t bytesTransferred) {
|
||||||
|
if (ec) {
|
||||||
|
LOG("Write error: %s", ec.message().c_str());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::HandlePing(Packet* packet) {
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
bitStream.Write<uint8_t>(ID_CONNECTED_PONG);
|
||||||
|
bitStream.Write<uint8_t>(packet->data[1]);
|
||||||
|
bitStream.Write<uint8_t>(packet->data[2]);
|
||||||
|
bitStream.Write<uint8_t>(packet->data[3]);
|
||||||
|
bitStream.Write<uint8_t>(packet->data[4]);
|
||||||
|
bitStream.Write<uint32_t>(0);
|
||||||
|
|
||||||
|
Send(bitStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::HandlePong(Packet* packet) {
|
||||||
|
auto current = m_PingTimer;
|
||||||
|
|
||||||
|
RakNet::BitStream bitStream(packet->data, packet->length, false);
|
||||||
|
bitStream.IgnoreBytes(1);
|
||||||
|
|
||||||
|
uint32_t old = 0;
|
||||||
|
bitStream.Read(old);
|
||||||
|
|
||||||
|
m_LastPing = current - old;
|
||||||
|
m_CumulativePing += m_LastPing;
|
||||||
|
m_PingCount++;
|
||||||
|
|
||||||
|
const auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_ChronoLastPingTime);
|
||||||
|
m_AccumulatedPingTime += duration;
|
||||||
|
|
||||||
|
m_ChronoLastPongTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::DoPing() {
|
||||||
|
if (!m_IsConnected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
bitStream.Write<uint8_t>(ID_INTERNAL_PING);
|
||||||
|
bitStream.Write<uint32_t>(m_PingTimer);
|
||||||
|
|
||||||
|
Send(bitStream);
|
||||||
|
|
||||||
|
m_ChronoLastPingTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
// Start the ping timer in 5 seconds using boost
|
||||||
|
m_PingTimerObject.expires_after(std::chrono::seconds(5));
|
||||||
|
m_PingTimerObject.async_wait([this](const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
DoPing();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::ReadyForUserPackets() {
|
||||||
|
m_ReadyForUserPackets = true;
|
||||||
|
|
||||||
|
while (!m_UserPacketQueue.empty()) {
|
||||||
|
auto* packet = m_UserPacketQueue.front();
|
||||||
|
m_UserPacketQueue.pop();
|
||||||
|
|
||||||
|
m_Server->OnReceive(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float TcpSession::GetAveragePing() const {
|
||||||
|
if (m_PingCount == 0) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<float>(m_AccumulatedPingTime.count()) / m_PingCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TcpSession::GetLastPing() const {
|
||||||
|
return static_cast<float>(m_LastPing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpSession::Close() {
|
||||||
|
if (!m_IsConnected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Closing connection to %s:%d", m_SystemAddress.ToString(false), m_SystemAddress.port);
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLStream->async_shutdown([this](const boost::system::error_code& ec) {
|
||||||
|
if (ec) {
|
||||||
|
LOG("SSL shutdown error: %s", ec.message().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SSLStream->lowest_layer().close();
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
|
||||||
|
m_SSLStream.reset();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
|
||||||
|
m_Socket->close();
|
||||||
|
|
||||||
|
m_IsConnected = false;
|
||||||
|
|
||||||
|
m_Socket.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PingTimerObject.cancel();
|
||||||
|
|
||||||
|
m_Server->RemoveSession(m_SystemAddress);
|
||||||
|
}
|
80
dNet/TcpSession.h
Normal file
80
dNet/TcpSession.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/ssl.hpp>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <memory>
|
||||||
|
#include <chrono>
|
||||||
|
#include "RakNetTypes.h"
|
||||||
|
#include "eServerDisconnectIdentifiers.h"
|
||||||
|
#include "BitStream.h"
|
||||||
|
|
||||||
|
class TcpTransportLayer;
|
||||||
|
|
||||||
|
class TcpSession : public std::enable_shared_from_this<TcpSession> {
|
||||||
|
public:
|
||||||
|
TcpSession(boost::asio::io_service& io_service, boost::asio::ssl::context* sslContext, TcpTransportLayer* server);
|
||||||
|
void Start();
|
||||||
|
void Send(const std::vector<uint8_t>& data);
|
||||||
|
void Send(const RakNet::BitStream& data);
|
||||||
|
|
||||||
|
boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>& GetSocket();
|
||||||
|
|
||||||
|
bool IsConnected() const { return m_IsConnected; }
|
||||||
|
|
||||||
|
const SystemAddress& GetSystemAddress() const { return m_SystemAddress; }
|
||||||
|
|
||||||
|
bool IsReadyForUserPackets() const { return m_ReadyForUserPackets; }
|
||||||
|
|
||||||
|
void ReadyForUserPackets();
|
||||||
|
|
||||||
|
float GetAveragePing() const;
|
||||||
|
|
||||||
|
float GetLastPing() const;
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void StartAsyncRead();
|
||||||
|
|
||||||
|
void OnReadHeader(const boost::system::error_code& ec, std::size_t bytesTransferred);
|
||||||
|
|
||||||
|
void OnReadBody(const boost::system::error_code& ec, std::size_t bytesTransferred);
|
||||||
|
|
||||||
|
void OnWrite(const boost::system::error_code& ec, std::size_t bytesTransferred);
|
||||||
|
|
||||||
|
void HandlePing(Packet* packet);
|
||||||
|
|
||||||
|
void HandlePong(Packet* packet);
|
||||||
|
|
||||||
|
void DoPing();
|
||||||
|
|
||||||
|
std::unique_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
||||||
|
std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_SSLStream;
|
||||||
|
bool m_UseTls;
|
||||||
|
TcpTransportLayer* m_Server;
|
||||||
|
SystemAddress m_SystemAddress;
|
||||||
|
bool m_IsConnected;
|
||||||
|
bool m_ReadyForUserPackets;
|
||||||
|
std::queue<Packet*> m_UserPacketQueue;
|
||||||
|
|
||||||
|
std::vector<uint8_t> m_HeaderBuffer;
|
||||||
|
std::vector<uint8_t> m_BodyBuffer;
|
||||||
|
|
||||||
|
// Ping handling
|
||||||
|
int32_t m_CumulativePing;
|
||||||
|
int32_t m_PingCount;
|
||||||
|
int32_t m_LastPing;
|
||||||
|
int32_t m_PingTimer;
|
||||||
|
boost::asio::steady_timer m_PingTimerObject;
|
||||||
|
|
||||||
|
// Last ping time
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_ChronoLastPingTime;
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_ChronoLastPongTime;
|
||||||
|
// Accumulated ping time
|
||||||
|
std::chrono::milliseconds m_AccumulatedPingTime;
|
||||||
|
};
|
426
dNet/TcpTransportLayer.cpp
Normal file
426
dNet/TcpTransportLayer.cpp
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
#define _VARIADIC_MAX 10
|
||||||
|
|
||||||
|
#include "dNetCommon.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
|
#include "RakNetworkFactory.h"
|
||||||
|
#include "MessageIdentifiers.h"
|
||||||
|
#include "eConnectionType.h"
|
||||||
|
#include "eServerMessageType.h"
|
||||||
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "MasterPackets.h"
|
||||||
|
#include "ZoneInstanceManager.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
#include "TcpTransportLayer.h"
|
||||||
|
#include "TcpSession.h"
|
||||||
|
#include "TcpPeer.h"
|
||||||
|
|
||||||
|
|
||||||
|
TcpTransportLayer::TcpTransportLayer(
|
||||||
|
const std::string& ip,
|
||||||
|
int port,
|
||||||
|
int instanceID,
|
||||||
|
int maxConnections,
|
||||||
|
bool isInternal,
|
||||||
|
bool useEncryption,
|
||||||
|
Logger* logger,
|
||||||
|
const std::string managerIP,
|
||||||
|
int managerPort,
|
||||||
|
ServerType serverType,
|
||||||
|
dConfig* config,
|
||||||
|
Game::signal_t* shouldShutdown,
|
||||||
|
unsigned int zoneID
|
||||||
|
) {
|
||||||
|
m_IP = ip;
|
||||||
|
m_Port = port;
|
||||||
|
m_ZoneID = zoneID;
|
||||||
|
m_InstanceID = instanceID;
|
||||||
|
m_MaxConnections = maxConnections;
|
||||||
|
m_IsInternal = isInternal;
|
||||||
|
m_UseTls = config->GetValue("use_tls") == "1";
|
||||||
|
m_Logger = logger;
|
||||||
|
m_ManagerIP = managerIP;
|
||||||
|
m_ManagerPort = managerPort;
|
||||||
|
m_ManagerConnectionActive = false;
|
||||||
|
m_ServerType = serverType;
|
||||||
|
m_Config = config;
|
||||||
|
m_ShouldShutdown = shouldShutdown;
|
||||||
|
m_IsOkay = false;
|
||||||
|
m_ManagerConnectionActive = false;
|
||||||
|
m_ManagerTransport = nullptr;
|
||||||
|
m_SessionID = 0;
|
||||||
|
m_Acceptor = nullptr;
|
||||||
|
m_SSLContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TcpTransportLayer::~TcpTransportLayer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* TcpTransportLayer::ReceiveFromManager() {
|
||||||
|
if (m_ManagerTransport == nullptr) {
|
||||||
|
throw std::runtime_error("Manager connection is not active!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_ManagerConnectionActive) {
|
||||||
|
throw std::runtime_error("Manager connection is not active!");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* packet = m_ManagerTransport->Receive();
|
||||||
|
|
||||||
|
if (packet) {
|
||||||
|
if (packet->length < 1) { m_ManagerTransport->DeallocatePacket(packet); return nullptr; }
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
|
LOG("Lost our connection to Manager, shutting DOWN!");
|
||||||
|
m_ManagerConnectionActive = false;
|
||||||
|
//ConnectToManager(); //We'll just shut down now
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
||||||
|
LOG("Established connection to Manager, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
||||||
|
m_ManagerConnectionActive = true;
|
||||||
|
m_ManagerSystemAddress = packet->systemAddress;
|
||||||
|
MasterPackets::SendServerInfo(this, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||||
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||||
|
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||||
|
case eManagerMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
||||||
|
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eManagerMessageType::SHUTDOWN:
|
||||||
|
*m_ShouldShutdown = -2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//When we handle these packets in World instead RakNetTransportLayer, we just return the packet's pointer.
|
||||||
|
default:
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ManagerTransport->DeallocatePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* TcpTransportLayer::Receive() {
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
|
||||||
|
if (m_ReceiveQueue.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet* packet = m_ReceiveQueue.front();
|
||||||
|
m_ReceiveQueue.pop();
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::DeallocatePacket(Packet* packet) {
|
||||||
|
delete[] packet->data;
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::DeallocateManagerPacket(Packet* packet) {
|
||||||
|
if (m_ManagerTransport) {
|
||||||
|
m_ManagerTransport->DeallocatePacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) {
|
||||||
|
if (broadcast) {
|
||||||
|
for (auto& [addr, session] : m_ClientSessions) {
|
||||||
|
session->Send(bitStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||||
|
LOG("Invalid system address!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& it = m_ClientSessions.find(sysAddr);
|
||||||
|
|
||||||
|
if (it == m_ClientSessions.end()) {
|
||||||
|
LOG("Can not send to %s:%d, client not found!", sysAddr.ToString(false), sysAddr.port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->second->Send(bitStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::SendToManager(RakNet::BitStream& bitStream) {
|
||||||
|
if (!m_ManagerConnectionActive) {
|
||||||
|
throw std::runtime_error("Manager connection is not active!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ManagerTransport) {
|
||||||
|
m_ManagerTransport->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, m_ManagerSystemAddress, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) {
|
||||||
|
const auto& it = m_ClientSessions.find(sysAddr);
|
||||||
|
|
||||||
|
if (it == m_ClientSessions.end()) {
|
||||||
|
LOG("Client %s:%d not found in the session map!", sysAddr.ToString(false), sysAddr.port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY);
|
||||||
|
bitStream.Write(disconNotifyID);
|
||||||
|
|
||||||
|
it->second->Send(bitStream);
|
||||||
|
|
||||||
|
m_ClientSessions.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TcpTransportLayer::IsConnected(const SystemAddress& sysAddr) {
|
||||||
|
return m_ClientSessions.find(sysAddr) != m_ClientSessions.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TcpTransportLayer::Startup() {
|
||||||
|
m_VerifyCertificate = m_Config->GetValue("verify_certificate") == "1";
|
||||||
|
|
||||||
|
if (m_UseTls) {
|
||||||
|
m_SSLContext = std::make_unique<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
|
||||||
|
m_SSLContext->set_verify_mode(m_VerifyCertificate ? boost::asio::ssl::verify_peer : boost::asio::ssl::verify_none);
|
||||||
|
|
||||||
|
if (m_Config->GetValue("cert_file").empty() || m_Config->GetValue("key_file").empty()) {
|
||||||
|
LOG("Missing certificate or key file for TLS connection!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SSLContext->use_certificate_chain_file(m_Config->GetValue("cert_file"));
|
||||||
|
m_SSLContext->use_private_key_file(m_Config->GetValue("key_file"), boost::asio::ssl::context::pem);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Acceptor = std::make_unique<boost::asio::ip::tcp::acceptor>(m_IOService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), m_Port));
|
||||||
|
|
||||||
|
StartAccept();
|
||||||
|
|
||||||
|
// Start the I/O service in a separate thread
|
||||||
|
m_IOThread = std::thread([this]() {
|
||||||
|
m_IOService.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (m_ServerType != ServerType::Manager) {
|
||||||
|
SetupForManagerConnection();
|
||||||
|
if (!ConnectToManager()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::Shutdown() {
|
||||||
|
// Disconnect all clients
|
||||||
|
std::vector<SystemAddress> addresses;
|
||||||
|
for (auto& [addr, session] : m_ClientSessions) {
|
||||||
|
addresses.push_back(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& addr : addresses) {
|
||||||
|
Disconnect(addr, eServerDisconnectIdentifiers::SERVER_SHUTDOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IOService.stop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (m_IOThread.joinable()) {
|
||||||
|
m_IOThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
LOG("Exception in io-thread: %s", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Acceptor->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::RemoveSession(const SystemAddress& sysAddr) {
|
||||||
|
m_ClientSessions.erase(sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::OnReceive(Packet* packet) {
|
||||||
|
const auto& it = m_ClientSessions.find(packet->systemAddress);
|
||||||
|
|
||||||
|
if (it == m_ClientSessions.end()) {
|
||||||
|
LOG("Client %s:%d not found in the session map!", packet->systemAddress.ToString(false), packet->systemAddress.port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& session = it->second;
|
||||||
|
|
||||||
|
const auto& type = packet->data[0];
|
||||||
|
|
||||||
|
if (type == ID_USER_PACKET_ENUM) {
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
|
||||||
|
m_ReceiveQueue.push(packet);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ID_DISCONNECTION_NOTIFICATION) {
|
||||||
|
LOG("A client has disconnected");
|
||||||
|
session->Close();
|
||||||
|
RemoveSession(packet->systemAddress);
|
||||||
|
} else if (type == ID_CONNECTION_LOST) {
|
||||||
|
LOG("Lost our connection to a client");
|
||||||
|
session->Close();
|
||||||
|
RemoveSession(packet->systemAddress);
|
||||||
|
} else if (type == ID_NEW_INCOMING_CONNECTION) {
|
||||||
|
LOG("New incoming connection from %s:%d", packet->systemAddress.ToString(false), packet->systemAddress.port);
|
||||||
|
} else if (type == ID_CONNECTION_REQUEST) {
|
||||||
|
LOG("Connection request from %s:%d", packet->systemAddress.ToString(false), packet->systemAddress.port);
|
||||||
|
|
||||||
|
const std::string password = std::string(reinterpret_cast<char*>(packet->data + 1), packet->length - 1);
|
||||||
|
|
||||||
|
if (m_IsInternal) {
|
||||||
|
if (password != NET_PASSWORD_INTERNAL) {
|
||||||
|
LOG("Invalid internal password from %s:%d", packet->systemAddress.ToString(false), packet->systemAddress.port);
|
||||||
|
Disconnect(packet->systemAddress, eServerDisconnectIdentifiers::WRONG_GAME_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (password != NET_PASSWORD_EXTERNAL) {
|
||||||
|
LOG("Invalid external password from %s:%d", packet->systemAddress.ToString(false), packet->systemAddress.port);
|
||||||
|
Disconnect(packet->systemAddress, eServerDisconnectIdentifiers::WRONG_GAME_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
bitStream.Write<uint8_t>(ID_CONNECTION_REQUEST_ACCEPTED);
|
||||||
|
bitStream.Write<uint32_t>(packet->systemAddress.binaryAddress);
|
||||||
|
bitStream.Write<uint16_t>(packet->systemAddress.port);
|
||||||
|
bitStream.Write<uint16_t>(0);
|
||||||
|
// Our ip and port
|
||||||
|
bitStream.Write<uint32_t>(inet_addr(m_IP.c_str()));
|
||||||
|
bitStream.Write<uint16_t>(m_Port);
|
||||||
|
|
||||||
|
Send(bitStream, packet->systemAddress, false);
|
||||||
|
|
||||||
|
session->ReadyForUserPackets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::SetupForManagerConnection() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TcpTransportLayer::ConnectToManager() {
|
||||||
|
if (m_ManagerTransport) {
|
||||||
|
delete m_ManagerTransport;
|
||||||
|
m_ManagerTransport = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ManagerTransport = new TcpPeer(m_ManagerIP, m_ManagerPort, NET_PASSWORD_INTERNAL, m_UseTls, m_VerifyCertificate);
|
||||||
|
|
||||||
|
if (!m_ManagerTransport->WaitForConnection()) {
|
||||||
|
LOG("Failed to connect to Manager!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_ManagerTransport->IsConnected()) {
|
||||||
|
LOG("Failed to connect to Manager!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ManagerConnectionActive = true;
|
||||||
|
|
||||||
|
LOG("Connected to Manager %s:%d", m_ManagerIP.c_str(), m_ManagerPort);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::StartAccept() {
|
||||||
|
LOG("Listening for incoming connection on %s:%d", m_IP.c_str(), m_Port);
|
||||||
|
|
||||||
|
auto session = std::make_shared<TcpSession>(m_IOService, m_SSLContext.get(), this);
|
||||||
|
|
||||||
|
m_Acceptor->async_accept(session->GetSocket(),
|
||||||
|
[this, session](const boost::system::error_code& ec) {
|
||||||
|
HandleAccept(session, ec);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpTransportLayer::HandleAccept(const std::shared_ptr<TcpSession>& session, const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
session->Start();
|
||||||
|
|
||||||
|
SystemAddress sysAddr = session->GetSystemAddress();
|
||||||
|
|
||||||
|
if (m_ClientSessions.find(sysAddr) != m_ClientSessions.end()) {
|
||||||
|
LOG("Client already exists in the session map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClientSessions[sysAddr] = session;
|
||||||
|
|
||||||
|
LOG("[%i] Accepted connection from %s:%d", static_cast<int32_t>(m_ServerType), session->GetSocket().remote_endpoint().address().to_string().c_str(), session->GetSocket().remote_endpoint().port());
|
||||||
|
} else {
|
||||||
|
LOG("Accept error: %s", ec.message().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
StartAccept();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TcpTransportLayer::GetPing(const SystemAddress& sysAddr) const {
|
||||||
|
const auto& it = m_ClientSessions.find(sysAddr);
|
||||||
|
|
||||||
|
if (it == m_ClientSessions.end()) {
|
||||||
|
LOG("Client %s:%d not found in the session map!", sysAddr.ToString(false), sysAddr.port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second->GetAveragePing();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TcpTransportLayer::GetLatestPing(const SystemAddress& sysAddr) const {
|
||||||
|
const auto& it = m_ClientSessions.find(sysAddr);
|
||||||
|
|
||||||
|
if (it == m_ClientSessions.end()) {
|
||||||
|
LOG("Client %s:%d not found in the session map!", sysAddr.ToString(false), sysAddr.port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second->GetLastPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportPeerInterface* TcpTransportLayer::CreateOutgoingTransport(
|
||||||
|
uint32_t peerPort,
|
||||||
|
const std::string& ip,
|
||||||
|
uint32_t port,
|
||||||
|
const std::string& password
|
||||||
|
) const {
|
||||||
|
auto* peer = new TcpPeer(ip, port, password, m_UseTls, m_VerifyCertificate);
|
||||||
|
|
||||||
|
if (!peer->WaitForConnection()) {
|
||||||
|
LOG("Failed to connect to %s:%d", ip.c_str(), port);
|
||||||
|
delete peer;
|
||||||
|
throw std::runtime_error("Failed to connect to the server!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TcpTransportLayer::ClaimSessionID() {
|
||||||
|
return ++m_SessionID;
|
||||||
|
}
|
158
dNet/TcpTransportLayer.h
Normal file
158
dNet/TcpTransportLayer.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/ssl.hpp>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <memory>
|
||||||
|
#include <csignal>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
|
||||||
|
#include "RakPeerInterface.h"
|
||||||
|
#include "ReplicaManager.h"
|
||||||
|
#include "NetworkIDManager.h"
|
||||||
|
|
||||||
|
#include "TransportLayer.h"
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
#include "TcpSession.h"
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
// SystemAddress hash specialization
|
||||||
|
template <>
|
||||||
|
struct hash<SystemAddress> {
|
||||||
|
std::size_t operator()(const SystemAddress& sysAddr) const {
|
||||||
|
const std::size_t hash1 = sysAddr.binaryAddress;
|
||||||
|
const std::size_t hash2 = sysAddr.port;
|
||||||
|
return (hash1 | (hash2 << 32));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class TcpPeer;
|
||||||
|
|
||||||
|
class TcpTransportLayer : public TransportLayer {
|
||||||
|
public:
|
||||||
|
TcpTransportLayer(
|
||||||
|
const std::string& ip,
|
||||||
|
int port,
|
||||||
|
int instanceID,
|
||||||
|
int maxConnections,
|
||||||
|
bool isInternal,
|
||||||
|
bool useEncryption,
|
||||||
|
Logger* logger,
|
||||||
|
const std::string managerIP,
|
||||||
|
int managerPort,
|
||||||
|
ServerType serverType,
|
||||||
|
dConfig* config,
|
||||||
|
Game::signal_t* shouldShutdown,
|
||||||
|
unsigned int zoneID = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
~TcpTransportLayer();
|
||||||
|
|
||||||
|
Packet* ReceiveFromManager() override;
|
||||||
|
|
||||||
|
Packet* Receive() override;
|
||||||
|
|
||||||
|
void DeallocatePacket(Packet* packet) override;
|
||||||
|
|
||||||
|
void DeallocateManagerPacket(Packet* packet) override;
|
||||||
|
|
||||||
|
void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) override;
|
||||||
|
|
||||||
|
void SendToManager(RakNet::BitStream& bitStream) override;
|
||||||
|
|
||||||
|
void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) override;
|
||||||
|
|
||||||
|
bool IsConnected(const SystemAddress& sysAddr) override;
|
||||||
|
|
||||||
|
const std::string& GetIP() const override { return m_IP; }
|
||||||
|
|
||||||
|
const int GetPort() const override { return m_Port; }
|
||||||
|
|
||||||
|
const int GetMaxConnections() const override { return m_MaxConnections; }
|
||||||
|
|
||||||
|
const bool GetIsEncrypted() const override { return m_UseTls; }
|
||||||
|
|
||||||
|
const bool GetIsInternal() const override { return m_IsInternal; }
|
||||||
|
|
||||||
|
const bool GetIsOkay() const override { return m_IsOkay; }
|
||||||
|
|
||||||
|
Logger* GetLogger() const override { return m_Logger; }
|
||||||
|
|
||||||
|
const bool GetIsConnectedToManager() const override { return m_ManagerConnectionActive; }
|
||||||
|
|
||||||
|
const unsigned int GetZoneID() const override { return m_ZoneID; }
|
||||||
|
|
||||||
|
const int GetInstanceID() const override { return m_InstanceID; }
|
||||||
|
|
||||||
|
int GetPing(const SystemAddress& sysAddr) const override;
|
||||||
|
|
||||||
|
int GetLatestPing(const SystemAddress& sysAddr) const override;
|
||||||
|
|
||||||
|
const ServerType GetServerType() const override { return m_ServerType; }
|
||||||
|
|
||||||
|
TransportPeerInterface* CreateOutgoingTransport(
|
||||||
|
uint32_t peerPort,
|
||||||
|
const std::string& ip,
|
||||||
|
uint32_t port,
|
||||||
|
const std::string& password
|
||||||
|
) const override;
|
||||||
|
|
||||||
|
bool Startup() override;
|
||||||
|
|
||||||
|
void Shutdown() override;
|
||||||
|
|
||||||
|
void OnReceive(Packet* packet);
|
||||||
|
|
||||||
|
void RemoveSession(const SystemAddress& sysAddr);
|
||||||
|
|
||||||
|
uint32_t ClaimSessionID();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetupForManagerConnection();
|
||||||
|
|
||||||
|
bool ConnectToManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void StartAccept();
|
||||||
|
|
||||||
|
void HandleAccept(const std::shared_ptr<TcpSession>& session, const boost::system::error_code& ec);
|
||||||
|
|
||||||
|
boost::asio::io_service m_IOService;
|
||||||
|
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_Acceptor;
|
||||||
|
std::unique_ptr<boost::asio::ssl::context> m_SSLContext;
|
||||||
|
bool m_UseTls;
|
||||||
|
bool m_VerifyCertificate;
|
||||||
|
|
||||||
|
std::unordered_map<SystemAddress, std::shared_ptr<TcpSession>> m_ClientSessions;
|
||||||
|
std::queue<Packet*> m_ReceiveQueue;
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
std::thread m_IOThread;
|
||||||
|
|
||||||
|
Logger* m_Logger = nullptr;
|
||||||
|
dConfig* m_Config = nullptr;
|
||||||
|
|
||||||
|
Game::signal_t* m_ShouldShutdown = nullptr;
|
||||||
|
|
||||||
|
std::string m_IP;
|
||||||
|
int32_t m_Port;
|
||||||
|
int32_t m_MaxConnections;
|
||||||
|
uint32_t m_ZoneID;
|
||||||
|
int32_t m_InstanceID;
|
||||||
|
bool m_IsInternal;
|
||||||
|
bool m_IsOkay;
|
||||||
|
bool m_ManagerConnectionActive;
|
||||||
|
ServerType m_ServerType;
|
||||||
|
int32_t m_SessionID = 0;
|
||||||
|
|
||||||
|
TcpPeer* m_ManagerTransport = nullptr;
|
||||||
|
SystemAddress m_ManagerSystemAddress;
|
||||||
|
std::string m_ManagerIP;
|
||||||
|
int m_ManagerPort;
|
||||||
|
};
|
193
dNet/TransportLayer.h
Normal file
193
dNet/TransportLayer.h
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
|
#include "RakNetTypes.h"
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
|
||||||
|
class Logger;
|
||||||
|
class dConfig;
|
||||||
|
enum class eServerDisconnectIdentifiers : uint32_t;
|
||||||
|
|
||||||
|
enum class ServerType : uint32_t {
|
||||||
|
Manager,
|
||||||
|
Auth,
|
||||||
|
Chat,
|
||||||
|
World
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ServiceId : uint32_t {
|
||||||
|
General = 0,
|
||||||
|
Auth = 1,
|
||||||
|
Chat = 2,
|
||||||
|
World = 4,
|
||||||
|
Client = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Game {
|
||||||
|
using signal_t = volatile std::sig_atomic_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Abstract base class for managing the network and transport layer.
|
||||||
|
*/
|
||||||
|
class TransportLayer {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Receives a packet from the manager.
|
||||||
|
* @return Pointer to the received Packet.
|
||||||
|
*/
|
||||||
|
virtual Packet* ReceiveFromManager() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deallocates a packet received from the manager.
|
||||||
|
* @param packet Pointer to the Packet to be deallocated.
|
||||||
|
*/
|
||||||
|
virtual void DeallocateManagerPacket(Packet* packet) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a bit stream to the manager.
|
||||||
|
* @param bitStream Reference to the bitsteam to be sent.
|
||||||
|
*/
|
||||||
|
virtual void SendToManager(RakNet::BitStream& bitStream) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receives a packet.
|
||||||
|
* @return Pointer to the received Packet.
|
||||||
|
*/
|
||||||
|
virtual Packet* Receive() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deallocates a received packet.
|
||||||
|
* @param packet Pointer to the Packet to be deallocated.
|
||||||
|
*/
|
||||||
|
virtual void DeallocatePacket(Packet* packet) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a bitstream to a specified system address.
|
||||||
|
* @param bitStream Reference to the RakNet::BitStream to be sent.
|
||||||
|
* @param sysAddr Reference to the SystemAddress to send the bit stream to.
|
||||||
|
* @param broadcast Whether to broadcast the bit stream.
|
||||||
|
*/
|
||||||
|
virtual void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnects from a specified system address.
|
||||||
|
* @param sysAddr Reference to the SystemAddress to disconnect from.
|
||||||
|
* @param disconNotifyID Identifier for the disconnection notification.
|
||||||
|
*/
|
||||||
|
virtual void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if connected to a specified system address.
|
||||||
|
* @param sysAddr Reference to the SystemAddress to check connection status.
|
||||||
|
* @return Connection status, true if connected, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool IsConnected(const SystemAddress& sysAddr) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the IP address.
|
||||||
|
* @return Reference to the IP address string.
|
||||||
|
*/
|
||||||
|
virtual const std::string& GetIP() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the port number.
|
||||||
|
* @return The port number.
|
||||||
|
*/
|
||||||
|
virtual const int GetPort() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the maximum number of connections.
|
||||||
|
* @return The maximum number of connections.
|
||||||
|
*/
|
||||||
|
virtual const int GetMaxConnections() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the connection is encrypted.
|
||||||
|
* @return Weather the connection is encrypted.
|
||||||
|
*/
|
||||||
|
virtual const bool GetIsEncrypted() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the connection is internal.
|
||||||
|
* @return Weather the connection is internal.
|
||||||
|
*/
|
||||||
|
virtual const bool GetIsInternal() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the connection is okay.
|
||||||
|
* @return Weather the connection is okay.
|
||||||
|
*/
|
||||||
|
virtual const bool GetIsOkay() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the logger instance.
|
||||||
|
* @return Pointer to the Logger instance.
|
||||||
|
*/
|
||||||
|
virtual Logger* GetLogger() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if connected to the manager.
|
||||||
|
* @return Weather we are connected to the manager.
|
||||||
|
*/
|
||||||
|
virtual const bool GetIsConnectedToManager() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the zone ID.
|
||||||
|
* @return The zone ID.
|
||||||
|
*/
|
||||||
|
virtual const uint32_t GetZoneID() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the instance ID.
|
||||||
|
* @return The instance ID.
|
||||||
|
*/
|
||||||
|
virtual const int GetInstanceID() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the ping to a specified system address.
|
||||||
|
* @param sysAddr Reference to the SystemAddress to get the ping for.
|
||||||
|
* @return The ping.
|
||||||
|
*/
|
||||||
|
virtual int GetPing(const SystemAddress& sysAddr) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the latest ping to a specified system address.
|
||||||
|
* @param sysAddr Reference to the SystemAddress to get the latest ping for.
|
||||||
|
* @return The latest ping.
|
||||||
|
*/
|
||||||
|
virtual int GetLatestPing(const SystemAddress& sysAddr) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the server type.
|
||||||
|
* @return The server type.
|
||||||
|
*/
|
||||||
|
virtual const ServerType GetServerType() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts up the transport layer.
|
||||||
|
*
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool Startup() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shuts down the transport layer.
|
||||||
|
*/
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an outgoing transport connected to a server.
|
||||||
|
*
|
||||||
|
* @param ip The IP address of the server.
|
||||||
|
* @param port The port of the server.
|
||||||
|
* @param password The password to connect to the server.
|
||||||
|
*/
|
||||||
|
virtual TransportPeerInterface* CreateOutgoingTransport(
|
||||||
|
uint32_t peerPort,
|
||||||
|
const std::string& ip,
|
||||||
|
uint32_t port,
|
||||||
|
const std::string& password
|
||||||
|
) const = 0;
|
||||||
|
};
|
25
dNet/TransportPeerInterface.h
Normal file
25
dNet/TransportPeerInterface.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "RakNetTypes.h"
|
||||||
|
#include "PacketPriority.h"
|
||||||
|
|
||||||
|
class TransportPeerInterface {
|
||||||
|
public:
|
||||||
|
virtual void Send(
|
||||||
|
const RakNet::BitStream* bitStream,
|
||||||
|
PacketPriority priority,
|
||||||
|
PacketReliability reliability,
|
||||||
|
char orderingChannel,
|
||||||
|
SystemAddress systemAddress,
|
||||||
|
bool broadcas
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual void Disconnect() = 0;
|
||||||
|
|
||||||
|
virtual void Reconnect() = 0;
|
||||||
|
|
||||||
|
virtual Packet* Receive() = 0;
|
||||||
|
|
||||||
|
virtual void DeallocatePacket(Packet* packet) = 0;
|
||||||
|
};
|
@ -20,7 +20,7 @@ void ZoneInstanceManager::RequestZoneTransfer(dServer* server, uint32_t zoneID,
|
|||||||
|
|
||||||
this->requests.push_back(request);
|
this->requests.push_back(request);
|
||||||
|
|
||||||
MasterPackets::SendZoneTransferRequest(server, request->requestID, mythranShift, zoneID, zoneClone);
|
MasterPackets::SendZoneTransferRequest(server->GetTransportLayerPtr(), request->requestID, mythranShift, zoneID, zoneClone);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Handles a zone transfer response
|
//! Handles a zone transfer response
|
||||||
@ -58,7 +58,7 @@ void ZoneInstanceManager::HandleRequestZoneTransferResponse(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ZoneInstanceManager::CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password) {
|
void ZoneInstanceManager::CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password) {
|
||||||
MasterPackets::SendZoneCreatePrivate(server, zoneID, zoneClone, password);
|
MasterPackets::SendZoneCreatePrivate(server->GetTransportLayerPtr(), zoneID, zoneClone, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneInstanceManager::RequestPrivateZone(
|
void ZoneInstanceManager::RequestPrivateZone(
|
||||||
@ -72,5 +72,5 @@ void ZoneInstanceManager::RequestPrivateZone(
|
|||||||
|
|
||||||
this->requests.push_back(request);
|
this->requests.push_back(request);
|
||||||
|
|
||||||
MasterPackets::SendZoneRequestPrivate(server, request->requestID, mythranShift, password);
|
MasterPackets::SendZoneRequestPrivate(server->GetTransportLayerPtr(), request->requestID, mythranShift, password);
|
||||||
}
|
}
|
||||||
|
341
dNet/dServer.cpp
341
dNet/dServer.cpp
@ -8,252 +8,187 @@
|
|||||||
#include "MessageIdentifiers.h"
|
#include "MessageIdentifiers.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eServerMessageType.h"
|
#include "eServerMessageType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
|
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "MasterPackets.h"
|
#include "MasterPackets.h"
|
||||||
#include "ZoneInstanceManager.h"
|
#include "ZoneInstanceManager.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
//! Replica Constructor class
|
#include "RakNetTransportLayer.h"
|
||||||
class ReplicaConstructor : public ReceiveConstructionInterface {
|
#ifdef NET_ENABLE_TCP_TRANSPORT
|
||||||
public:
|
#include "TcpTransportLayer.h"
|
||||||
ReplicaReturnResult ReceiveConstruction(RakNet::BitStream* inBitStream, RakNetTime timestamp, NetworkID networkID, NetworkIDObject* existingObject, SystemAddress senderId, ReplicaManager* caller) {
|
#endif
|
||||||
return REPLICA_PROCESSING_DONE;
|
|
||||||
|
dServer::dServer(
|
||||||
|
const std::string& ip,
|
||||||
|
int port,
|
||||||
|
int instanceID,
|
||||||
|
int maxConnections,
|
||||||
|
bool isInternal,
|
||||||
|
bool useEncryption,
|
||||||
|
Logger* logger,
|
||||||
|
const std::string masterIP,
|
||||||
|
int masterPort,
|
||||||
|
ServerType serverType,
|
||||||
|
dConfig* config,
|
||||||
|
Game::signal_t* shouldShutdown,
|
||||||
|
unsigned int zoneID
|
||||||
|
) {
|
||||||
|
m_TransportType = TransportType::RakNet;
|
||||||
|
|
||||||
|
if (config->GetValue("transport_layer") == "tcp") {
|
||||||
|
m_TransportType = TransportType::Tcp;
|
||||||
|
LOG("Using TCP transport layer.");
|
||||||
}
|
}
|
||||||
} ConstructionCB;
|
else {
|
||||||
|
LOG("Using RakNet transport layer.");
|
||||||
//! Replica Download Sender class
|
|
||||||
class ReplicaSender : public SendDownloadCompleteInterface {
|
|
||||||
public:
|
|
||||||
ReplicaReturnResult SendDownloadComplete(RakNet::BitStream* outBitStream, RakNetTime currentTime, SystemAddress senderId, ReplicaManager* caller) {
|
|
||||||
return REPLICA_PROCESSING_DONE;
|
|
||||||
}
|
|
||||||
} SendDownloadCompleteCB;
|
|
||||||
|
|
||||||
//! Replica Download Receiver class
|
|
||||||
class ReplicaReceiever : public ReceiveDownloadCompleteInterface {
|
|
||||||
public:
|
|
||||||
ReplicaReturnResult ReceiveDownloadComplete(RakNet::BitStream* inBitStream, SystemAddress senderId, ReplicaManager* caller) {
|
|
||||||
return REPLICA_PROCESSING_DONE;
|
|
||||||
}
|
|
||||||
} ReceiveDownloadCompleteCB;
|
|
||||||
|
|
||||||
dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
|
|
||||||
mIP = ip;
|
|
||||||
mPort = port;
|
|
||||||
mZoneID = zoneID;
|
|
||||||
mInstanceID = instanceID;
|
|
||||||
mMaxConnections = maxConnections;
|
|
||||||
mIsInternal = isInternal;
|
|
||||||
mUseEncryption = useEncryption;
|
|
||||||
mLogger = logger;
|
|
||||||
mMasterIP = masterIP;
|
|
||||||
mMasterPort = masterPort;
|
|
||||||
mMasterConnectionActive = false;
|
|
||||||
mNetIDManager = nullptr;
|
|
||||||
mReplicaManager = nullptr;
|
|
||||||
mServerType = serverType;
|
|
||||||
mConfig = config;
|
|
||||||
mShouldShutdown = lastSignal;
|
|
||||||
//Attempt to start our server here:
|
|
||||||
mIsOkay = Startup();
|
|
||||||
|
|
||||||
//Forcibly log to both the console and our file what ip, port and possibly zoneID / instanceID we're running on:
|
|
||||||
bool prevLogSetting = mLogger->GetLogToConsole();
|
|
||||||
mLogger->SetLogToConsole(true);
|
|
||||||
|
|
||||||
if (mIsOkay) {
|
|
||||||
if (zoneID == 0)
|
|
||||||
LOG("%s Server is listening on %s:%i with encryption: %i", StringifiedEnum::ToString(serverType).data(), ip.c_str(), port, int(useEncryption));
|
|
||||||
else
|
|
||||||
LOG("%s Server is listening on %s:%i with encryption: %i, running zone %i / %i", StringifiedEnum::ToString(serverType).data(), ip.c_str(), port, int(useEncryption), zoneID, instanceID);
|
|
||||||
} else { LOG("FAILED TO START SERVER ON IP/PORT: %s:%i", ip.c_str(), port); return; }
|
|
||||||
|
|
||||||
mLogger->SetLogToConsole(prevLogSetting);
|
|
||||||
|
|
||||||
//Connect to master if we are not master:
|
|
||||||
if (serverType != ServerType::Master) {
|
|
||||||
SetupForMasterConnection();
|
|
||||||
if (!ConnectToMaster()) {
|
|
||||||
LOG("Failed ConnectToMaster!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set up Replica if we're a world server:
|
switch (m_TransportType) {
|
||||||
if (serverType == ServerType::World) {
|
case TransportType::RakNet:
|
||||||
mNetIDManager = new NetworkIDManager();
|
m_TransportLayer = std::make_unique<RakNetTransportLayer>(
|
||||||
mNetIDManager->SetIsNetworkIDAuthority(true);
|
ip,
|
||||||
|
port,
|
||||||
|
instanceID,
|
||||||
|
maxConnections,
|
||||||
|
isInternal,
|
||||||
|
useEncryption,
|
||||||
|
logger,
|
||||||
|
masterIP,
|
||||||
|
masterPort,
|
||||||
|
serverType,
|
||||||
|
config,
|
||||||
|
shouldShutdown,
|
||||||
|
zoneID
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case TransportType::Tcp:
|
||||||
|
#ifdef NET_ENABLE_TCP_TRANSPORT
|
||||||
|
m_TransportLayer = std::make_unique<TcpTransportLayer>(
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
instanceID,
|
||||||
|
maxConnections,
|
||||||
|
isInternal,
|
||||||
|
useEncryption,
|
||||||
|
logger,
|
||||||
|
masterIP,
|
||||||
|
masterPort,
|
||||||
|
serverType,
|
||||||
|
config,
|
||||||
|
shouldShutdown,
|
||||||
|
zoneID
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("TCP transport is not enabled!");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mReplicaManager = new ReplicaManager();
|
bool okey = m_TransportLayer->Startup();
|
||||||
mReplicaManager->SetAutoParticipateNewConnections(false);
|
|
||||||
mReplicaManager->SetAutoConstructToNewParticipants(false);
|
|
||||||
mReplicaManager->SetAutoSerializeInScope(true);
|
|
||||||
mReplicaManager->SetReceiveConstructionCB(&ConstructionCB);
|
|
||||||
mReplicaManager->SetDownloadCompleteCB(&SendDownloadCompleteCB, &ReceiveDownloadCompleteCB);
|
|
||||||
|
|
||||||
mPeer->AttachPlugin(mReplicaManager);
|
if (!okey) {
|
||||||
mPeer->SetNetworkIDManager(mNetIDManager);
|
LOG("Failed to start the server!");
|
||||||
|
|
||||||
|
throw std::runtime_error("Failed to start the server!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dServer::~dServer() {
|
dServer::~dServer() {
|
||||||
Shutdown();
|
m_TransportLayer->Shutdown();
|
||||||
|
|
||||||
|
m_TransportLayer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet* dServer::ReceiveFromMaster() {
|
Packet* dServer::ReceiveFromMaster() {
|
||||||
if (!mMasterPeer) return nullptr;
|
return m_TransportLayer->ReceiveFromManager();
|
||||||
if (!mMasterConnectionActive) ConnectToMaster();
|
|
||||||
|
|
||||||
Packet* packet = mMasterPeer->Receive();
|
|
||||||
if (packet) {
|
|
||||||
if (packet->length < 1) { mMasterPeer->DeallocatePacket(packet); return nullptr; }
|
|
||||||
|
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
|
||||||
LOG("Lost our connection to master, shutting DOWN!");
|
|
||||||
mMasterConnectionActive = false;
|
|
||||||
//ConnectToMaster(); //We'll just shut down now
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
|
||||||
LOG("Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
|
||||||
mMasterConnectionActive = true;
|
|
||||||
mMasterSystemAddress = packet->systemAddress;
|
|
||||||
MasterPackets::SendServerInfo(this, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
|
||||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
|
||||||
case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
|
||||||
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(packet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eMasterMessageType::SHUTDOWN:
|
|
||||||
*mShouldShutdown = -2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
//When we handle these packets in World instead dServer, we just return the packet's pointer.
|
|
||||||
default:
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mMasterPeer->DeallocatePacket(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet* dServer::Receive() {
|
Packet* dServer::Receive() {
|
||||||
return mPeer->Receive();
|
return m_TransportLayer->Receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::DeallocatePacket(Packet* packet) {
|
void dServer::DeallocatePacket(Packet* packet) {
|
||||||
mPeer->DeallocatePacket(packet);
|
m_TransportLayer->DeallocatePacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::DeallocateMasterPacket(Packet* packet) {
|
void dServer::DeallocateMasterPacket(Packet* packet) {
|
||||||
mMasterPeer->DeallocatePacket(packet);
|
m_TransportLayer->DeallocateManagerPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) {
|
void dServer::Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) {
|
||||||
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, broadcast);
|
m_TransportLayer->Send(bitStream, sysAddr, broadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::SendToMaster(RakNet::BitStream& bitStream) {
|
void dServer::SendToMaster(RakNet::BitStream& bitStream) {
|
||||||
if (!mMasterConnectionActive) ConnectToMaster();
|
m_TransportLayer->SendToManager(bitStream);
|
||||||
mMasterPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, mMasterSystemAddress, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) {
|
void dServer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) {
|
||||||
RakNet::BitStream bitStream;
|
m_TransportLayer->Disconnect(sysAddr, disconNotifyID);
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY);
|
|
||||||
bitStream.Write(disconNotifyID);
|
|
||||||
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, false);
|
|
||||||
|
|
||||||
mPeer->CloseConnection(sysAddr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dServer::IsConnected(const SystemAddress& sysAddr) {
|
bool dServer::IsConnected(const SystemAddress& sysAddr) {
|
||||||
return mPeer->IsConnected(sysAddr);
|
return m_TransportLayer->IsConnected(sysAddr);
|
||||||
}
|
|
||||||
|
|
||||||
bool dServer::Startup() {
|
|
||||||
mSocketDescriptor = SocketDescriptor(uint16_t(mPort), 0);
|
|
||||||
mPeer = RakNetworkFactory::GetRakPeerInterface();
|
|
||||||
|
|
||||||
if (!mPeer) return false;
|
|
||||||
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
|
||||||
|
|
||||||
if (mIsInternal) {
|
|
||||||
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
|
||||||
} else {
|
|
||||||
UpdateBandwidthLimit();
|
|
||||||
UpdateMaximumMtuSize();
|
|
||||||
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
|
||||||
if (mUseEncryption) mPeer->InitializeSecurity(NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dServer::UpdateMaximumMtuSize() {
|
|
||||||
auto maxMtuSize = mConfig->GetValue("maximum_mtu_size");
|
|
||||||
mPeer->SetMTUSize(maxMtuSize.empty() ? 1228 : std::stoi(maxMtuSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
void dServer::UpdateBandwidthLimit() {
|
|
||||||
auto newBandwidth = mConfig->GetValue("maximum_outgoing_bandwidth");
|
|
||||||
mPeer->SetPerConnectionOutgoingBandwidthLimit(!newBandwidth.empty() ? std::stoi(newBandwidth) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dServer::Shutdown() {
|
|
||||||
if (mPeer) {
|
|
||||||
mPeer->Shutdown(1000);
|
|
||||||
RakNetworkFactory::DestroyRakPeerInterface(mPeer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNetIDManager) {
|
|
||||||
delete mNetIDManager;
|
|
||||||
mNetIDManager = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mReplicaManager) {
|
|
||||||
delete mReplicaManager;
|
|
||||||
mReplicaManager = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mServerType != ServerType::Master && mMasterPeer) {
|
|
||||||
mMasterPeer->Shutdown(1000);
|
|
||||||
RakNetworkFactory::DestroyRakPeerInterface(mMasterPeer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dServer::SetupForMasterConnection() {
|
|
||||||
mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
|
|
||||||
mMasterPeer = RakNetworkFactory::GetRakPeerInterface();
|
|
||||||
bool ret = mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1);
|
|
||||||
if (!ret) LOG("Failed MasterPeer Startup!");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dServer::ConnectToMaster() {
|
|
||||||
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
|
||||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dServer::UpdateReplica() {
|
|
||||||
mReplicaManager->Update(mPeer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dServer::GetPing(const SystemAddress& sysAddr) const {
|
int dServer::GetPing(const SystemAddress& sysAddr) const {
|
||||||
return mPeer->GetAveragePing(sysAddr);
|
return m_TransportLayer->GetPing(sysAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dServer::GetLatestPing(const SystemAddress& sysAddr) const {
|
int dServer::GetLatestPing(const SystemAddress& sysAddr) const {
|
||||||
return mPeer->GetLastPing(sysAddr);
|
return m_TransportLayer->GetLatestPing(sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& dServer::GetIP() const {
|
||||||
|
return m_TransportLayer->GetIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int dServer::GetPort() const {
|
||||||
|
return m_TransportLayer->GetPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int dServer::GetMaxConnections() const {
|
||||||
|
return m_TransportLayer->GetMaxConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool dServer::GetIsEncrypted() const {
|
||||||
|
return m_TransportLayer->GetIsEncrypted();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool dServer::GetIsInternal() const {
|
||||||
|
return m_TransportLayer->GetIsInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool dServer::GetIsOkay() const {
|
||||||
|
return m_TransportLayer->GetIsOkay();
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger* dServer::GetLogger() const {
|
||||||
|
return m_TransportLayer->GetLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool dServer::GetIsConnectedToMaster() const {
|
||||||
|
return m_TransportLayer->GetIsConnectedToManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int dServer::GetZoneID() const {
|
||||||
|
return m_TransportLayer->GetZoneID();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int dServer::GetInstanceID() const {
|
||||||
|
return m_TransportLayer->GetInstanceID();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ServerType dServer::GetServerType() const {
|
||||||
|
return m_TransportLayer->GetServerType();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unique_ptr<TransportLayer>& dServer::GetTransportLayer() const {
|
||||||
|
return m_TransportLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TransportType dServer::GetTransportType() const {
|
||||||
|
return m_TransportType;
|
||||||
}
|
}
|
||||||
|
138
dNet/dServer.h
138
dNet/dServer.h
@ -1,33 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include "RakPeerInterface.h"
|
#include <memory>
|
||||||
#include "ReplicaManager.h"
|
|
||||||
#include "NetworkIDManager.h"
|
|
||||||
|
|
||||||
class Logger;
|
#include "TransportLayer.h"
|
||||||
class dConfig;
|
|
||||||
enum class eServerDisconnectIdentifiers : uint32_t;
|
|
||||||
|
|
||||||
enum class ServerType : uint32_t {
|
enum class TransportType : uint32_t {
|
||||||
Master,
|
RakNet,
|
||||||
Auth,
|
Tcp
|
||||||
Chat,
|
|
||||||
World
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ServiceId : uint32_t{
|
|
||||||
General = 0,
|
|
||||||
Auth = 1,
|
|
||||||
Chat = 2,
|
|
||||||
World = 4,
|
|
||||||
Client = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Game {
|
|
||||||
using signal_t = volatile std::sig_atomic_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
class dServer {
|
class dServer {
|
||||||
public:
|
public:
|
||||||
// Default constructor should only used for testing!
|
// Default constructor should only used for testing!
|
||||||
@ -45,73 +27,85 @@ public:
|
|||||||
ServerType serverType,
|
ServerType serverType,
|
||||||
dConfig* config,
|
dConfig* config,
|
||||||
Game::signal_t* shouldShutdown,
|
Game::signal_t* shouldShutdown,
|
||||||
unsigned int zoneID = 0);
|
unsigned int zoneID = 0
|
||||||
|
);
|
||||||
|
|
||||||
~dServer();
|
~dServer();
|
||||||
|
|
||||||
Packet* ReceiveFromMaster();
|
Packet* ReceiveFromMaster();
|
||||||
|
|
||||||
Packet* Receive();
|
Packet* Receive();
|
||||||
|
|
||||||
void DeallocatePacket(Packet* packet);
|
void DeallocatePacket(Packet* packet);
|
||||||
|
|
||||||
void DeallocateMasterPacket(Packet* packet);
|
void DeallocateMasterPacket(Packet* packet);
|
||||||
|
|
||||||
virtual void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast);
|
virtual void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast);
|
||||||
|
|
||||||
void SendToMaster(RakNet::BitStream& bitStream);
|
void SendToMaster(RakNet::BitStream& bitStream);
|
||||||
|
|
||||||
void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID);
|
void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID);
|
||||||
|
|
||||||
bool IsConnected(const SystemAddress& sysAddr);
|
bool IsConnected(const SystemAddress& sysAddr);
|
||||||
const std::string& GetIP() const { return mIP; }
|
|
||||||
const int GetPort() const { return mPort; }
|
const std::string& GetIP() const;
|
||||||
const int GetMaxConnections() const { return mMaxConnections; }
|
|
||||||
const bool GetIsEncrypted() const { return mUseEncryption; }
|
const int GetPort() const;
|
||||||
const bool GetIsInternal() const { return mIsInternal; }
|
|
||||||
const bool GetIsOkay() const { return mIsOkay; }
|
const int GetMaxConnections() const;
|
||||||
Logger* GetLogger() const { return mLogger; }
|
|
||||||
const bool GetIsConnectedToMaster() const { return mMasterConnectionActive; }
|
const bool GetIsEncrypted() const;
|
||||||
const unsigned int GetZoneID() const { return mZoneID; }
|
|
||||||
const int GetInstanceID() const { return mInstanceID; }
|
const bool GetIsInternal() const;
|
||||||
ReplicaManager* GetReplicaManager() { return mReplicaManager; }
|
|
||||||
void UpdateReplica();
|
const bool GetIsOkay() const;
|
||||||
void UpdateBandwidthLimit();
|
|
||||||
void UpdateMaximumMtuSize();
|
Logger* GetLogger() const;
|
||||||
|
|
||||||
|
const bool GetIsConnectedToMaster() const;
|
||||||
|
|
||||||
|
const unsigned int GetZoneID() const;
|
||||||
|
|
||||||
|
const int GetInstanceID() const;
|
||||||
|
|
||||||
int GetPing(const SystemAddress& sysAddr) const;
|
int GetPing(const SystemAddress& sysAddr) const;
|
||||||
|
|
||||||
int GetLatestPing(const SystemAddress& sysAddr) const;
|
int GetLatestPing(const SystemAddress& sysAddr) const;
|
||||||
|
|
||||||
NetworkIDManager* GetNetworkIDManager() { return mNetIDManager; }
|
const ServerType GetServerType() const;
|
||||||
|
|
||||||
const ServerType GetServerType() const { return mServerType; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool Startup();
|
|
||||||
void Shutdown();
|
|
||||||
void SetupForMasterConnection();
|
|
||||||
bool ConnectToMaster();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Logger* mLogger = nullptr;
|
|
||||||
dConfig* mConfig = nullptr;
|
|
||||||
RakPeerInterface* mPeer = nullptr;
|
|
||||||
ReplicaManager* mReplicaManager = nullptr;
|
|
||||||
NetworkIDManager* mNetIDManager = nullptr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not to shut down the server. Pointer to Game::lastSignal.
|
* @brief Gets the transport layer.
|
||||||
|
*
|
||||||
|
* @return The TransportLayer instance.
|
||||||
*/
|
*/
|
||||||
Game::signal_t* mShouldShutdown = nullptr;
|
const std::unique_ptr<TransportLayer>& GetTransportLayer() const;
|
||||||
SocketDescriptor mSocketDescriptor;
|
|
||||||
std::string mIP;
|
|
||||||
int mPort;
|
|
||||||
int mMaxConnections;
|
|
||||||
unsigned int mZoneID;
|
|
||||||
int mInstanceID;
|
|
||||||
bool mUseEncryption;
|
|
||||||
bool mIsInternal;
|
|
||||||
bool mIsOkay;
|
|
||||||
bool mMasterConnectionActive;
|
|
||||||
ServerType mServerType;
|
|
||||||
|
|
||||||
RakPeerInterface* mMasterPeer = nullptr;
|
/**
|
||||||
SocketDescriptor mMasterSocketDescriptor;
|
* @brief Gets the transport type.
|
||||||
SystemAddress mMasterSystemAddress;
|
*
|
||||||
std::string mMasterIP;
|
* @return The transport type.
|
||||||
int mMasterPort;
|
*/
|
||||||
|
const TransportType GetTransportType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implicit conversion to TransportLayer*.
|
||||||
|
*/
|
||||||
|
operator TransportLayer*() const {
|
||||||
|
return m_TransportLayer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to the TransportLayer.
|
||||||
|
*
|
||||||
|
* @return Pointer to the TransportLayer.
|
||||||
|
*/
|
||||||
|
TransportLayer* GetTransportLayerPtr() const {
|
||||||
|
return m_TransportLayer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TransportType m_TransportType;
|
||||||
|
|
||||||
|
std::unique_ptr<TransportLayer> m_TransportLayer;
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
#include "eServerMessageType.h"
|
#include "eServerMessageType.h"
|
||||||
#include "eChatMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "eWorldMessageType.h"
|
#include "eWorldMessageType.h"
|
||||||
#include "eMasterMessageType.h"
|
#include "eManagerMessageType.h"
|
||||||
#include "eGameMessageType.h"
|
#include "eGameMessageType.h"
|
||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
@ -87,7 +87,7 @@ namespace Game {
|
|||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
RakPeerInterface* chatServer = nullptr;
|
TransportPeerInterface* chatServer = nullptr;
|
||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
SystemAddress chatSysAddr;
|
SystemAddress chatSysAddr;
|
||||||
Game::signal_t lastSignal = 0;
|
Game::signal_t lastSignal = 0;
|
||||||
@ -218,10 +218,12 @@ int main(int argc, char** argv) {
|
|||||||
uint32_t chatPort = 1501;
|
uint32_t chatPort = 1501;
|
||||||
if (Game::config->GetValue("chat_server_port") != "") chatPort = std::atoi(Game::config->GetValue("chat_server_port").c_str());
|
if (Game::config->GetValue("chat_server_port") != "") chatPort = std::atoi(Game::config->GetValue("chat_server_port").c_str());
|
||||||
|
|
||||||
auto chatSock = SocketDescriptor(static_cast<uint16_t>(ourPort + 2), 0);
|
Game::chatServer = Game::server->GetTransportLayer()->CreateOutgoingTransport(
|
||||||
Game::chatServer = RakNetworkFactory::GetRakPeerInterface();
|
ourPort + 2,
|
||||||
Game::chatServer->Startup(1, 30, &chatSock, 1);
|
masterIP,
|
||||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
chatPort,
|
||||||
|
"3.25 ND1"
|
||||||
|
);
|
||||||
|
|
||||||
//Set up other things:
|
//Set up other things:
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
@ -379,7 +381,7 @@ int main(int argc, char** argv) {
|
|||||||
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
||||||
framesSinceChatDisconnect = 0;
|
framesSinceChatDisconnect = 0;
|
||||||
|
|
||||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
Game::chatServer->Reconnect();
|
||||||
}
|
}
|
||||||
} else framesSinceChatDisconnect = 0;
|
} else framesSinceChatDisconnect = 0;
|
||||||
|
|
||||||
@ -447,9 +449,6 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Metrics::StartMeasurement(MetricVariable::UpdateReplica);
|
Metrics::StartMeasurement(MetricVariable::UpdateReplica);
|
||||||
|
|
||||||
//Update our replica objects:
|
|
||||||
Game::server->UpdateReplica();
|
|
||||||
|
|
||||||
Metrics::EndMeasurement(MetricVariable::UpdateReplica);
|
Metrics::EndMeasurement(MetricVariable::UpdateReplica);
|
||||||
|
|
||||||
//Push our log every 15s:
|
//Push our log every 15s:
|
||||||
@ -510,7 +509,7 @@ int main(int argc, char** argv) {
|
|||||||
if (framesSinceMasterStatus >= 200) {
|
if (framesSinceMasterStatus >= 200) {
|
||||||
LOG("Finished loading world with zone (%i), ready up!", Game::server->GetZoneID());
|
LOG("Finished loading world with zone (%i), ready up!", Game::server->GetZoneID());
|
||||||
|
|
||||||
MasterPackets::SendWorldReady(Game::server, Game::server->GetZoneID(), Game::server->GetInstanceID());
|
MasterPackets::SendWorldReady(Game::server->GetTransportLayerPtr(), Game::server->GetZoneID(), Game::server->GetInstanceID());
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
@ -663,8 +662,8 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
void HandleMasterPacket(Packet* packet) {
|
void HandleMasterPacket(Packet* packet) {
|
||||||
if (packet->length < 2) return;
|
if (packet->length < 2) return;
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::MASTER || packet->length < 4) return;
|
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::MASTER || packet->length < 4) return;
|
||||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||||
case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
case eManagerMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
uint64_t requestID;
|
uint64_t requestID;
|
||||||
inStream.Read(requestID);
|
inStream.Read(requestID);
|
||||||
@ -674,7 +673,7 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SESSION_KEY_RESPONSE: {
|
case eManagerMessageType::SESSION_KEY_RESPONSE: {
|
||||||
//Read our session key and to which user it belongs:
|
//Read our session key and to which user it belongs:
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
uint32_t sessionKey = 0;
|
uint32_t sessionKey = 0;
|
||||||
@ -729,7 +728,7 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
//Notify master:
|
//Notify master:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_ADDED);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::PLAYER_ADDED);
|
||||||
bitStream.Write<LWOMAPID>(Game::server->GetZoneID());
|
bitStream.Write<LWOMAPID>(Game::server->GetZoneID());
|
||||||
bitStream.Write<LWOINSTANCEID>(instanceID);
|
bitStream.Write<LWOINSTANCEID>(instanceID);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
@ -738,7 +737,7 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eMasterMessageType::AFFIRM_TRANSFER_REQUEST: {
|
case eManagerMessageType::AFFIRM_TRANSFER_REQUEST: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
uint64_t requestID;
|
uint64_t requestID;
|
||||||
inStream.Read(requestID);
|
inStream.Read(requestID);
|
||||||
@ -746,20 +745,20 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::AFFIRM_TRANSFER_RESPONSE);
|
||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::SHUTDOWN: {
|
case eManagerMessageType::SHUTDOWN: {
|
||||||
Game::lastSignal = -1;
|
Game::lastSignal = -1;
|
||||||
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case eMasterMessageType::NEW_SESSION_ALERT: {
|
case eManagerMessageType::NEW_SESSION_ALERT: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
uint32_t sessionKey = inStream.Read(sessionKey);
|
uint32_t sessionKey = inStream.Read(sessionKey);
|
||||||
|
|
||||||
@ -832,7 +831,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_REMOVED);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::PLAYER_REMOVED);
|
||||||
bitStream.Write<LWOMAPID>(Game::server->GetZoneID());
|
bitStream.Write<LWOMAPID>(Game::server->GetZoneID());
|
||||||
bitStream.Write<LWOINSTANCEID>(instanceID);
|
bitStream.Write<LWOINSTANCEID>(instanceID);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
@ -896,7 +895,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
//Request the session info from Master:
|
//Request the session info from Master:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_SESSION_KEY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_SESSION_KEY);
|
||||||
bitStream.Write(username);
|
bitStream.Write(username);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
|
|
||||||
@ -1017,8 +1016,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
Character* c = user->GetLastUsedChar();
|
Character* c = user->GetLastUsedChar();
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
std::u16string username = GeneralUtils::ASCIIToUTF16(c->GetName());
|
std::u16string username = GeneralUtils::ASCIIToUTF16(c->GetName());
|
||||||
Game::server->GetReplicaManager()->AddParticipant(packet->systemAddress);
|
|
||||||
|
|
||||||
EntityInfo info{};
|
EntityInfo info{};
|
||||||
info.lot = 1;
|
info.lot = 1;
|
||||||
Entity* player = Game::entityManager->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress));
|
Entity* player = Game::entityManager->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress));
|
||||||
@ -1385,10 +1383,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
void WorldShutdownProcess(uint32_t zoneId) {
|
void WorldShutdownProcess(uint32_t zoneId) {
|
||||||
LOG("Saving map %i instance %i", zoneId, instanceID);
|
LOG("Saving map %i instance %i", zoneId, instanceID);
|
||||||
for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) {
|
for (auto* entity : PlayerManager::GetAllPlayers()) {
|
||||||
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i);
|
|
||||||
|
|
||||||
auto* entity = PlayerManager::GetPlayer(player);
|
|
||||||
LOG("Saving data!");
|
LOG("Saving data!");
|
||||||
if (entity != nullptr && entity->GetCharacter() != nullptr) {
|
if (entity != nullptr && entity->GetCharacter() != nullptr) {
|
||||||
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
||||||
@ -1411,8 +1406,8 @@ void WorldShutdownProcess(uint32_t zoneId) {
|
|||||||
|
|
||||||
LOG("ALL DATA HAS BEEN SAVED FOR ZONE %i INSTANCE %i!", zoneId, instanceID);
|
LOG("ALL DATA HAS BEEN SAVED FOR ZONE %i INSTANCE %i!", zoneId, instanceID);
|
||||||
|
|
||||||
while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) {
|
for (auto* entity : PlayerManager::GetAllPlayers()) {
|
||||||
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0);
|
const auto& player = entity->GetSystemAddress();
|
||||||
|
|
||||||
Game::server->Disconnect(player, eServerDisconnectIdentifiers::SERVER_SHUTDOWN);
|
Game::server->Disconnect(player, eServerDisconnectIdentifiers::SERVER_SHUTDOWN);
|
||||||
}
|
}
|
||||||
@ -1463,6 +1458,6 @@ void FinalizeShutdown() {
|
|||||||
|
|
||||||
void SendShutdownMessageToMaster() {
|
void SendShutdownMessageToMaster() {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN_RESPONSE);
|
||||||
Game::server->SendToMaster(bitStream);
|
Game::server->SendToMaster(bitStream);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "GameDependencies.h"
|
#include "GameDependencies.h"
|
||||||
|
|
||||||
|
#include "TransportPeerInterface.h"
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
@ -7,7 +9,7 @@ namespace Game {
|
|||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
RakPeerInterface* chatServer = nullptr;
|
TransportPeerInterface* chatServer = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
SystemAddress chatSysAddr;
|
SystemAddress chatSysAddr;
|
||||||
EntityManager* entityManager = nullptr;
|
EntityManager* entityManager = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user