Compare commits

...

2 Commits

Author SHA1 Message Date
David Markowitz
1847d03c7b Server: Fix bugs 2023-10-06 02:54:59 -07:00
David Markowitz
e10351bde6 Server: Secure Master packet handling 2023-10-06 01:57:18 -07:00
5 changed files with 140 additions and 108 deletions

View File

@@ -22,6 +22,9 @@
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eServerMessageType.h" #include "eServerMessageType.h"
#include "eAuthMessageType.h" #include "eAuthMessageType.h"
#include "eMasterMessageType.h"
#include "PacketUtils.h"
#include "ZoneInstanceManager.h"
#include "Game.h" #include "Game.h"
namespace Game { namespace Game {
@@ -115,7 +118,13 @@ int main(int argc, char** argv) {
//In world we'd update our other systems here. //In world we'd update our other systems here.
//Check for packets here: //Check for packets here:
Game::server->ReceiveFromMaster(); //ReceiveFromMaster also handles the master packets if needed. packet = Game::server->ReceiveFromMaster();
if (packet) {
HandlePacket(packet);
Game::server->DeallocatePacket(packet);
packet = nullptr;
}
packet = Game::server->Receive(); packet = Game::server->Receive();
if (packet) { if (packet) {
HandlePacket(packet); HandlePacket(packet);
@@ -185,6 +194,21 @@ void HandlePacket(Packet* packet) {
if (static_cast<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) { if (static_cast<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) {
AuthPackets::HandleLoginRequest(Game::server, packet); AuthPackets::HandleLoginRequest(Game::server, packet);
} }
} else if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
switch (static_cast<eMasterMessageType>(packet->data[3])) {
case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
uint64_t requestID = PacketUtils::ReadU64(8, packet);
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet);
break;
}
case eMasterMessageType::SHUTDOWN: {
Game::shouldShutdown = true;
Game::logger->Log("AuthServer", "Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
break;
}
}
} }
} }
} }

View File

@@ -25,6 +25,9 @@
//RakNet includes: //RakNet includes:
#include "RakNetDefines.h" #include "RakNetDefines.h"
#include <MessageIdentifiers.h> #include <MessageIdentifiers.h>
#include "eMasterMessageType.h"
#include "PacketUtils.h"
#include "ZoneInstanceManager.h"
namespace Game { namespace Game {
dLogger* logger = nullptr; dLogger* logger = nullptr;
@@ -115,7 +118,7 @@ int main(int argc, char** argv) {
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown); Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
//Run it until server gets a kill message from Master: //Run it until server gets a kill message from Master:
@@ -139,7 +142,13 @@ int main(int argc, char** argv) {
//In world we'd update our other systems here. //In world we'd update our other systems here.
//Check for packets here: //Check for packets here:
Game::server->ReceiveFromMaster(); //ReceiveFromMaster also handles the master packets if needed. packet = Game::server->ReceiveFromMaster();
if (packet) {
HandlePacket(packet);
Game::server->DeallocatePacket(packet);
packet = nullptr;
}
packet = Game::server->Receive(); packet = Game::server->Receive();
if (packet) { if (packet) {
HandlePacket(packet); HandlePacket(packet);
@@ -207,7 +216,22 @@ void HandlePacket(Packet* packet) {
} }
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue. if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
switch (static_cast<eMasterMessageType>(packet->data[3])) {
case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
uint64_t requestID = PacketUtils::ReadU64(8, packet);
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet);
break;
}
case eMasterMessageType::SHUTDOWN: {
Game::shouldShutdown = true;
Game::logger->Log("ChatServer", "Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
break;
}
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) { if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) { switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION: case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:

View File

@@ -180,7 +180,7 @@ void InstanceManager::ReadyInstance(Instance* instance) {
const auto& zoneId = instance->GetZoneID(); const auto& zoneId = instance->GetZoneID();
Game::logger->Log("InstanceManager", "Responding to pending request %llu -> %i (%i)", request, zoneId.GetMapID(), zoneId.GetCloneID()); Game::logger->Log("InstanceManager", "Responding to pending request %llu -> %i (%i)", request, zoneId.GetMapID(), zoneId.GetCloneID());
Game::logger->Log("InstanceManager", "%s", request.sysAddr.ToString());
MasterPackets::SendZoneTransferResponse( MasterPackets::SendZoneTransferResponse(
Game::server, Game::server,
request.sysAddr, request.sysAddr,

View File

@@ -110,40 +110,20 @@ Packet* dServer::ReceiveFromMaster() {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) { if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
mLogger->Log("dServer", "Lost our connection to master, shutting DOWN!"); mLogger->Log("dServer", "Lost our connection to master, shutting DOWN!");
mMasterConnectionActive = false; mMasterConnectionActive = false;
mMasterPeer->DeallocatePacket(packet);
packet = nullptr;
//ConnectToMaster(); //We'll just shut down now //ConnectToMaster(); //We'll just shut down now
} } else if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
mLogger->Log("dServer", "Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID()); mLogger->Log("dServer", "Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
mMasterConnectionActive = true; mMasterConnectionActive = true;
mMasterSystemAddress = packet->systemAddress; mMasterSystemAddress = packet->systemAddress;
MasterPackets::SendServerInfo(this, packet); MasterPackets::SendServerInfo(this, packet);
mMasterPeer->DeallocatePacket(packet);
packet = nullptr;
} }
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: {
uint64_t requestID = PacketUtils::ReadU64(8, packet);
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet);
break;
}
case eMasterMessageType::SHUTDOWN:
*mShouldShutdown = true;
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 packet;
} }
Packet* dServer::Receive() { Packet* dServer::Receive() {

View File

@@ -97,6 +97,7 @@ void WorldShutdownSequence();
void WorldShutdownProcess(uint32_t zoneId); void WorldShutdownProcess(uint32_t zoneId);
void FinalizeShutdown(); void FinalizeShutdown();
void SendShutdownMessageToMaster(); void SendShutdownMessageToMaster();
void HandleMasterPacket(Packet* packet);
dLogger* SetupLogger(uint32_t zoneID, uint32_t instanceID); dLogger* SetupLogger(uint32_t zoneID, uint32_t instanceID);
void HandlePacketChat(Packet* packet); void HandlePacketChat(Packet* packet);
@@ -413,7 +414,7 @@ int main(int argc, char** argv) {
//Check for packets here: //Check for packets here:
packet = Game::server->ReceiveFromMaster(); packet = Game::server->ReceiveFromMaster();
if (packet) { //We can get messages not handle-able by the dServer class, so handle them if we returned anything. if (packet) { //We can get messages not handle-able by the dServer class, so handle them if we returned anything.
HandlePacket(packet); HandleMasterPacket(packet);
Game::server->DeallocateMasterPacket(packet); Game::server->DeallocateMasterPacket(packet);
} }
@@ -433,6 +434,7 @@ int main(int argc, char** argv) {
for (uint32_t curPacket = 0; curPacket < maxPacketsToProcess && timeSpent < maxPacketProcessingTime; curPacket++) { for (uint32_t curPacket = 0; curPacket < maxPacketsToProcess && timeSpent < maxPacketProcessingTime; curPacket++) {
packet = Game::server->Receive(); packet = Game::server->Receive();
if (packet) { if (packet) {
Game::logger->Log("WorldServer", "packet sysAddr %s", packet->systemAddress.ToString());
auto t1 = std::chrono::high_resolution_clock::now(); auto t1 = std::chrono::high_resolution_clock::now();
HandlePacket(packet); HandlePacket(packet);
auto t2 = std::chrono::high_resolution_clock::now(); auto t2 = std::chrono::high_resolution_clock::now();
@@ -677,64 +679,7 @@ void HandlePacketChat(Packet* packet) {
} }
} }
void HandlePacket(Packet* packet) { void HandleMasterPacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
if (!user) return;
auto c = user->GetLastUsedChar();
if (!c) {
UserManager::Instance()->DeleteUser(packet->systemAddress);
return;
}
auto* entity = Game::entityManager->GetEntity(c->GetObjectID());
if (!entity) {
entity = Player::GetPlayer(packet->systemAddress);
}
if (entity) {
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->Reset();
}
entity->GetCharacter()->SaveXMLToDatabase();
Game::logger->Log("WorldServer", "Deleting player %llu", entity->GetObjectID());
Game::entityManager->DestroyEntity(entity);
}
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
bitStream.Write(user->GetLoggedInChar());
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
}
UserManager::Instance()->DeleteUser(packet->systemAddress);
if (PropertyManagementComponent::Instance() != nullptr) {
PropertyManagementComponent::Instance()->Save();
}
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_REMOVED);
bitStream.Write((LWOMAPID)Game::server->GetZoneID());
bitStream.Write((LWOINSTANCEID)instanceID);
Game::server->SendToMaster(&bitStream);
}
if (packet->data[0] != ID_USER_PACKET_ENUM || packet->length < 4) return;
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
AuthPackets::HandleHandshake(Game::server, packet);
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) { if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
switch (static_cast<eMasterMessageType>(packet->data[3])) { switch (static_cast<eMasterMessageType>(packet->data[3])) {
case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: { case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
@@ -873,6 +818,65 @@ void HandlePacket(Packet* packet) {
return; return;
} }
}
void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
if (!user) return;
auto c = user->GetLastUsedChar();
if (!c) {
UserManager::Instance()->DeleteUser(packet->systemAddress);
return;
}
auto* entity = Game::entityManager->GetEntity(c->GetObjectID());
if (!entity) {
entity = Player::GetPlayer(packet->systemAddress);
}
if (entity) {
auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->Reset();
}
entity->GetCharacter()->SaveXMLToDatabase();
Game::logger->Log("WorldServer", "Deleting player %llu", entity->GetObjectID());
Game::entityManager->DestroyEntity(entity);
}
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
bitStream.Write(user->GetLoggedInChar());
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
}
UserManager::Instance()->DeleteUser(packet->systemAddress);
if (PropertyManagementComponent::Instance() != nullptr) {
PropertyManagementComponent::Instance()->Save();
}
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_REMOVED);
bitStream.Write((LWOMAPID)Game::server->GetZoneID());
bitStream.Write((LWOINSTANCEID)instanceID);
Game::server->SendToMaster(&bitStream);
}
if (packet->data[0] != ID_USER_PACKET_ENUM || packet->length < 4) return;
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
AuthPackets::HandleHandshake(Game::server, packet);
}
}
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::WORLD) return; if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::WORLD) return;
@@ -964,7 +968,7 @@ void HandlePacket(Packet* packet) {
CheckType::Entity, CheckType::Entity,
"Sending GM with a sending player that does not match their own. GM ID: %i", "Sending GM with a sending player that does not match their own. GM ID: %i",
static_cast<int32_t>(messageID) static_cast<int32_t>(messageID)
); );
if (isSender) GameMessageHandler::HandleMessage(&dataStream, packet->systemAddress, objectID, messageID); if (isSender) GameMessageHandler::HandleMessage(&dataStream, packet->systemAddress, objectID, messageID);
break; break;
@@ -988,7 +992,7 @@ void HandlePacket(Packet* packet) {
CheckType::User, CheckType::User,
"Sending login request with a sending player that does not match their own. Player ID: %llu", "Sending login request with a sending player that does not match their own. Player ID: %llu",
playerID playerID
); );
if (!valid) return; if (!valid) return;
@@ -1059,23 +1063,23 @@ void HandlePacket(Packet* packet) {
if (!levelComponent) return; if (!levelComponent) return;
auto version = levelComponent->GetCharacterVersion(); auto version = levelComponent->GetCharacterVersion();
switch(version) { switch (version) {
case eCharacterVersion::RELEASE: case eCharacterVersion::RELEASE:
// TODO: Implement, super low priority // TODO: Implement, super low priority
case eCharacterVersion::LIVE: case eCharacterVersion::LIVE:
Game::logger->Log("WorldServer", "Updating Character Flags"); Game::logger->Log("WorldServer", "Updating Character Flags");
c->SetRetroactiveFlags(); c->SetRetroactiveFlags();
levelComponent->SetCharacterVersion(eCharacterVersion::PLAYER_FACTION_FLAGS); levelComponent->SetCharacterVersion(eCharacterVersion::PLAYER_FACTION_FLAGS);
case eCharacterVersion::PLAYER_FACTION_FLAGS: case eCharacterVersion::PLAYER_FACTION_FLAGS:
Game::logger->Log("WorldServer", "Updating Vault Size"); Game::logger->Log("WorldServer", "Updating Vault Size");
player->RetroactiveVaultSize(); player->RetroactiveVaultSize();
levelComponent->SetCharacterVersion(eCharacterVersion::VAULT_SIZE); levelComponent->SetCharacterVersion(eCharacterVersion::VAULT_SIZE);
case eCharacterVersion::VAULT_SIZE: case eCharacterVersion::VAULT_SIZE:
Game::logger->Log("WorldServer", "Updaing Speedbase"); Game::logger->Log("WorldServer", "Updaing Speedbase");
levelComponent->SetRetroactiveBaseSpeed(); levelComponent->SetRetroactiveBaseSpeed();
levelComponent->SetCharacterVersion(eCharacterVersion::UP_TO_DATE); levelComponent->SetCharacterVersion(eCharacterVersion::UP_TO_DATE);
case eCharacterVersion::UP_TO_DATE: case eCharacterVersion::UP_TO_DATE:
break; break;
} }
player->GetCharacter()->SetTargetScene(""); player->GetCharacter()->SetTargetScene("");