17#ifndef _FGE_C_PROTOCOL_HPP_INCLUDED
18#define _FGE_C_PROTOCOL_HPP_INCLUDED
20#include "FastEngine/fge_extern.hpp"
21#include "FastEngine/network/C_identity.hpp"
22#include "FastEngine/network/C_packet.hpp"
28#define FGE_NET_HEADER_DO_NOT_DISCARD_FLAG 0x8000
29#define FGE_NET_HEADER_DO_NOT_REORDER_FLAG 0x4000
30#define FGE_NET_HEADER_COMPRESSED_FLAG 0x2000
31#define FGE_NET_HEADER_DO_NOT_FRAGMENT_FLAG 0x1000
32#define FGE_NET_HEADER_FLAGS_MASK 0xF000
33#define FGE_NET_HEADER_FLAGS_COUNT 4
35#define FGE_NET_ID_MAX ((~FGE_NET_HEADER_FLAGS_MASK) - 1)
37#define FGE_NET_INTERNAL_ID_MAX 1024
38#define FGE_NET_INTERNAL_ID_START 1
40#define FGE_NET_CUSTOM_ID_MAX FGE_NET_ID_MAX
41#define FGE_NET_CUSTOM_ID_START (FGE_NET_INTERNAL_ID_MAX + 1)
43#define FGE_NET_BAD_ID 0
45#define FGE_NET_PACKET_CACHE_DELAY_FACTOR 1.2f
46#define FGE_NET_PACKET_CACHE_MAX 100
47#define FGE_NET_PACKET_CACHE_MIN_LATENCY_MS 10
49#define FGE_NET_DEFAULT_REALM 0
50#define FGE_NET_DEFAULT_PACKET_REORDERER_CACHE_SIZE 5
51#define FGE_NET_PACKET_REORDERER_CACHE_COMPUTE(_clientReturnRate, _serverTickRate) \
52 (((_clientReturnRate) * FGE_NET_PACKET_CACHE_DELAY_FACTOR / (_serverTickRate) + 1) * 2)
54#define FGE_NET_HANDSHAKE_STRING "FGE:HANDSHAKE:AZCgMVg4d4Sl2xYvZcqXqljIOqSrKX6H"
84class FGE_API ProtocolPacket :
public Packet,
public std::enable_shared_from_this<ProtocolPacket>
100 constexpr explicit Option(
Options option, std::size_t argument = 0) :
109 using IdType = uint16_t;
110 using RealmType = uint16_t;
111 using CounterType = uint16_t;
117 CounterType _counter;
118 CounterType _lastCounter;
121 constexpr static std::size_t HeaderSize =
sizeof(IdType) +
sizeof(RealmType) +
sizeof(CounterType) * 2;
122 constexpr static std::size_t IdPosition = 0;
123 constexpr static std::size_t RealmPosition =
sizeof(IdType);
124 constexpr static std::size_t CounterPosition =
sizeof(IdType) +
sizeof(RealmType);
125 constexpr static std::size_t LastCounterPosition =
sizeof(IdType) +
sizeof(RealmType) +
sizeof(CounterType);
127 inline ProtocolPacket(Packet
const& pck,
129 std::size_t fluxIndex = 0,
130 std::size_t fluxLifetime = 0);
131 inline ProtocolPacket(Packet&& pck,
Identity const&
id, std::size_t fluxIndex = 0, std::size_t fluxLifetime = 0);
132 inline ProtocolPacket(IdType header,
133 RealmType realmId = FGE_NET_DEFAULT_REALM,
134 CounterType countId = 0,
135 CounterType lastCountId = 0);
137 inline ProtocolPacket(Packet
const& r);
138 inline ProtocolPacket(Packet&& r)
noexcept;
140 inline ProtocolPacket(ProtocolPacket
const& r);
141 inline ProtocolPacket(ProtocolPacket&& r)
noexcept;
143 inline ~ProtocolPacket()
override =
default;
145 [[nodiscard]]
inline Packet& packet() noexcept {
return *
this; }
146 [[nodiscard]]
inline Packet const& packet() const noexcept {
return *
this; }
148 [[nodiscard]]
inline bool haveCorrectHeader()
const;
149 [[nodiscard]]
inline bool haveCorrectHeaderSize()
const;
150 [[nodiscard]]
inline std::optional<IdType> retrieveHeaderId()
const;
151 [[nodiscard]]
inline std::optional<IdType> retrieveFlags()
const;
152 [[nodiscard]]
inline std::optional<IdType> retrieveFullHeaderId()
const;
153 [[nodiscard]]
inline std::optional<RealmType> retrieveRealm()
const;
154 [[nodiscard]]
inline std::optional<CounterType> retrieveCounter()
const;
155 [[nodiscard]]
inline std::optional<CounterType> retrieveLastCounter()
const;
156 [[nodiscard]]
inline std::optional<Header> retrieveHeader()
const;
158 [[nodiscard]]
inline bool isFragmented()
const;
160 inline ProtocolPacket& setHeader(Header
const& header);
161 inline ProtocolPacket& setHeaderId(IdType
id);
163 inline ProtocolPacket& setFlags(IdType flags);
164 inline ProtocolPacket& addFlags(IdType flags);
165 inline ProtocolPacket& removeFlags(IdType flags);
166 [[nodiscard]]
inline bool checkFlags(IdType flags)
const;
167 inline ProtocolPacket& doNotDiscard();
168 inline ProtocolPacket& doNotReorder();
169 inline ProtocolPacket& doNotFragment();
171 inline ProtocolPacket& setRealm(RealmType realm);
172 inline ProtocolPacket& setCounter(CounterType counter);
173 inline ProtocolPacket& setLastReorderedPacketCounter(CounterType counter);
175 inline void setTimestamp(Timestamp timestamp);
176 [[nodiscard]]
inline Timestamp getTimeStamp()
const;
177 [[nodiscard]]
inline Identity
const& getIdentity()
const;
179 [[nodiscard]]
inline std::vector<Option>
const& options()
const;
180 [[nodiscard]]
inline std::vector<Option>& options();
182 [[nodiscard]]
bool compress(
Compressor& compressor);
183 [[nodiscard]]
bool decompress(
Compressor& compressor);
185 inline void markForEncryption();
186 inline void unmarkForEncryption();
187 [[nodiscard]]
inline bool isMarkedForEncryption()
const;
189 inline void markAsLocallyReordered();
190 inline void unmarkAsLocallyReordered();
191 [[nodiscard]]
inline bool isMarkedAsLocallyReordered()
const;
193 inline void markAsCached();
194 inline void unmarkAsCached();
195 [[nodiscard]]
inline bool isMarkedAsCached()
const;
224 inline std::size_t getFluxIndex()
const;
225 inline std::size_t bumpFluxIndex(std::size_t fluxSize);
227 [[nodiscard]] std::vector<std::unique_ptr<ProtocolPacket>> fragment(uint16_t mtu)
const;
233 std::size_t g_fluxIndex{0};
234 std::size_t g_fluxLifetime{0};
236 bool g_markedForEncryption{
false};
237 bool g_markedAsLocallyReordered{
false};
238 bool g_markedAsCached{
false};
240 std::vector<Option> g_options;
243using TransmitPacketPtr = std::unique_ptr<ProtocolPacket>;
244using ReceivedPacketPtr = std::unique_ptr<ProtocolPacket>;
246template<
class... Args>
247[[nodiscard]]
inline TransmitPacketPtr CreatePacket(Args&&... args)
249 return std::make_unique<ProtocolPacket>(std::forward<Args>(args)...);
251[[nodiscard]]
inline TransmitPacketPtr CreatePacket()
253 return std::make_unique<ProtocolPacket>(FGE_NET_BAD_ID);
256enum InternalProtocolIds : ProtocolPacket::IdType
258 NET_INTERNAL_ID_MTU_ASK = FGE_NET_INTERNAL_ID_START,
259 NET_INTERNAL_ID_MTU_ASK_RESPONSE,
260 NET_INTERNAL_ID_MTU_TEST,
261 NET_INTERNAL_ID_MTU_TEST_RESPONSE,
262 NET_INTERNAL_ID_MTU_FINAL,
264 NET_INTERNAL_ID_FRAGMENTED_PACKET,
266 NET_INTERNAL_ID_FGE_HANDSHAKE,
267 NET_INTERNAL_ID_CRYPT_HANDSHAKE,
269 NET_INTERNAL_ID_RETURN_PACKET,
271 NET_INTERNAL_ID_DISCONNECT
274[[nodiscard]]
inline TransmitPacketPtr CreateDisconnectPacket()
276 auto packet = std::make_unique<ProtocolPacket>(NET_INTERNAL_ID_DISCONNECT);
277 packet->doNotDiscard().doNotReorder();
283 uint8_t _fragmentTotal;
286class PacketDefragmentation
289 PacketDefragmentation() =
default;
290 ~PacketDefragmentation() =
default;
301 ProtocolPacket::RealmType _id;
306 [[nodiscard]]
Result process(ReceivedPacketPtr&& packet);
307 [[nodiscard]] ReceivedPacketPtr retrieve(ProtocolPacket::RealmType
id,
Identity const& client);
312 Data(ProtocolPacket::RealmType
id, ProtocolPacket::CounterType total) :
318 ProtocolPacket::RealmType _id;
319 decltype(InternalFragmentedPacketData::_fragmentTotal) _count;
320 std::vector<ReceivedPacketPtr> _fragments;
322 std::vector<Data> g_data;
332class FGE_API PacketReorderer
340 WAITING_NEXT_COUNTER,
344 PacketReorderer() =
default;
345 PacketReorderer(PacketReorderer
const& r) =
delete;
346 PacketReorderer(PacketReorderer&& r)
noexcept =
default;
347 ~PacketReorderer() =
default;
349 PacketReorderer& operator=(PacketReorderer
const& r) =
delete;
350 PacketReorderer& operator=(PacketReorderer&& r)
noexcept =
default;
354 void push(ReceivedPacketPtr&& packet);
355 [[nodiscard]]
static Stats checkStat(ReceivedPacketPtr
const& packet,
356 ProtocolPacket::CounterType currentCounter,
357 ProtocolPacket::RealmType currentRealm);
358 [[nodiscard]]
bool isForced()
const;
359 [[nodiscard]] std::optional<Stats> checkStat(ProtocolPacket::CounterType currentCounter,
360 ProtocolPacket::RealmType currentRealm)
const;
361 [[nodiscard]] ReceivedPacketPtr pop();
363 [[nodiscard]]
bool isEmpty()
const;
365 void setMaximumSize(std::size_t size);
366 [[nodiscard]] std::size_t getMaximumSize()
const;
371 explicit Data(ReceivedPacketPtr&& packet);
372 Data(Data
const& r) =
delete;
373 Data(Data&& r)
noexcept;
376 Data& operator=(Data
const& r) =
delete;
377 Data& operator=(Data&& r)
noexcept;
379 [[nodiscard]] Stats checkStat(ProtocolPacket::CounterType currentCounter,
380 ProtocolPacket::RealmType currentRealm)
const;
382 ReceivedPacketPtr _packet;
383 ProtocolPacket::CounterType _counter;
384 ProtocolPacket::CounterType _lastCounter;
385 ProtocolPacket::RealmType _realm;
389 [[nodiscard]]
constexpr bool operator()(Data
const& l, Data
const& r)
const
391 if (l._realm == r._realm)
393 return l._counter > r._counter;
395 return l._realm > r._realm;
400 std::priority_queue<Data, std::vector<Data>,
Data::Compare> g_cache;
401 std::size_t g_cacheSize{FGE_NET_DEFAULT_PACKET_REORDERER_CACHE_SIZE};
402 bool g_forceRetrieve{
false};
405class FGE_API PacketCache
410 constexpr Label() =
default;
411 constexpr Label(ProtocolPacket::CounterType counter, ProtocolPacket::RealmType realm) :
416 ProtocolPacket::CounterType _counter{0};
417 ProtocolPacket::RealmType _realm{0};
419 [[nodiscard]]
constexpr bool operator==(Label
const& r)
const
421 return this->_counter == r._counter && this->_realm == r._realm;
425 PacketCache() =
default;
426 PacketCache(PacketCache
const& r) =
delete;
427 PacketCache(PacketCache&& r)
noexcept =
default;
428 ~PacketCache() =
default;
430 PacketCache& operator=(PacketCache
const& r) =
delete;
431 PacketCache& operator=(PacketCache&& r)
noexcept =
default;
434 [[nodiscard]]
bool isEmpty()
const;
437 void push(TransmitPacketPtr
const& packet);
440 void acknowledgeReception(std::span<Label> labels);
443 [[nodiscard]]
bool check(std::chrono::steady_clock::time_point
const& timePoint,
444 std::chrono::milliseconds clientDelay);
445 [[nodiscard]] TransmitPacketPtr pop();
451 explicit Data(TransmitPacketPtr&& packet);
453 Data& operator=(TransmitPacketPtr&& packet);
455 TransmitPacketPtr _packet;
457 std::chrono::steady_clock::time_point _time{};
461 std::vector<Data> g_cache{FGE_NET_PACKET_CACHE_MAX};
462 std::size_t g_start{0};
463 std::size_t g_end{0};
468#include "C_protocol.inl"
Definition C_compressor.hpp:29
Class that represent the identity of a client.
Definition C_client.hpp:220
Definition C_packet.hpp:52
void applyOptions()
Apply packet options to the packet.
bool checkFluxLifetime(std::size_t fluxSize)
Check if the flux lifetime is reached.
Definition C_protocol.inl:341
void applyOptions(Client const &client)
Apply packet options to the packet.
Options
Options to pass to the network thread when sending a packet.
Definition C_protocol.hpp:92
@ UPDATE_FULL_TIMESTAMP
The full timestamp of the packet will be updated when sending.
Definition C_protocol.hpp:94
@ UPDATE_CORRECTION_LATENCY
The latency of the packet will be updated with the corrector latency from the Client.
Definition C_protocol.hpp:95
@ UPDATE_TIMESTAMP
The timestamp of the packet will be updated when sending.
Definition C_protocol.hpp:93
uint16_t Timestamp
An timestamp represent modulated current time in milliseconds.
Definition C_client.hpp:62
A class to represent a client or server identity with an IP address and a port.
Definition C_identity.hpp:31
Definition C_protocol.hpp:282
Definition C_protocol.hpp:409
Definition C_protocol.hpp:299
Definition C_protocol.hpp:388
Options _option
The option to send the packet with.
Definition C_protocol.hpp:105
std::size_t _argument
The option argument.
Definition C_protocol.hpp:106