mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
Nothing in the server writes or reads a packet by hand any more, so the helpers for doing so go: - CBITSTREAM, CMSGHEADER, CINSTREAM, CINSTREAM_SKIP_HEADER, SEND_PACKET, SEND_PACKET_BROADCAST and HEADER_SIZE leave dCommonVars.h; - the free BitStreamUtils::WriteHeader (LUBitStream::WriteHeader writes the same bytes) and the unused PacketUtils::SavePacket are deleted. The last raw reads are replaced: WorldServer builds its input stream directly, the master packet logs read the header with LUBitStream::ReadHeader instead of peeking at packet->data[1] and [3], and MessageInspector reads a sent game message's header with the new NetGameMsg::ReadPacketHeader (the counterpart of WritePacket) instead of memcmp/memcpy. packet->data[0] is still compared with RakNet's own connection IDs. The frozen oracles keep using the macros verbatim through the test-only tests/dGameTests/LegacyPacketMacros.h; the HeaderSkip tests, which only tested CINSTREAM_SKIP_HEADER, are removed. docs/PacketArchitecture.md: "where we are" now describes the final state and what still touches raw bytes (RakNet IDs, replica headers, behavior bit streams), and a new section collects the known wire discrepancies found during the conversion, with client addresses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
394 lines
14 KiB
C++
394 lines
14 KiB
C++
#ifndef MASTERPACKETSLEGACY_H
|
|
#define MASTERPACKETSLEGACY_H
|
|
|
|
// FROZEN ORACLE - DO NOT EDIT.
|
|
// Verbatim copies of the hand written master packet code that dNet/MasterPackets.h replaced (dNet/MasterPackets.cpp,
|
|
// dNet/ZoneInstanceManager.cpp, dMasterServer/{MasterServer,InstanceManager}.cpp, dWorldServer/WorldServer.cpp,
|
|
// dDashboardServer/DashboardServer.cpp and the other senders at 9a392167, with the login stamps). Only the namespace changed, except:
|
|
// - senders write into `bitStream` instead of sending it (SendToMaster and the master's peers aren't mocked);
|
|
// - values the old code took from a server or an instance are passed in;
|
|
// - old readers return what they read in a struct instead of acting on it.
|
|
// These messages never reach a client, but master, worlds, auth, chat and the dashboard can run different builds
|
|
// during an update, so their bytes are pinned too.
|
|
|
|
#include "LegacyPacketMacros.h"
|
|
#include "BitStreamUtils.h"
|
|
#include "dCommonVars.h"
|
|
#include "MessageType/Master.h"
|
|
#include "ServiceType.h"
|
|
#include "Stamps.h"
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace LegacyMaster {
|
|
// dNet/MasterPackets.cpp
|
|
inline void SendZoneTransferRequest(RakNet::BitStream& bitStream, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t cloneID, const Stamps& stamps = {}) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::REQUEST_ZONE_TRANSFER);
|
|
|
|
bitStream.Write(requestID);
|
|
bitStream.Write<uint8_t>(mythranShift);
|
|
bitStream.Write(zoneID);
|
|
bitStream.Write(cloneID);
|
|
stamps.Serialize(bitStream);
|
|
}
|
|
|
|
inline void SendZoneCreatePrivate(RakNet::BitStream& bitStream, uint32_t zoneID, uint32_t cloneID, const std::string& password) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::CREATE_PRIVATE_ZONE);
|
|
|
|
bitStream.Write(zoneID);
|
|
bitStream.Write(cloneID);
|
|
|
|
bitStream.Write<uint32_t>(password.size());
|
|
for (auto character : password) {
|
|
bitStream.Write<char>(character);
|
|
}
|
|
}
|
|
|
|
inline void SendZoneRequestPrivate(RakNet::BitStream& bitStream, uint64_t requestID, bool mythranShift, const std::string& password) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::REQUEST_PRIVATE_ZONE);
|
|
|
|
bitStream.Write(requestID);
|
|
bitStream.Write<uint8_t>(mythranShift);
|
|
|
|
bitStream.Write<uint32_t>(password.size());
|
|
for (auto character : password) {
|
|
bitStream.Write<char>(character);
|
|
}
|
|
}
|
|
|
|
inline void SendWorldReady(RakNet::BitStream& bitStream, LWOMAPID zoneId, LWOINSTANCEID instanceId) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::WORLD_READY);
|
|
|
|
bitStream.Write(zoneId);
|
|
bitStream.Write(instanceId);
|
|
}
|
|
|
|
inline void SendZoneTransferResponse(RakNet::BitStream& bitStream, uint64_t requestID, bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, const std::string& serverIP, uint32_t serverPort, const Stamps& stamps = {}) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::REQUEST_ZONE_TRANSFER_RESPONSE);
|
|
|
|
bitStream.Write(requestID);
|
|
bitStream.Write<uint8_t>(mythranShift);
|
|
bitStream.Write(zoneID);
|
|
bitStream.Write(zoneInstance);
|
|
bitStream.Write(zoneClone);
|
|
bitStream.Write<uint16_t>(serverPort);
|
|
bitStream.Write(LUString(serverIP, 255));
|
|
stamps.Serialize(bitStream);
|
|
}
|
|
|
|
// SendServerInfo, with dServer's getters (int port, unsigned int zone, int instance) passed in
|
|
inline void SendServerInfo(RakNet::BitStream& bitStream, int port, unsigned int zoneID, int instanceID, ServiceType serverType, const std::string& ip) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::SERVER_INFO);
|
|
|
|
bitStream.Write(port);
|
|
bitStream.Write(zoneID);
|
|
bitStream.Write(instanceID);
|
|
bitStream.Write(serverType);
|
|
bitStream.Write(LUString(ip));
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp: a server went offline (to the dashboard)
|
|
inline void WriteServerOffline(RakNet::BitStream& bitStream, ServiceType type) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::SERVER_INFO);
|
|
bitStream.Write<uint32_t>(0);
|
|
bitStream.Write<uint32_t>(0);
|
|
bitStream.Write<uint32_t>(0);
|
|
bitStream.Write(type);
|
|
bitStream.Write(LUString("offline"));
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp: a world disconnected (to the dashboard)
|
|
inline void WriteWorldShutDown(RakNet::BitStream& bitStream, LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::SHUTDOWN_RESPONSE);
|
|
bitStream.Write(mapID);
|
|
bitStream.Write(instanceID);
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp: WORLD_READY (to the dashboard)
|
|
inline void WriteWorldReadyInfo(RakNet::BitStream& bitStream, LWOMAPID zoneID, LWOINSTANCEID instanceID, LWOCLONEID cloneID, const std::string& ip, uint32_t port, bool isPrivate) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::WORLD_READY);
|
|
bitStream.Write(zoneID);
|
|
bitStream.Write(instanceID);
|
|
bitStream.Write(cloneID);
|
|
bitStream.Write(LUString(ip));
|
|
bitStream.Write(port);
|
|
bitStream.Write<uint8_t>(isPrivate ? 1 : 0);
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp SET_SESSION_KEY, and dNet/AuthPackets.cpp
|
|
inline void WriteSessionKey(RakNet::BitStream& bitStream, MessageType::Master type, uint32_t sessionKey, const LUString& username) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, type);
|
|
bitStream.Write(sessionKey);
|
|
bitStream.Write(username);
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp REQUEST_SESSION_KEY
|
|
inline void WriteSessionKeyResponse(RakNet::BitStream& bitStream, uint32_t sessionKey, const LUWString& username) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::SESSION_KEY_RESPONSE);
|
|
bitStream.Write(sessionKey);
|
|
bitStream.Write(username);
|
|
}
|
|
|
|
// dWorldServer/WorldServer.cpp
|
|
inline void WriteRequestSessionKey(RakNet::BitStream& bitStream, const LUWString& username) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::REQUEST_SESSION_KEY);
|
|
bitStream.Write(username);
|
|
}
|
|
|
|
// dWorldServer/WorldServer.cpp and dMasterServer/MasterServer.cpp (PLAYER_ADDED and PLAYER_REMOVED)
|
|
inline void WritePlayerCount(RakNet::BitStream& bitStream, MessageType::Master type, LWOMAPID zoneID, LWOINSTANCEID instanceID) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, type);
|
|
bitStream.Write<LWOMAPID>(zoneID);
|
|
bitStream.Write<LWOINSTANCEID>(instanceID);
|
|
}
|
|
|
|
// dMasterServer/InstanceManager.cpp and dWorldServer/WorldServer.cpp (AFFIRM_TRANSFER_REQUEST and _RESPONSE)
|
|
inline void WriteAffirmTransfer(RakNet::BitStream& bitStream, MessageType::Master type, uint64_t requestID) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, type);
|
|
|
|
bitStream.Write(requestID);
|
|
}
|
|
|
|
// Messages with nothing after the header: SHUTDOWN, SHUTDOWN_RESPONSE (world), SHUTDOWN_UNIVERSE,
|
|
// REQUEST_SERVER_LIST, CONFIG_RELOAD, DASHBOARD_SHUTDOWN
|
|
inline void WriteEmpty(RakNet::BitStream& bitStream, MessageType::Master type) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, type);
|
|
}
|
|
|
|
// dGame/dComponents/RocketLaunchpadControlComponent.cpp
|
|
inline void TellMasterToPrepZone(RakNet::BitStream& bitStream, int zoneID) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::PREP_ZONE);
|
|
bitStream.Write(zoneID);
|
|
}
|
|
|
|
// dDashboardServer/routes/LiveWorld.cpp
|
|
inline void WriteInstanceShutdown(RakNet::BitStream& bitStream, uint32_t zone, uint32_t instance) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::INSTANCE_SHUTDOWN);
|
|
bitStream.Write(zone);
|
|
bitStream.Write(instance);
|
|
}
|
|
|
|
struct ServerListInstance {
|
|
LWOMAPID mapID{};
|
|
LWOINSTANCEID instanceID{};
|
|
LWOCLONEID cloneID{};
|
|
uint32_t players{};
|
|
std::string ip;
|
|
uint32_t port{};
|
|
bool isPrivate{};
|
|
};
|
|
|
|
// dMasterServer/MasterServer.cpp REQUEST_SERVER_LIST, with the ready instances passed in
|
|
inline void WriteServerList(RakNet::BitStream& bitStream, bool authOnline, bool chatOnline, const std::vector<ServerListInstance>& instances) {
|
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::SERVER_LIST_RESPONSE);
|
|
|
|
bitStream.Write<uint8_t>(authOnline ? 1 : 0);
|
|
bitStream.Write<uint8_t>(chatOnline ? 1 : 0);
|
|
|
|
uint32_t instanceCount = instances.size();
|
|
bitStream.Write(instanceCount);
|
|
|
|
for (const auto& inst : instances) {
|
|
bitStream.Write(inst.mapID);
|
|
bitStream.Write(inst.instanceID);
|
|
bitStream.Write(inst.cloneID);
|
|
bitStream.Write<uint32_t>(inst.players);
|
|
bitStream.Write(LUString(inst.ip));
|
|
bitStream.Write(inst.port);
|
|
bitStream.Write<uint8_t>(inst.isPrivate ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
// Readers. The stream is past the packet header.
|
|
|
|
struct TransferRequestRead {
|
|
uint64_t requestID = 0;
|
|
uint8_t mythranShift = false;
|
|
uint32_t zoneID = 0;
|
|
uint32_t zoneClone = 0;
|
|
Stamps stamps;
|
|
};
|
|
|
|
// dMasterServer/MasterServer.cpp REQUEST_ZONE_TRANSFER
|
|
inline TransferRequestRead ReadZoneTransferRequest(RakNet::BitStream& inStream) {
|
|
uint64_t requestID = 0;
|
|
uint8_t mythranShift = false;
|
|
uint32_t zoneID = 0;
|
|
uint32_t zoneClone = 0;
|
|
|
|
inStream.Read(requestID);
|
|
inStream.Read(mythranShift);
|
|
inStream.Read(zoneID);
|
|
inStream.Read(zoneClone);
|
|
// The login stamps travelling with the request (see Stamps.h)
|
|
Stamps stamps;
|
|
if (!stamps.Deserialize(inStream)) stamps = {};
|
|
return { requestID, mythranShift, zoneID, zoneClone, stamps };
|
|
}
|
|
|
|
struct TransferResponseRead {
|
|
uint64_t requestID{};
|
|
bool mythranShift{};
|
|
uint32_t zoneID{};
|
|
uint32_t zoneInstance{};
|
|
uint32_t zoneClone{};
|
|
uint16_t serverPort{};
|
|
std::string serverIP;
|
|
Stamps stamps;
|
|
};
|
|
|
|
// dNet/ZoneInstanceManager.cpp HandleRequestZoneTransferResponse
|
|
inline TransferResponseRead ReadZoneTransferResponse(RakNet::BitStream& inStream) {
|
|
uint64_t requestID;
|
|
inStream.Read(requestID);
|
|
bool mythranShift;
|
|
uint8_t tmp;
|
|
inStream.Read(tmp);
|
|
mythranShift = tmp > 0;
|
|
uint32_t zoneID;
|
|
inStream.Read(zoneID);
|
|
uint32_t zoneInstance;
|
|
inStream.Read(zoneInstance);
|
|
uint32_t zoneClone;
|
|
inStream.Read(zoneClone);
|
|
uint16_t serverPort;
|
|
inStream.Read(serverPort);
|
|
LUString serverIP(255);
|
|
inStream.Read(serverIP);
|
|
Stamps stamps;
|
|
if (!stamps.Deserialize(inStream)) stamps = {};
|
|
return { requestID, mythranShift, zoneID, zoneInstance, zoneClone, serverPort, serverIP.string, stamps };
|
|
}
|
|
|
|
struct ServerInfoRead {
|
|
uint32_t theirPort = 0;
|
|
uint32_t theirZoneID = 0;
|
|
uint32_t theirInstanceID = 0;
|
|
ServiceType theirServerType;
|
|
std::string theirIP;
|
|
};
|
|
|
|
// dMasterServer/MasterServer.cpp and dDashboardServer/DashboardServer.cpp SERVER_INFO
|
|
inline ServerInfoRead ReadServerInfo(RakNet::BitStream& inStream) {
|
|
uint32_t theirPort = 0;
|
|
uint32_t theirZoneID = 0;
|
|
uint32_t theirInstanceID = 0;
|
|
ServiceType theirServerType;
|
|
LUString theirIP;
|
|
|
|
inStream.Read(theirPort);
|
|
inStream.Read(theirZoneID);
|
|
inStream.Read(theirInstanceID);
|
|
inStream.Read(theirServerType);
|
|
inStream.Read(theirIP);
|
|
return { theirPort, theirZoneID, theirInstanceID, theirServerType, theirIP.string };
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp CREATE_PRIVATE_ZONE
|
|
inline std::pair<std::pair<uint32_t, LWOCLONEID>, std::string> ReadCreatePrivateZone(RakNet::BitStream& inStream) {
|
|
uint32_t mapId;
|
|
LWOCLONEID cloneId;
|
|
std::string password;
|
|
|
|
inStream.Read(mapId);
|
|
inStream.Read(cloneId);
|
|
|
|
uint32_t len;
|
|
inStream.Read<uint32_t>(len);
|
|
len = std::min<uint32_t>(len, 50); // cap the master password at 50 characters
|
|
|
|
for (uint32_t i = 0; len > i; i++) {
|
|
char character;
|
|
inStream.Read<char>(character);
|
|
password += character;
|
|
}
|
|
return { { mapId, cloneId }, password };
|
|
}
|
|
|
|
// dMasterServer/MasterServer.cpp REQUEST_PRIVATE_ZONE
|
|
inline std::pair<std::pair<uint64_t, uint8_t>, std::string> ReadRequestPrivateZone(RakNet::BitStream& inStream) {
|
|
uint64_t requestID = 0;
|
|
uint8_t mythranShift = false;
|
|
|
|
std::string password;
|
|
|
|
inStream.Read(requestID);
|
|
inStream.Read(mythranShift);
|
|
|
|
uint32_t len;
|
|
inStream.Read<uint32_t>(len);
|
|
len = std::min<uint32_t>(len, 50);
|
|
|
|
for (uint32_t i = 0; i < len; i++) {
|
|
char character; inStream.Read<char>(character);
|
|
password += character;
|
|
}
|
|
return { { requestID, mythranShift }, password };
|
|
}
|
|
|
|
struct ServerListRead {
|
|
uint8_t authOnline = 0;
|
|
uint8_t chatOnline = 0;
|
|
std::vector<ServerListInstance> instances;
|
|
};
|
|
|
|
// dDashboardServer/DashboardServer.cpp SERVER_LIST_RESPONSE
|
|
inline ServerListRead ReadServerList(RakNet::BitStream& inStream) {
|
|
ServerListRead out;
|
|
uint8_t authOnline = 0;
|
|
uint8_t chatOnline = 0;
|
|
uint32_t instanceCount = 0;
|
|
|
|
inStream.Read(authOnline);
|
|
inStream.Read(chatOnline);
|
|
inStream.Read(instanceCount);
|
|
out.authOnline = authOnline;
|
|
out.chatOnline = chatOnline;
|
|
|
|
for (uint32_t i = 0; i < instanceCount; i++) {
|
|
ServerListInstance info;
|
|
LUString ip;
|
|
// Same types as MasterServer writes them (map and instance IDs are 16 bits)
|
|
LWOMAPID mapID = 0;
|
|
LWOINSTANCEID instanceID = 0;
|
|
inStream.Read(mapID);
|
|
inStream.Read(instanceID);
|
|
info.mapID = mapID;
|
|
info.instanceID = instanceID;
|
|
inStream.Read(info.cloneID);
|
|
inStream.Read(info.players);
|
|
inStream.Read(ip);
|
|
info.ip = ip.string;
|
|
inStream.Read(info.port);
|
|
uint8_t isPrivate = 0;
|
|
inStream.Read(isPrivate);
|
|
info.isPrivate = isPrivate != 0;
|
|
out.instances.push_back(info);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// dDashboardServer/DashboardServer.cpp WORLD_READY
|
|
inline ServerListInstance ReadWorldReadyInfo(RakNet::BitStream& inStream) {
|
|
LWOMAPID zoneID;
|
|
LWOINSTANCEID instanceID;
|
|
LWOCLONEID cloneID;
|
|
LUString ip;
|
|
uint32_t port;
|
|
uint8_t isPrivate;
|
|
|
|
inStream.Read(zoneID);
|
|
inStream.Read(instanceID);
|
|
inStream.Read(cloneID);
|
|
inStream.Read(ip);
|
|
inStream.Read(port);
|
|
inStream.Read(isPrivate);
|
|
return { zoneID, instanceID, cloneID, 0, ip.string, port, isPrivate != 0 };
|
|
}
|
|
}
|
|
|
|
#endif // MASTERPACKETSLEGACY_H
|