r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
Protocol.hpp
Go to the documentation of this file.
1///
2/// @file Protocol.hpp
3/// @brief This file contains the network protocol
4/// @namespace rnp
5///
6
7#pragma once
8
9#include <cstdint>
10#include <cstring>
11#include <stdexcept>
12#include <vector>
13
14namespace rnp
15{
16
17 inline constexpr std::uint8_t PROTOCOL_VERSION = 1;
18 inline constexpr std::size_t MAX_PAYLOAD = 512;
19
20 ///
21 /// @brief Packet types according to RNP specification
22 ///
23 enum class PacketType : std::uint8_t
24 {
25 CONNECT = 0x01,
26 DISCONNECT = 0x02,
27 WORLD_STATE = 0x03,
28 PING = 0x04,
29 PONG = 0x05,
30 PACKET_ERROR = 0x06,
31 ACK = 0x07,
32 ENTITY_EVENT = 0x08,
33 CONNECT_ACCEPT = 0x09,
34 PLAYER_INPUT = 0x03 // Deprecated: use ENTITY_EVENT with INPUT type
35 };
36
37 ///
38 /// @brief Packet flags for reliability and fragmentation
39 ///
40 enum class PacketFlags : std::uint16_t
41 {
42 NONE = 0x0000,
43 ACK_REQ = 0x0001,
44 RELIABLE = 0x0002,
45 FRAG = 0x0004,
46 COMPRESSED = 0x0008
47 };
48
49 ///
50 /// @brief Disconnect reason codes
51 ///
52 enum class DisconnectReason : std::uint16_t
53 {
54 UNSPECIFIED = 0,
56 TIMEOUT = 2,
59 SERVER_FULL = 5,
60 BANNED = 6
61 };
62
63 ///
64 /// @brief Error codes
65 ///
66 enum class ErrorCode : std::uint16_t
67 {
70 RATE_LIMITED = 3,
72 };
73
74 ///
75 /// @brief Event types for ENTITY_EVENT packets
76 ///
77 enum class EventType : std::uint8_t
78 {
79 SPAWN = 0x01,
80 DESPAWN = 0x02,
81 DAMAGE = 0x03,
82 SCORE = 0x04,
83 POWERUP = 0x05,
84 INPUT = 0x06,
85 CUSTOM = 0xFF
86 };
87
88 ///
89 /// @brief Entity types for world state
90 ///
91 enum class EntityType : std::uint16_t
92 {
93 PLAYER = 0x01,
94 ENEMY = 0x02,
95 PROJECTILE = 0x03,
96 POWERUP = 0x04,
97 OBSTACLE = 0x05
98 };
99
100 ///
101 /// @brief Event record for ENTITY_EVENT packets (TLV format)
102 ///
104 {
106 std::uint32_t entityId;
107 std::vector<std::uint8_t> data;
108 };
109
110 ///
111 /// @brief Packet header according to RNP specification (Big Endian)
112 /// Total size: 16 bytes
113 ///
115 {
116 std::uint8_t type; // PacketType
117 std::uint16_t length; // Payload length in bytes
118 std::uint16_t flags; // PacketFlags bitfield
119 std::uint16_t reserved; // Must be 0
120 std::uint32_t sequence; // Per-session, monotonic sequence number
121 std::uint32_t sessionId; // Server-assigned session ID
122 };
123
124 ///
125 /// @brief CONNECT packet payload
126 ///
128 {
129 std::uint8_t nameLen;
130 char playerName[32];
131 std::uint32_t clientCaps;
132 };
133
134 ///
135 /// @brief CONNECT_ACCEPT packet payload
136 ///
138 {
139 std::uint32_t sessionId;
140 std::uint16_t tickRateHz;
141 std::uint16_t mtuPayloadBytes;
142 std::uint32_t serverCaps;
143 };
144
145 ///
146 /// @brief DISCONNECT packet payload
147 ///
149 {
150 std::uint16_t reasonCode; // DisconnectReason
151 };
152
153 ///
154 /// @brief Entity state for WORLD_STATE packet
155 ///
157 {
158 std::uint32_t id;
159 std::uint16_t type; // EntityType
160 float x, y;
161 float vx, vy;
162 std::uint8_t stateFlags;
163 };
164
165 ///
166 /// @brief WORLD_STATE packet payload
167 ///
169 {
170 std::uint32_t serverTick;
171 std::uint16_t entityCount;
172 std::vector<EntityState> entities;
173 };
174
175 ///
176 /// @brief PING/PONG packet payload
177 ///
179 {
180 std::uint32_t nonce;
181 std::uint32_t sendTimeMs;
182 };
183
184 ///
185 /// @brief ACK packet payload
186 ///
188 {
189 std::uint32_t cumulativeAck;
190 std::uint32_t ackBits; // 32-bit SACK window
191 };
192
193 ///
194 /// @brief ERROR packet payload
195 ///
197 {
198 std::uint16_t errorCode; // ErrorCode
199 std::uint16_t msgLen;
200 std::string description;
201 };
202
203 ///
204 /// @brief Fragmentation header (when FRAG flag is set)
205 ///
207 {
208 std::uint16_t fragId;
209 std::uint16_t fragIndex;
210 std::uint16_t fragCount;
211 };
212
213 ///
214 /// @brief Serialize events in ENTITY_EVENT format (TLV with entity_id)
215 /// Format per event: type(1) | entity_id(4, BE) | data_len(1) | data(data_len)
216 ///
217 inline std::vector<std::uint8_t> serializeEvents(const std::vector<EventRecord> &events)
218 {
219 std::vector<std::uint8_t> payload;
220 payload.reserve(64);
221
222 for (const auto &ev : events)
223 {
224 const std::uint8_t dataLen = static_cast<std::uint8_t>(ev.data.size());
225
226 // Event type (1 byte)
227 payload.push_back(static_cast<std::uint8_t>(ev.type));
228
229 // Entity ID (4 bytes, big endian)
230 payload.push_back(static_cast<std::uint8_t>((ev.entityId >> 24) & 0xFF));
231 payload.push_back(static_cast<std::uint8_t>((ev.entityId >> 16) & 0xFF));
232 payload.push_back(static_cast<std::uint8_t>((ev.entityId >> 8) & 0xFF));
233 payload.push_back(static_cast<std::uint8_t>(ev.entityId & 0xFF));
234
235 // Data length (1 byte)
236 payload.push_back(dataLen);
237
238 // Data (dataLen bytes)
239 payload.insert(payload.end(), ev.data.begin(), ev.data.end());
240
241 if (payload.size() > MAX_PAYLOAD)
242 {
243 throw std::runtime_error("Events payload exceeds MAX_PAYLOAD");
244 }
245 }
246 return payload;
247 }
248
249 ///
250 /// @brief Deserialize ENTITY_EVENT payload into event records
251 /// Format per event: type(1) | entity_id(4, BE) | data_len(1) | data(data_len)
252 ///
253 inline std::vector<EventRecord> deserializeEvents(const std::uint8_t *payload, const std::size_t length)
254 {
255 std::vector<EventRecord> events;
256 std::size_t offset = 0;
257
258 while (offset < length)
259 {
260 if (length - offset < 6) // type(1) + entity_id(4) + data_len(1)
261 {
262 throw std::runtime_error("Truncated event header in payload");
263 }
264
265 const EventType type = static_cast<EventType>(payload[offset]);
266 const std::uint32_t entityId = (static_cast<std::uint32_t>(payload[offset + 1]) << 24) |
267 (static_cast<std::uint32_t>(payload[offset + 2]) << 16) |
268 (static_cast<std::uint32_t>(payload[offset + 3]) << 8) |
269 static_cast<std::uint32_t>(payload[offset + 4]);
270 const std::uint8_t dataLen = payload[offset + 5];
271 offset += 6;
272
273 if (length - offset < dataLen)
274 {
275 throw std::runtime_error("Truncated event data in payload");
276 }
277
278 EventRecord rec{type, entityId, {}};
279 if (dataLen > 0)
280 {
281 rec.data.insert(rec.data.end(), payload + offset, payload + offset + dataLen);
282 }
283 events.emplace_back(std::move(rec));
284 offset += dataLen;
285 }
286 return events;
287 }
288
289 ///
290 /// @brief Serialize packet header (Big Endian as per RNP spec)
291 ///
292 inline std::vector<uint8_t> serializeHeader(const PacketHeader &header)
293 {
294 std::vector<uint8_t> buffer(16); // Fixed header size
295
296 buffer[0] = header.type;
297
298 // length (2 bytes, big endian)
299 buffer[1] = static_cast<uint8_t>((header.length >> 8) & 0xFF);
300 buffer[2] = static_cast<uint8_t>(header.length & 0xFF);
301
302 // flags (2 bytes, big endian)
303 buffer[3] = static_cast<uint8_t>((header.flags >> 8) & 0xFF);
304 buffer[4] = static_cast<uint8_t>(header.flags & 0xFF);
305
306 // reserved (2 bytes)
307 buffer[5] = static_cast<uint8_t>((header.reserved >> 8) & 0xFF);
308 buffer[6] = static_cast<uint8_t>(header.reserved & 0xFF);
309
310 // sequence (4 bytes, big endian)
311 buffer[7] = static_cast<uint8_t>((header.sequence >> 24) & 0xFF);
312 buffer[8] = static_cast<uint8_t>((header.sequence >> 16) & 0xFF);
313 buffer[9] = static_cast<uint8_t>((header.sequence >> 8) & 0xFF);
314 buffer[10] = static_cast<uint8_t>(header.sequence & 0xFF);
315
316 // sessionId (4 bytes, big endian)
317 buffer[11] = static_cast<uint8_t>((header.sessionId >> 24) & 0xFF);
318 buffer[12] = static_cast<uint8_t>((header.sessionId >> 16) & 0xFF);
319 buffer[13] = static_cast<uint8_t>((header.sessionId >> 8) & 0xFF);
320 buffer[14] = static_cast<uint8_t>(header.sessionId & 0xFF);
321
322 buffer[15] = 0; // Padding to 16 bytes
323
324 return buffer;
325 }
326
327 ///
328 /// @brief Serialize packet with header and optional payload (Big Endian)
329 ///
330 inline std::vector<uint8_t> serialize(const PacketHeader &header, const uint8_t *payload = nullptr)
331 {
332 std::vector<uint8_t> buffer = serializeHeader(header);
333
334 if (payload && header.length > 0)
335 {
336 buffer.insert(buffer.end(), payload, payload + header.length);
337 }
338
339 return buffer;
340 }
341
342 ///
343 /// @brief Deserialize packet header (Big Endian)
344 ///
345 inline PacketHeader deserializeHeader(const uint8_t *data, const std::size_t size)
346 {
347 if (size < 16)
348 {
349 throw std::runtime_error("Buffer too small for header");
350 }
351
352 PacketHeader header;
353
354 header.type = data[0];
355
356 // length (2 bytes, big endian)
357 header.length = (static_cast<std::uint16_t>(data[1]) << 8) | static_cast<std::uint16_t>(data[2]);
358
359 // flags (2 bytes, big endian)
360 header.flags = (static_cast<std::uint16_t>(data[3]) << 8) | static_cast<std::uint16_t>(data[4]);
361
362 // reserved (2 bytes)
363 header.reserved = (static_cast<std::uint16_t>(data[5]) << 8) | static_cast<std::uint16_t>(data[6]);
364
365 // sequence (4 bytes, big endian)
366 header.sequence = (static_cast<std::uint32_t>(data[7]) << 24) | (static_cast<std::uint32_t>(data[8]) << 16) |
367 (static_cast<std::uint32_t>(data[9]) << 8) | static_cast<std::uint32_t>(data[10]);
368
369 // sessionId (4 bytes, big endian)
370 header.sessionId = (static_cast<std::uint32_t>(data[11]) << 24) | (static_cast<std::uint32_t>(data[12]) << 16) |
371 (static_cast<std::uint32_t>(data[13]) << 8) | static_cast<std::uint32_t>(data[14]);
372
373 return header;
374 }
375
376} // namespace rnp
ErrorCode
Error codes.
Definition Protocol.hpp:67
EventType
Event types for ENTITY_EVENT packets.
Definition Protocol.hpp:78
std::vector< uint8_t > serializeHeader(const PacketHeader &header)
Serialize packet header (Big Endian as per RNP spec)
Definition Protocol.hpp:292
PacketFlags
Packet flags for reliability and fragmentation.
Definition Protocol.hpp:41
DisconnectReason
Disconnect reason codes.
Definition Protocol.hpp:53
EntityType
Entity types for world state.
Definition Protocol.hpp:92
PacketType
Packet types according to RNP specification.
Definition Protocol.hpp:24
std::vector< uint8_t > serialize(const PacketHeader &header, const uint8_t *payload=nullptr)
Serialize packet with header and optional payload (Big Endian)
Definition Protocol.hpp:330
PacketHeader deserializeHeader(const uint8_t *data, const std::size_t size)
Deserialize packet header (Big Endian)
Definition Protocol.hpp:345
std::vector< EventRecord > deserializeEvents(const std::uint8_t *payload, const std::size_t length)
Deserialize ENTITY_EVENT payload into event records Format per event: type(1) | entity_id(4,...
Definition Protocol.hpp:253
constexpr std::uint8_t PROTOCOL_VERSION
Definition Protocol.hpp:17
constexpr std::size_t MAX_PAYLOAD
Definition Protocol.hpp:18
std::vector< std::uint8_t > serializeEvents(const std::vector< EventRecord > &events)
Serialize events in ENTITY_EVENT format (TLV with entity_id) Format per event: type(1) | entity_id(4,...
Definition Protocol.hpp:217
Entity state for WORLD_STATE packet.
Definition Protocol.hpp:157
std::uint32_t id
Definition Protocol.hpp:158
std::uint16_t type
Definition Protocol.hpp:159
std::uint8_t stateFlags
Definition Protocol.hpp:162
Event record for ENTITY_EVENT packets (TLV format)
Definition Protocol.hpp:104
std::uint32_t entityId
Definition Protocol.hpp:106
std::vector< std::uint8_t > data
Definition Protocol.hpp:107
Fragmentation header (when FRAG flag is set)
Definition Protocol.hpp:207
std::uint16_t fragId
Definition Protocol.hpp:208
std::uint16_t fragIndex
Definition Protocol.hpp:209
std::uint16_t fragCount
Definition Protocol.hpp:210
ACK packet payload.
Definition Protocol.hpp:188
std::uint32_t ackBits
Definition Protocol.hpp:190
std::uint32_t cumulativeAck
Definition Protocol.hpp:189
CONNECT_ACCEPT packet payload.
Definition Protocol.hpp:138
std::uint32_t sessionId
Definition Protocol.hpp:139
std::uint16_t tickRateHz
Definition Protocol.hpp:140
std::uint16_t mtuPayloadBytes
Definition Protocol.hpp:141
std::uint32_t serverCaps
Definition Protocol.hpp:142
CONNECT packet payload.
Definition Protocol.hpp:128
std::uint32_t clientCaps
Definition Protocol.hpp:131
std::uint8_t nameLen
Definition Protocol.hpp:129
DISCONNECT packet payload.
Definition Protocol.hpp:149
std::uint16_t reasonCode
Definition Protocol.hpp:150
ERROR packet payload.
Definition Protocol.hpp:197
std::uint16_t msgLen
Definition Protocol.hpp:199
std::uint16_t errorCode
Definition Protocol.hpp:198
std::string description
Definition Protocol.hpp:200
Packet header according to RNP specification (Big Endian) Total size: 16 bytes.
Definition Protocol.hpp:115
std::uint32_t sessionId
Definition Protocol.hpp:121
std::uint8_t type
Definition Protocol.hpp:116
std::uint16_t length
Definition Protocol.hpp:117
std::uint32_t sequence
Definition Protocol.hpp:120
std::uint16_t flags
Definition Protocol.hpp:118
std::uint16_t reserved
Definition Protocol.hpp:119
PING/PONG packet payload.
Definition Protocol.hpp:179
std::uint32_t sendTimeMs
Definition Protocol.hpp:181
std::uint32_t nonce
Definition Protocol.hpp:180
WORLD_STATE packet payload.
Definition Protocol.hpp:169
std::uint16_t entityCount
Definition Protocol.hpp:171
std::uint32_t serverTick
Definition Protocol.hpp:170
std::vector< EntityState > entities
Definition Protocol.hpp:172