FastEngine 0.9.4
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_client.hpp
1/*
2 * Copyright 2025 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _FGE_C_CLIENT_HPP_INCLUDED
18#define _FGE_C_CLIENT_HPP_INCLUDED
19
20#include "FastEngine/fge_extern.hpp"
21#include "C_identity.hpp"
22#include "FastEngine/C_event.hpp"
23#include "FastEngine/C_propertyList.hpp"
24#include "FastEngine/network/C_protocol.hpp"
25#include <array>
26#include <atomic>
27#include <chrono>
28#include <deque>
29#include <memory>
30#include <mutex>
31
32#define FGE_NET_DEFAULT_LATENCY 20
33#define FGE_NET_CLIENT_TIMESTAMP_MODULO 65536
34#define FGE_NET_BAD_LATENCY std::numeric_limits<fge::net::Latency_ms>::max()
35#define FGE_NET_LATENCY_PLANNER_MEAN 6
36#define FGE_NET_DEFAULT_lOST_PACKET_THRESHOLD 15
37#define FGE_NET_STATUS_DEFAULT_TIMEOUT \
38 std::chrono::milliseconds \
39 { \
40 2000 \
41 }
42#define FGE_NET_STATUS_DEFAULT_CONNECTED_TIMEOUT \
43 std::chrono::milliseconds \
44 { \
45 6000 \
46 }
47#define FGE_NET_STATUS_DEFAULT_STATUS "none"
48
49#define FGE_NET_DEFAULT_RETURN_PACKET_RATE \
50 std::chrono::milliseconds \
51 { \
52 500 \
53 }
54
55namespace fge::net
56{
57
61
62using Timestamp = uint16_t;
63using FullTimestamp = uint64_t;
64using FullTimestampOffset = int64_t;
65using Latency_ms = uint16_t;
66
77class FGE_API OneWayLatencyPlanner
78{
79public:
80 OneWayLatencyPlanner() = default;
81
82 enum Stats : uint8_t
83 {
84 HAVE_EXTERNAL_TIMESTAMP = 1 << 0
85 };
86
92 void pack(TransmitPacketPtr& tPacket);
99 void unpack(ProtocolPacket* packet, Client& client);
100
109 [[nodiscard]] std::optional<FullTimestampOffset> getClockOffset() const;
115 [[nodiscard]] std::optional<Latency_ms> getLatency() const;
123 [[nodiscard]] std::optional<Latency_ms> getOtherSideLatency() const;
154 [[nodiscard]] std::optional<Latency_ms> getRoundTripTime() const;
155
156private:
157 std::optional<Latency_ms> g_latency;
158 std::optional<Latency_ms> g_otherSideLatency;
159
160 std::optional<FullTimestampOffset> g_meanClockOffset;
161 std::array<FullTimestampOffset, FGE_NET_LATENCY_PLANNER_MEAN> g_clockOffsets{};
162 std::size_t g_clockOffsetCount{0};
163
164 std::optional<Latency_ms> g_roundTripTime;
165
166 Timestamp g_externalStoredTimestamp{0};
167 std::underlying_type_t<Stats> g_syncStat{0};
168};
169
170class FGE_API ClientStatus
171{
172public:
173 enum class NetworkStatus
174 {
175 UNKNOWN,
176
177 ACKNOWLEDGED,
178 MTU_DISCOVERED,
179 CONNECTED,
180 AUTHENTICATED,
181
182 DISCONNECTED,
183 TIMEOUT,
184 };
185
186 ClientStatus() = default;
187 explicit ClientStatus(std::string_view status, NetworkStatus networkStatus = NetworkStatus::UNKNOWN);
188
189 [[nodiscard]] bool isInEncryptedState() const;
190 [[nodiscard]] bool isDisconnected() const;
191 [[nodiscard]] bool isConnected() const;
192 [[nodiscard]] bool isConnecting() const;
193 [[nodiscard]] bool isAuthenticated() const;
194
195 [[nodiscard]] std::string const& getStatus() const;
196 [[nodiscard]] NetworkStatus getNetworkStatus() const;
197 [[nodiscard]] std::chrono::milliseconds getTimeout() const;
198 [[nodiscard]] std::chrono::milliseconds getRemainingTimeout() const;
199
200 void set(std::string_view status, NetworkStatus networkStatus);
201 void setStatus(std::string_view status);
202 void setNetworkStatus(NetworkStatus networkStatus);
203
204 void setTimeout(std::chrono::milliseconds timeout);
205 void resetTimeout();
206 [[nodiscard]] bool isTimeout() const;
207
208private:
209 std::string g_status{FGE_NET_STATUS_DEFAULT_STATUS};
210 std::atomic<NetworkStatus> g_networkStatus{NetworkStatus::UNKNOWN};
211 std::chrono::milliseconds g_timeout{FGE_NET_STATUS_DEFAULT_TIMEOUT};
212 std::chrono::steady_clock::time_point g_currentTimeout{std::chrono::steady_clock::now()};
213};
214
219class FGE_API Client
220{
221public:
223 {
224 void* _ssl{nullptr};
225 void* _rbio{nullptr};
226 void* _wbio{nullptr};
227 };
228
229 Client();
230 ~Client();
237 explicit Client(Latency_ms CTOSLatency, Latency_ms STOCLatency);
238
271
294 std::optional<Timestamp> getCorrectorTimestamp() const;
306 std::optional<Latency_ms> getCorrectorLatency() const;
307
319 [[nodiscard]] std::chrono::milliseconds getLastPacketElapsedTime() const;
320 [[nodiscard]] Latency_ms getLastPacketLatency() const;
321
328 static Timestamp getTimestamp_ms(FullTimestamp fullTimestamp);
342 static Latency_ms computeLatency_ms(Timestamp const& sentTimestamp, Timestamp const& receivedTimestamp);
343
361 void pushPacket(TransmitPacketPtr pck);
362 void pushForcedFrontPacket(TransmitPacketPtr pck);
368 TransmitPacketPtr popPacket();
375
376 void disconnect(bool pushDisconnectPacket = true);
377
378 [[nodiscard]] ProtocolPacket::RealmType getCurrentRealm() const;
379 [[nodiscard]] std::chrono::milliseconds getLastRealmChangeElapsedTime() const;
380 void setCurrentRealm(ProtocolPacket::RealmType realm);
381 ProtocolPacket::RealmType advanceCurrentRealm();
382
383 [[nodiscard]] ProtocolPacket::CounterType getCurrentPacketCounter() const;
384 ProtocolPacket::CounterType advanceCurrentPacketCounter();
385 void setCurrentPacketCounter(ProtocolPacket::CounterType counter);
386
387 [[nodiscard]] ProtocolPacket::CounterType getClientPacketCounter() const;
388 ProtocolPacket::CounterType advanceClientPacketCounter();
389 void setClientPacketCounter(ProtocolPacket::CounterType counter);
390 void resetLastReorderedPacketCounter();
391 [[nodiscard]] ProtocolPacket::CounterType getLastReorderedPacketCounter() const;
392
393 [[nodiscard]] PacketReorderer& getPacketReorderer();
394 [[nodiscard]] PacketReorderer const& getPacketReorderer() const;
395
396 [[nodiscard]] DataLockPair<PacketCache*, std::recursive_mutex> getPacketCache();
397 [[nodiscard]] DataLockPair<PacketCache const*, std::recursive_mutex> getPacketCache() const;
398 void acknowledgeReception(ReceivedPacketPtr const& packet);
399 [[nodiscard]] std::vector<PacketCache::Label> const& getAcknowledgedList() const;
400 void clearAcknowledgedList();
401
402 void clearLostPacketCount();
403 uint32_t advanceLostPacketCount();
404 void setLostPacketThreshold(uint32_t threshold);
405 [[nodiscard]] uint32_t getLostPacketThreshold() const;
406 [[nodiscard]] uint32_t getLostPacketCount() const;
407
408 [[nodiscard]] ClientStatus const& getStatus() const;
409 [[nodiscard]] ClientStatus& getStatus();
410
411 [[nodiscard]] CryptInfo const& getCryptInfo() const;
412 [[nodiscard]] CryptInfo& getCryptInfo();
413
414 [[nodiscard]] uint16_t getMTU() const;
415 void setMTU(uint16_t mtu);
416
417 void setPacketReturnRate(std::chrono::milliseconds rate);
418 [[nodiscard]] std::chrono::milliseconds getPacketReturnRate() const;
419
420 CallbackHandler<Client&> _onThresholdLostPacket;
421
425 bool _mtuFinalizedFlag{false};
426
427private:
428 mutable std::optional<Timestamp> g_correctorTimestamp;
429 Latency_ms g_CTOSLatency_ms;
430 Latency_ms g_STOCLatency_ms;
431 std::chrono::steady_clock::time_point g_lastPacketTimePoint;
432
433 std::deque<TransmitPacketPtr> g_pendingTransmitPackets;
434 mutable std::recursive_mutex g_mutex;
435
436 std::chrono::steady_clock::time_point g_lastRealmChangeTimePoint;
437 ProtocolPacket::RealmType g_currentRealm{FGE_NET_DEFAULT_REALM};
438 ProtocolPacket::CounterType g_currentPacketCounter{0};
439 ProtocolPacket::CounterType g_lastReorderedPacketCounter{0};
440 ProtocolPacket::CounterType g_clientPacketCounter{0};
441
442 std::vector<PacketCache::Label> g_acknowledgedPackets;
443 PacketCache g_packetCache;
444 PacketReorderer g_packetReorderer;
445 uint32_t g_lostPacketCount{0};
446 uint32_t g_lostPacketThreshold{FGE_NET_DEFAULT_lOST_PACKET_THRESHOLD};
447
448 std::chrono::milliseconds g_returnPacketRate{FGE_NET_DEFAULT_RETURN_PACKET_RATE};
449
450 uint16_t g_mtu{0};
451
452 ClientStatus g_status;
453 CryptInfo g_cryptInfo;
454};
455
459
460} // namespace fge::net
461
462#endif // _FGE_C_CLIENT_HPP_INCLUDED
This class is used to handle callbacks in a safe way.
Definition C_callback.hpp:189
This class is a wrapper for SDL events.
Definition C_event.hpp:59
A class that map a string to a Property.
Definition C_propertyList.hpp:35
Definition C_client.hpp:171
Class that represent the identity of a client.
Definition C_client.hpp:220
void resetLastPacketTimePoint()
Reset the time point for limiting the packets sending frequency.
Latency_ms getPing_ms() const
Compute the ping.
Client(Latency_ms CTOSLatency, Latency_ms STOCLatency)
Constructor with default latencies.
OneWayLatencyPlanner _latencyPlanner
A latency planner that will help latency calculation.
Definition C_client.hpp:424
void pushPacket(TransmitPacketPtr pck)
Add a Packet to the queue.
void clearPackets()
Clear the packet queue.
std::chrono::milliseconds getLastPacketElapsedTime() const
Get the delta time between the last sent packet and the current time.
void setCorrectorTimestamp(Timestamp timestamp)
Set the corrector timestamp.
bool _mtuFinalizedFlag
A flag that indicate if the MTU has been finalized from the remote side.
Definition C_client.hpp:425
PropertyList _data
Some user-defined client properties.
Definition C_client.hpp:423
Event _event
Optional client-side event that can be synchronized with the server.
Definition C_client.hpp:422
std::optional< Timestamp > getCorrectorTimestamp() const
Get the corrector timestamp.
static Timestamp getTimestamp_ms()
Get a modulated timestamp of the current time.
Latency_ms getSTOCLatency_ms() const
Get the "Server To Client" latency.
std::optional< Latency_ms > getCorrectorLatency() const
Compute the corrector latency.
bool isPendingPacketsEmpty() const
Check if the packet queue is empty.
static FullTimestamp getFullTimestamp_ms()
Get a timestamp of the current time.
void setCTOSLatency_ms(Latency_ms latency)
Set the "Client To Server" latency.
TransmitPacketPtr popPacket()
Pop a packet from the queue.
Latency_ms getCTOSLatency_ms() const
Get the "Client To Server" latency.
void setSTOCLatency_ms(Latency_ms latency)
Set the "Server To Client" latency.
static Latency_ms computeLatency_ms(Timestamp const &sentTimestamp, Timestamp const &receivedTimestamp)
Compute the latency for the client->server / server->client with the given timestamps.
A helper class that measure latency between client/server.
Definition C_client.hpp:78
std::optional< FullTimestampOffset > getClockOffset() const
Retrieve the clock offset.
std::optional< Latency_ms > getRoundTripTime() const
Retrieve the RTT (Round Trip Time)
std::optional< Latency_ms > getLatency() const
Retrieve the latency.
void pack(TransmitPacketPtr &tPacket)
Pack the required data by the planner to the client/server.
void unpack(ProtocolPacket *packet, Client &client)
Unpack the data received by another client/server planner.
std::optional< Latency_ms > getOtherSideLatency() const
Retrieve the other side latency.
A packet reorderer.
Definition C_protocol.hpp:333
A special inheritance of Packet with a predefined communication protocol.
Definition C_protocol.hpp:85
int64_t FullTimestampOffset
An timestamp offset.
Definition C_client.hpp:64
uint64_t FullTimestamp
An timestamp represent current time in milliseconds.
Definition C_client.hpp:63
uint16_t Timestamp
An timestamp represent modulated current time in milliseconds.
Definition C_client.hpp:62
uint16_t Latency_ms
An latency represent the latency of the client->server / server->client connection.
Definition C_client.hpp:65
Definition C_client.hpp:223