mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-21 13:07:31 +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 PlayerContainer;
|
||||
|
||||
#include "TransportPeerInterface.h"
|
||||
|
||||
namespace Game {
|
||||
using signal_t = volatile std::sig_atomic_t;
|
||||
extern Logger* logger;
|
||||
@ -24,7 +26,7 @@ namespace Game {
|
||||
extern dChatFilter* chatFilter;
|
||||
extern dConfig* config;
|
||||
extern std::mt19937 randomEngine;
|
||||
extern RakPeerInterface* chatServer;
|
||||
extern TransportPeerInterface* chatServer;
|
||||
extern AssetManager* assetManager;
|
||||
extern SystemAddress chatSysAddr;
|
||||
extern signal_t lastSignal;
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef __EMASTERMESSAGETYPE__H__
|
||||
#define __EMASTERMESSAGETYPE__H__
|
||||
#ifndef __EMANAGERMESSAGETYPE__H__
|
||||
#define __EMANAGERMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eMasterMessageType : uint32_t {
|
||||
enum class eManagerMessageType : uint32_t {
|
||||
REQUEST_PERSISTENT_ID = 1,
|
||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||
REQUEST_ZONE_TRANSFER,
|
||||
@ -33,4 +33,4 @@ enum class eMasterMessageType : uint32_t {
|
||||
NEW_SESSION_ALERT
|
||||
};
|
||||
|
||||
#endif //!__EMASTERMESSAGETYPE__H__
|
||||
#endif //!__EMANAGERMESSAGETYPE__H__
|
@ -18,7 +18,7 @@
|
||||
#include "BitStreamUtils.h"
|
||||
#include "eObjectWorldState.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
|
||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
@ -137,7 +137,7 @@ LWOCLONEID RocketLaunchpadControlComponent::GetSelectedCloneId(LWOOBJID player)
|
||||
|
||||
void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PREP_ZONE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::PREP_ZONE);
|
||||
bitStream.Write(zoneID);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Database.h"
|
||||
#include "Logger.h"
|
||||
#include "Game.h"
|
||||
#include "dServer.h"
|
||||
|
||||
//! The persistent ID request
|
||||
struct PersistentIDRequest {
|
||||
@ -25,7 +26,7 @@ namespace {
|
||||
void ObjectIDManager::RequestPersistentID(const std::function<void(uint32_t)> 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
|
||||
|
@ -45,9 +45,10 @@
|
||||
|
||||
// Enums
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
#include "eInventoryType.h"
|
||||
#include "ePlayerFlag.h"
|
||||
#include <RakNetTransportLayer.h>
|
||||
|
||||
|
||||
namespace DEVGMCommands {
|
||||
@ -503,7 +504,7 @@ namespace DEVGMCommands {
|
||||
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":
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_UNIVERSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN_UNIVERSE);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Sent universe shutdown notification to master.");
|
||||
|
||||
@ -1247,8 +1248,16 @@ namespace DEVGMCommands {
|
||||
|
||||
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!");
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "MasterPackets.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.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());
|
||||
|
||||
MasterPackets::SendZoneTransferResponse(
|
||||
Game::server,
|
||||
Game::server->GetTransportLayerPtr(),
|
||||
request.sysAddr,
|
||||
request.id,
|
||||
request.mythranShift,
|
||||
@ -177,7 +177,7 @@ void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstan
|
||||
|
||||
CBITSTREAM;
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_REQUEST);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::AFFIRM_TRANSFER_REQUEST);
|
||||
|
||||
bitStream.Write(request.id);
|
||||
|
||||
@ -200,7 +200,7 @@ void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transfer
|
||||
const auto& zoneId = instance->GetZoneID();
|
||||
|
||||
MasterPackets::SendZoneTransferResponse(
|
||||
Game::server,
|
||||
Game::server->GetTransportLayerPtr(),
|
||||
request.sysAddr,
|
||||
request.id,
|
||||
request.mythranShift,
|
||||
@ -359,7 +359,7 @@ bool Instance::GetShutdownComplete() const {
|
||||
void Instance::Shutdown() {
|
||||
CBITSTREAM;
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN);
|
||||
|
||||
Game::server->Send(bitStream, this->m_SysAddr, false);
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "AssetManager.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
|
||||
//RakNet includes:
|
||||
#include "RakNetDefines.h"
|
||||
@ -295,7 +295,7 @@ int main(int argc, char** argv) {
|
||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||
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";
|
||||
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
||||
@ -473,8 +473,8 @@ void HandlePacket(Packet* packet) {
|
||||
if (packet->length < 4) return;
|
||||
|
||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
||||
case eMasterMessageType::REQUEST_PERSISTENT_ID: {
|
||||
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||
case eManagerMessageType::REQUEST_PERSISTENT_ID: {
|
||||
LOG("A persistent ID req");
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
@ -482,11 +482,11 @@ void HandlePacket(Packet* packet) {
|
||||
inStream.Read(requestID);
|
||||
|
||||
uint32_t objID = PersistentIDManager::GeneratePersistentID();
|
||||
MasterPackets::SendPersistentIDResponse(Game::server, packet->systemAddress, requestID, objID);
|
||||
MasterPackets::SendPersistentIDResponse(Game::server->GetTransportLayerPtr(), packet->systemAddress, requestID, objID);
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::REQUEST_ZONE_TRANSFER: {
|
||||
case eManagerMessageType::REQUEST_ZONE_TRANSFER: {
|
||||
LOG("Received zone transfer req");
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
@ -522,7 +522,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SERVER_INFO: {
|
||||
case eManagerMessageType::SERVER_INFO: {
|
||||
//MasterPackets::HandleServerInfo(packet);
|
||||
|
||||
//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(theirIP);
|
||||
|
||||
LOG("Received server info, %i %i %i %i %s", theirPort, theirZoneID, theirInstanceID, theirServerType, theirIP.string.c_str());
|
||||
|
||||
if (theirServerType == ServerType::World) {
|
||||
if (!Game::im->IsPortInUse(theirPort)) {
|
||||
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.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);
|
||||
Game::im->AddInstance(in);
|
||||
} else {
|
||||
auto instance = Game::im->FindInstance(
|
||||
auto* instance = Game::im->FindInstance(
|
||||
theirZoneID, static_cast<uint16_t>(theirInstanceID));
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -583,7 +591,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SET_SESSION_KEY: {
|
||||
case eManagerMessageType::SET_SESSION_KEY: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
uint32_t sessionKey = 0;
|
||||
inStream.Read(sessionKey);
|
||||
@ -595,7 +603,7 @@ void HandlePacket(Packet* packet) {
|
||||
activeSessions.erase(it.first);
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::NEW_SESSION_ALERT);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::NEW_SESSION_ALERT);
|
||||
bitStream.Write(sessionKey);
|
||||
bitStream.Write(username);
|
||||
SEND_PACKET_BROADCAST;
|
||||
@ -609,7 +617,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::REQUEST_SESSION_KEY: {
|
||||
case eManagerMessageType::REQUEST_SESSION_KEY: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LUWString username;
|
||||
inStream.Read(username);
|
||||
@ -617,7 +625,7 @@ void HandlePacket(Packet* packet) {
|
||||
for (auto key : activeSessions) {
|
||||
if (key.second == username.GetAsString()) {
|
||||
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(username);
|
||||
Game::server->Send(bitStream, packet->systemAddress, false);
|
||||
@ -627,7 +635,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::PLAYER_ADDED: {
|
||||
case eManagerMessageType::PLAYER_ADDED: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -647,7 +655,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::PLAYER_REMOVED: {
|
||||
case eManagerMessageType::PLAYER_REMOVED: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -665,7 +673,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::CREATE_PRIVATE_ZONE: {
|
||||
case eManagerMessageType::CREATE_PRIVATE_ZONE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -689,7 +697,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::REQUEST_PRIVATE_ZONE: {
|
||||
case eManagerMessageType::REQUEST_PRIVATE_ZONE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -719,12 +727,12 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
case eMasterMessageType::WORLD_READY: {
|
||||
case eManagerMessageType::WORLD_READY: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -748,7 +756,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::PREP_ZONE: {
|
||||
case eManagerMessageType::PREP_ZONE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -764,7 +772,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::AFFIRM_TRANSFER_RESPONSE: {
|
||||
case eManagerMessageType::AFFIRM_TRANSFER_RESPONSE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -784,7 +792,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SHUTDOWN_RESPONSE: {
|
||||
case eManagerMessageType::SHUTDOWN_RESPONSE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
|
||||
@ -799,7 +807,7 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SHUTDOWN_UNIVERSE: {
|
||||
case eManagerMessageType::SHUTDOWN_UNIVERSE: {
|
||||
LOG("Received shutdown universe command, shutting down in 10 minutes.");
|
||||
Game::universeShutdownRequested = true;
|
||||
break;
|
||||
@ -829,7 +837,7 @@ int ShutdownSequence(int32_t signal) {
|
||||
|
||||
{
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN);
|
||||
Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
LOG("Triggered master shutdown");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "eLoginResponse.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eServerMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "StringifiedEnum.h"
|
||||
namespace {
|
||||
@ -60,7 +60,7 @@ void AuthPackets::HandleHandshake(dServer* server, Packet* packet) {
|
||||
|
||||
uint16_t 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);
|
||||
|
||||
@ -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:
|
||||
if (responseCode == eLoginResponse::SUCCESS) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SET_SESSION_KEY);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SET_SESSION_KEY);
|
||||
bitStream.Write(sessionKey);
|
||||
bitStream.Write(LUString(username));
|
||||
server->SendToMaster(bitStream);
|
||||
|
@ -5,10 +5,33 @@ set(DNET_SOURCES "AuthPackets.cpp"
|
||||
"MasterPackets.cpp"
|
||||
"PacketUtils.cpp"
|
||||
"WorldPackets.cpp"
|
||||
"RakNetTransportLayer.cpp"
|
||||
"RakNetPeer.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})
|
||||
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
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
|
@ -1,23 +1,23 @@
|
||||
#include "MasterPackets.h"
|
||||
#include "BitStream.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "dServer.h"
|
||||
#include "TransportLayer.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
#include "BitStreamUtils.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
void MasterPackets::SendPersistentIDRequest(dServer* server, uint64_t requestID) {
|
||||
void MasterPackets::SendPersistentIDRequest(TransportLayer* server, uint64_t requestID) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PERSISTENT_ID);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_PERSISTENT_ID);
|
||||
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;
|
||||
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(objID);
|
||||
@ -25,21 +25,21 @@ void MasterPackets::SendPersistentIDResponse(dServer* server, const SystemAddres
|
||||
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;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_ZONE_TRANSFER);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_ZONE_TRANSFER);
|
||||
|
||||
bitStream.Write(requestID);
|
||||
bitStream.Write<uint8_t>(mythranShift);
|
||||
bitStream.Write(zoneID);
|
||||
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;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::CREATE_PRIVATE_ZONE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::CREATE_PRIVATE_ZONE);
|
||||
|
||||
bitStream.Write(zoneID);
|
||||
bitStream.Write(cloneID);
|
||||
@ -49,12 +49,12 @@ void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint
|
||||
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;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_PRIVATE_ZONE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_PRIVATE_ZONE);
|
||||
|
||||
bitStream.Write(requestID);
|
||||
bitStream.Write<uint8_t>(mythranShift);
|
||||
@ -64,22 +64,22 @@ void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID,
|
||||
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;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::WORLD_READY);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::WORLD_READY);
|
||||
|
||||
bitStream.Write(zoneId);
|
||||
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;
|
||||
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<uint8_t>(mythranShift);
|
||||
@ -109,9 +109,9 @@ void MasterPackets::HandleServerInfo(Packet* packet) {
|
||||
//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;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SERVER_INFO);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SERVER_INFO);
|
||||
|
||||
bitStream.Write(server->GetPort());
|
||||
bitStream.Write(server->GetZoneID());
|
||||
@ -119,5 +119,5 @@ void MasterPackets::SendServerInfo(dServer* server, Packet* packet) {
|
||||
bitStream.Write(server->GetServerType());
|
||||
bitStream.Write(LUString(server->GetIP()));
|
||||
|
||||
server->SendToMaster(bitStream);
|
||||
server->SendToManager(bitStream);
|
||||
}
|
||||
|
@ -5,23 +5,23 @@
|
||||
#include <string>
|
||||
#include "RakNetTypes.h"
|
||||
#include "dCommonVars.h"
|
||||
class dServer;
|
||||
class TransportLayer;
|
||||
|
||||
namespace MasterPackets {
|
||||
void SendPersistentIDRequest(dServer* server, uint64_t requestID); //Called from the World server
|
||||
void SendPersistentIDResponse(dServer* server, const SystemAddress& sysAddr, uint64_t requestID, uint32_t objID);
|
||||
void SendPersistentIDRequest(TransportLayer* server, uint64_t requestID); //Called from the World server
|
||||
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 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 SendZoneTransferRequest(TransportLayer* server, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID);
|
||||
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 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);
|
||||
}
|
||||
|
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);
|
||||
|
||||
MasterPackets::SendZoneTransferRequest(server, request->requestID, mythranShift, zoneID, zoneClone);
|
||||
MasterPackets::SendZoneTransferRequest(server->GetTransportLayerPtr(), request->requestID, mythranShift, zoneID, zoneClone);
|
||||
}
|
||||
|
||||
//! 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) {
|
||||
MasterPackets::SendZoneCreatePrivate(server, zoneID, zoneClone, password);
|
||||
MasterPackets::SendZoneCreatePrivate(server->GetTransportLayerPtr(), zoneID, zoneClone, password);
|
||||
}
|
||||
|
||||
void ZoneInstanceManager::RequestPrivateZone(
|
||||
@ -72,5 +72,5 @@ void ZoneInstanceManager::RequestPrivateZone(
|
||||
|
||||
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 "eConnectionType.h"
|
||||
#include "eServerMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
|
||||
#include "BitStreamUtils.h"
|
||||
#include "MasterPackets.h"
|
||||
#include "ZoneInstanceManager.h"
|
||||
#include "StringifiedEnum.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;
|
||||
#include "RakNetTransportLayer.h"
|
||||
#ifdef NET_ENABLE_TCP_TRANSPORT
|
||||
#include "TcpTransportLayer.h"
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
//! 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!");
|
||||
}
|
||||
else {
|
||||
LOG("Using RakNet transport layer.");
|
||||
}
|
||||
|
||||
//Set up Replica if we're a world server:
|
||||
if (serverType == ServerType::World) {
|
||||
mNetIDManager = new NetworkIDManager();
|
||||
mNetIDManager->SetIsNetworkIDAuthority(true);
|
||||
switch (m_TransportType) {
|
||||
case TransportType::RakNet:
|
||||
m_TransportLayer = std::make_unique<RakNetTransportLayer>(
|
||||
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();
|
||||
mReplicaManager->SetAutoParticipateNewConnections(false);
|
||||
mReplicaManager->SetAutoConstructToNewParticipants(false);
|
||||
mReplicaManager->SetAutoSerializeInScope(true);
|
||||
mReplicaManager->SetReceiveConstructionCB(&ConstructionCB);
|
||||
mReplicaManager->SetDownloadCompleteCB(&SendDownloadCompleteCB, &ReceiveDownloadCompleteCB);
|
||||
bool okey = m_TransportLayer->Startup();
|
||||
|
||||
mPeer->AttachPlugin(mReplicaManager);
|
||||
mPeer->SetNetworkIDManager(mNetIDManager);
|
||||
if (!okey) {
|
||||
LOG("Failed to start the server!");
|
||||
|
||||
throw std::runtime_error("Failed to start the server!");
|
||||
}
|
||||
}
|
||||
|
||||
dServer::~dServer() {
|
||||
Shutdown();
|
||||
m_TransportLayer->Shutdown();
|
||||
|
||||
m_TransportLayer = nullptr;
|
||||
}
|
||||
|
||||
Packet* dServer::ReceiveFromMaster() {
|
||||
if (!mMasterPeer) return nullptr;
|
||||
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;
|
||||
return m_TransportLayer->ReceiveFromManager();
|
||||
}
|
||||
|
||||
Packet* dServer::Receive() {
|
||||
return mPeer->Receive();
|
||||
return m_TransportLayer->Receive();
|
||||
}
|
||||
|
||||
void dServer::DeallocatePacket(Packet* packet) {
|
||||
mPeer->DeallocatePacket(packet);
|
||||
m_TransportLayer->DeallocatePacket(packet);
|
||||
}
|
||||
|
||||
void dServer::DeallocateMasterPacket(Packet* packet) {
|
||||
mMasterPeer->DeallocatePacket(packet);
|
||||
m_TransportLayer->DeallocateManagerPacket(packet);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!mMasterConnectionActive) ConnectToMaster();
|
||||
mMasterPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, mMasterSystemAddress, false);
|
||||
m_TransportLayer->SendToManager(bitStream);
|
||||
}
|
||||
|
||||
void dServer::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);
|
||||
m_TransportLayer->Disconnect(sysAddr, disconNotifyID);
|
||||
}
|
||||
|
||||
bool dServer::IsConnected(const SystemAddress& sysAddr) {
|
||||
return mPeer->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);
|
||||
return m_TransportLayer->IsConnected(sysAddr);
|
||||
}
|
||||
|
||||
int dServer::GetPing(const SystemAddress& sysAddr) const {
|
||||
return mPeer->GetAveragePing(sysAddr);
|
||||
return m_TransportLayer->GetPing(sysAddr);
|
||||
}
|
||||
|
||||
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
|
||||
#include <string>
|
||||
#include <csignal>
|
||||
#include "RakPeerInterface.h"
|
||||
#include "ReplicaManager.h"
|
||||
#include "NetworkIDManager.h"
|
||||
#include <memory>
|
||||
|
||||
class Logger;
|
||||
class dConfig;
|
||||
enum class eServerDisconnectIdentifiers : uint32_t;
|
||||
#include "TransportLayer.h"
|
||||
|
||||
enum class ServerType : uint32_t {
|
||||
Master,
|
||||
Auth,
|
||||
Chat,
|
||||
World
|
||||
enum class TransportType : uint32_t {
|
||||
RakNet,
|
||||
Tcp
|
||||
};
|
||||
|
||||
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 {
|
||||
public:
|
||||
// Default constructor should only used for testing!
|
||||
@ -45,73 +27,85 @@ public:
|
||||
ServerType serverType,
|
||||
dConfig* config,
|
||||
Game::signal_t* shouldShutdown,
|
||||
unsigned int zoneID = 0);
|
||||
unsigned int zoneID = 0
|
||||
);
|
||||
|
||||
~dServer();
|
||||
|
||||
Packet* ReceiveFromMaster();
|
||||
|
||||
Packet* Receive();
|
||||
|
||||
void DeallocatePacket(Packet* packet);
|
||||
|
||||
void DeallocateMasterPacket(Packet* packet);
|
||||
|
||||
virtual void Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast);
|
||||
|
||||
void SendToMaster(RakNet::BitStream& bitStream);
|
||||
|
||||
void Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID);
|
||||
|
||||
bool IsConnected(const SystemAddress& sysAddr);
|
||||
const std::string& GetIP() const { return mIP; }
|
||||
const int GetPort() const { return mPort; }
|
||||
const int GetMaxConnections() const { return mMaxConnections; }
|
||||
const bool GetIsEncrypted() const { return mUseEncryption; }
|
||||
const bool GetIsInternal() const { return mIsInternal; }
|
||||
const bool GetIsOkay() const { return mIsOkay; }
|
||||
Logger* GetLogger() const { return mLogger; }
|
||||
const bool GetIsConnectedToMaster() const { return mMasterConnectionActive; }
|
||||
const unsigned int GetZoneID() const { return mZoneID; }
|
||||
const int GetInstanceID() const { return mInstanceID; }
|
||||
ReplicaManager* GetReplicaManager() { return mReplicaManager; }
|
||||
void UpdateReplica();
|
||||
void UpdateBandwidthLimit();
|
||||
void UpdateMaximumMtuSize();
|
||||
|
||||
const std::string& GetIP() const;
|
||||
|
||||
const int GetPort() const;
|
||||
|
||||
const int GetMaxConnections() const;
|
||||
|
||||
const bool GetIsEncrypted() const;
|
||||
|
||||
const bool GetIsInternal() const;
|
||||
|
||||
const bool GetIsOkay() const;
|
||||
|
||||
Logger* GetLogger() const;
|
||||
|
||||
const bool GetIsConnectedToMaster() const;
|
||||
|
||||
const unsigned int GetZoneID() const;
|
||||
|
||||
const int GetInstanceID() const;
|
||||
|
||||
int GetPing(const SystemAddress& sysAddr) const;
|
||||
|
||||
int GetLatestPing(const SystemAddress& sysAddr) const;
|
||||
|
||||
NetworkIDManager* GetNetworkIDManager() { return mNetIDManager; }
|
||||
|
||||
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;
|
||||
const ServerType GetServerType() const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
SocketDescriptor mSocketDescriptor;
|
||||
std::string mIP;
|
||||
int mPort;
|
||||
int mMaxConnections;
|
||||
unsigned int mZoneID;
|
||||
int mInstanceID;
|
||||
bool mUseEncryption;
|
||||
bool mIsInternal;
|
||||
bool mIsOkay;
|
||||
bool mMasterConnectionActive;
|
||||
ServerType mServerType;
|
||||
const std::unique_ptr<TransportLayer>& GetTransportLayer() const;
|
||||
|
||||
RakPeerInterface* mMasterPeer = nullptr;
|
||||
SocketDescriptor mMasterSocketDescriptor;
|
||||
SystemAddress mMasterSystemAddress;
|
||||
std::string mMasterIP;
|
||||
int mMasterPort;
|
||||
/**
|
||||
* @brief Gets the transport type.
|
||||
*
|
||||
* @return The transport type.
|
||||
*/
|
||||
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 "eChatMessageType.h"
|
||||
#include "eWorldMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
#include "eGameMessageType.h"
|
||||
#include "ZCompression.h"
|
||||
#include "EntityManager.h"
|
||||
@ -87,7 +87,7 @@ namespace Game {
|
||||
dChatFilter* chatFilter = nullptr;
|
||||
dConfig* config = nullptr;
|
||||
AssetManager* assetManager = nullptr;
|
||||
RakPeerInterface* chatServer = nullptr;
|
||||
TransportPeerInterface* chatServer = nullptr;
|
||||
std::mt19937 randomEngine;
|
||||
SystemAddress chatSysAddr;
|
||||
Game::signal_t lastSignal = 0;
|
||||
@ -218,10 +218,12 @@ int main(int argc, char** argv) {
|
||||
uint32_t chatPort = 1501;
|
||||
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 = RakNetworkFactory::GetRakPeerInterface();
|
||||
Game::chatServer->Startup(1, 30, &chatSock, 1);
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||
Game::chatServer = Game::server->GetTransportLayer()->CreateOutgoingTransport(
|
||||
ourPort + 2,
|
||||
masterIP,
|
||||
chatPort,
|
||||
"3.25 ND1"
|
||||
);
|
||||
|
||||
//Set up other things:
|
||||
Game::randomEngine = std::mt19937(time(0));
|
||||
@ -379,7 +381,7 @@ int main(int argc, char** argv) {
|
||||
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
||||
framesSinceChatDisconnect = 0;
|
||||
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||
Game::chatServer->Reconnect();
|
||||
}
|
||||
} else framesSinceChatDisconnect = 0;
|
||||
|
||||
@ -447,9 +449,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
Metrics::StartMeasurement(MetricVariable::UpdateReplica);
|
||||
|
||||
//Update our replica objects:
|
||||
Game::server->UpdateReplica();
|
||||
|
||||
Metrics::EndMeasurement(MetricVariable::UpdateReplica);
|
||||
|
||||
//Push our log every 15s:
|
||||
@ -510,7 +509,7 @@ int main(int argc, char** argv) {
|
||||
if (framesSinceMasterStatus >= 200) {
|
||||
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;
|
||||
}
|
||||
@ -663,8 +662,8 @@ void HandlePacketChat(Packet* packet) {
|
||||
void HandleMasterPacket(Packet* packet) {
|
||||
if (packet->length < 2) return;
|
||||
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::MASTER || packet->length < 4) return;
|
||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
||||
case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
||||
switch (static_cast<eManagerMessageType>(packet->data[3])) {
|
||||
case eManagerMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
uint64_t requestID;
|
||||
inStream.Read(requestID);
|
||||
@ -674,7 +673,7 @@ void HandleMasterPacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SESSION_KEY_RESPONSE: {
|
||||
case eManagerMessageType::SESSION_KEY_RESPONSE: {
|
||||
//Read our session key and to which user it belongs:
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
uint32_t sessionKey = 0;
|
||||
@ -729,7 +728,7 @@ void HandleMasterPacket(Packet* packet) {
|
||||
//Notify master:
|
||||
{
|
||||
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<LWOINSTANCEID>(instanceID);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
@ -738,7 +737,7 @@ void HandleMasterPacket(Packet* packet) {
|
||||
|
||||
break;
|
||||
}
|
||||
case eMasterMessageType::AFFIRM_TRANSFER_REQUEST: {
|
||||
case eManagerMessageType::AFFIRM_TRANSFER_REQUEST: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
uint64_t requestID;
|
||||
inStream.Read(requestID);
|
||||
@ -746,20 +745,20 @@ void HandleMasterPacket(Packet* packet) {
|
||||
|
||||
CBITSTREAM;
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::AFFIRM_TRANSFER_RESPONSE);
|
||||
bitStream.Write(requestID);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::SHUTDOWN: {
|
||||
case eManagerMessageType::SHUTDOWN: {
|
||||
Game::lastSignal = -1;
|
||||
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
||||
break;
|
||||
}
|
||||
|
||||
case eMasterMessageType::NEW_SESSION_ALERT: {
|
||||
case eManagerMessageType::NEW_SESSION_ALERT: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
uint32_t sessionKey = inStream.Read(sessionKey);
|
||||
|
||||
@ -832,7 +831,7 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
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<LWOINSTANCEID>(instanceID);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
@ -896,7 +895,7 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
//Request the session info from Master:
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::REQUEST_SESSION_KEY);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::REQUEST_SESSION_KEY);
|
||||
bitStream.Write(username);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
|
||||
@ -1017,8 +1016,7 @@ void HandlePacket(Packet* packet) {
|
||||
Character* c = user->GetLastUsedChar();
|
||||
if (c != nullptr) {
|
||||
std::u16string username = GeneralUtils::ASCIIToUTF16(c->GetName());
|
||||
Game::server->GetReplicaManager()->AddParticipant(packet->systemAddress);
|
||||
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = 1;
|
||||
Entity* player = Game::entityManager->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress));
|
||||
@ -1385,10 +1383,7 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
void WorldShutdownProcess(uint32_t zoneId) {
|
||||
LOG("Saving map %i instance %i", zoneId, instanceID);
|
||||
for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) {
|
||||
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i);
|
||||
|
||||
auto* entity = PlayerManager::GetPlayer(player);
|
||||
for (auto* entity : PlayerManager::GetAllPlayers()) {
|
||||
LOG("Saving data!");
|
||||
if (entity != nullptr && entity->GetCharacter() != nullptr) {
|
||||
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);
|
||||
|
||||
while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) {
|
||||
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0);
|
||||
for (auto* entity : PlayerManager::GetAllPlayers()) {
|
||||
const auto& player = entity->GetSystemAddress();
|
||||
|
||||
Game::server->Disconnect(player, eServerDisconnectIdentifiers::SERVER_SHUTDOWN);
|
||||
}
|
||||
@ -1463,6 +1458,6 @@ void FinalizeShutdown() {
|
||||
|
||||
void SendShutdownMessageToMaster() {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SHUTDOWN_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eManagerMessageType::SHUTDOWN_RESPONSE);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "GameDependencies.h"
|
||||
|
||||
#include "TransportPeerInterface.h"
|
||||
|
||||
namespace Game {
|
||||
Logger* logger = nullptr;
|
||||
dServer* server = nullptr;
|
||||
@ -7,7 +9,7 @@ namespace Game {
|
||||
dChatFilter* chatFilter = nullptr;
|
||||
dConfig* config = nullptr;
|
||||
std::mt19937 randomEngine;
|
||||
RakPeerInterface* chatServer = nullptr;
|
||||
TransportPeerInterface* chatServer = nullptr;
|
||||
AssetManager* assetManager = nullptr;
|
||||
SystemAddress chatSysAddr;
|
||||
EntityManager* entityManager = nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user