Files
Starworld/src/NLPacketCodec.hpp

195 lines
5.2 KiB
C++

// NLPacketCodec.hpp
// Minimal NLPacket protocol implementation for Overte domain communication
// Based on Overte's NLPacket.h specification
#pragma once
#include <cstdint>
#include <vector>
#include <cstring>
#include <string>
namespace Overte {
// Packet types from Overte protocol
enum class PacketType : uint8_t {
Unknown,
DomainConnectRequestPending,
DomainList,
Ping,
PingReply,
KillAvatar,
AvatarData,
InjectAudio,
MixedAudio,
MicrophoneAudioNoEcho,
MicrophoneAudioWithEcho,
BulkAvatarData,
SilentAudioFrame,
DomainListRequest,
RequestAssignment,
CreateAssignment,
DomainConnectionDenied,
MuteEnvironment,
AudioStreamStats,
DomainServerPathQuery,
DomainServerPathResponse,
DomainServerAddedNode,
ICEServerPeerInformation,
ICEServerQuery,
OctreeStats,
SetAvatarTraits,
InjectorGainSet,
AssignmentClientStatus,
NoisyMute,
AvatarIdentity,
NodeIgnoreRequest,
DomainConnectRequest,
DomainServerRequireDTLS,
NodeJsonStats,
OctreeDataNack,
StopNode,
AudioEnvironment,
EntityEditNack,
ICEServerHeartbeat,
ICEPing,
ICEPingReply,
EntityData,
EntityQuery,
EntityAdd,
EntityErase,
EntityEdit,
DomainServerConnectionToken,
DomainSettingsRequest,
DomainSettings,
AssetGet,
AssetGetReply,
AssetUpload,
AssetUploadReply,
AssetGetInfo,
AssetGetInfoReply,
DomainDisconnectRequest,
DomainServerRemovedNode,
MessagesData,
MessagesSubscribe,
MessagesUnsubscribe,
ICEServerHeartbeatDenied,
AssetMappingOperation,
AssetMappingOperationReply,
ICEServerHeartbeatACK,
NegotiateAudioFormat,
SelectedAudioFormat,
MoreEntityShapes,
NodeKickRequest,
NodeMuteRequest,
RadiusIgnoreRequest,
UsernameFromIDRequest,
UsernameFromIDReply,
AvatarQuery,
RequestsDomainListData,
PerAvatarGainSet,
EntityScriptGetStatus,
EntityScriptGetStatusReply,
ReloadEntityServerScript,
EntityPhysics,
EntityServerScriptLog,
AdjustAvatarSorting,
OctreeFileReplacement,
CollisionEventChanges,
ReplicatedMicrophoneAudioNoEcho,
ReplicatedMicrophoneAudioWithEcho,
ReplicatedInjectAudio,
ReplicatedSilentAudioFrame,
ReplicatedAvatarIdentity,
ReplicatedKillAvatar,
ReplicatedBulkAvatarData,
DomainContentReplacementFromUrl,
DropOnNextProtocolChange_1,
EntityScriptCallMethod,
DropOnNextProtocolChange_2,
DropOnNextProtocolChange_3,
OctreeDataFileRequest,
OctreeDataFileReply,
OctreeDataPersist,
EntityClone,
EntityQueryInitialResultsComplete,
BulkAvatarTraits,
AudioSoloRequest,
BulkAvatarTraitsAck,
StopInjector,
AvatarZonePresence,
WebRTCSignaling,
NUM_PACKET_TYPE
};
using PacketVersion = uint8_t;
using LocalID = uint16_t;
using SequenceNumber = uint32_t;
// Packet version constants (from Overte source)
namespace PacketVersions {
constexpr PacketVersion DomainConnectRequest_SocketTypes = 27; // NoHostname(17) + 10
constexpr PacketVersion DomainListRequest_SocketTypes = 23; // PreSocketTypes(22) + 1
constexpr PacketVersion DomainList_SocketTypes = 25; // PrePermissionsGrid(18) + 7
constexpr PacketVersion Ping_IncludeConnectionID = 18;
}
// NLPacket structure (minimal implementation)
class NLPacket {
public:
// Packet header components
struct Header {
uint32_t sequenceAndFlags; // Sequence number (29 bits) + flags (3 bits)
PacketType type;
PacketVersion version;
LocalID sourceID; // Only for sourced packets
};
static constexpr LocalID NULL_LOCAL_ID = 0;
static constexpr size_t BASE_HEADER_SIZE = sizeof(uint32_t) + sizeof(PacketType) + sizeof(PacketVersion);
static constexpr size_t SOURCED_HEADER_SIZE = BASE_HEADER_SIZE + sizeof(LocalID);
NLPacket(PacketType type, PacketVersion version = 0, bool isReliable = false);
// Write data to packet payload
void write(const void* data, size_t size);
void writeUInt8(uint8_t value);
void writeUInt16(uint16_t value);
void writeUInt32(uint32_t value);
void writeUInt64(uint64_t value);
void writeString(const std::string& str, bool nullTerminated = true);
// Get packet data for sending
const std::vector<uint8_t>& getData() const { return m_data; }
size_t getSize() const { return m_data.size(); }
// Parse received packet
static bool parseHeader(const uint8_t* data, size_t size, Header& header);
static PacketType getType(const uint8_t* data, size_t size);
void setSequenceNumber(SequenceNumber seq);
void setSourceID(LocalID id);
// Write HMAC-MD5 verification hash
void writeVerificationHash(const uint8_t* connectionSecretUUID);
// Protocol version signature
static std::vector<uint8_t> computeProtocolVersionSignature();
static uint8_t versionForPacketType(PacketType type);
private:
void writeHeader();
PacketType m_type;
PacketVersion m_version;
SequenceNumber m_sequenceNumber{0};
LocalID m_sourceID{NULL_LOCAL_ID};
bool m_isReliable;
bool m_isSourced{false};
std::vector<uint8_t> m_data;
size_t m_headerSize;
};
} // namespace Overte