Skip to content

Commit aeed3ef

Browse files
authored
Network stability pass (#36)
* Fix and cleanup on the counter aspects of client * add process() options, add FGE_ENABLE_PACKET_DEBUG_VERBOSE, fixing * WIP: change PacketCache to pause transmission when packet can't be sent - Not an circular buffer anymore - Add a try count to packets inside the cache - Currently there is now a problem with the client reorder WIP - Client: add isReadyToAcceptMorePendingPackets() it should now be used instead of isPendingPacketsEmpty() * refactoring the PacketReorderer, fix network issues, remove duplicate client context - Also cleanup debug printing - WIP There is still a issue where not acknowledged packet is not correctly re-sent in certain situation * Add FGE_SOCKET_MAX_MTU of 16384 because we can't go further with DTLS (openssl) for now - This fix the transmission for big packets - Also add more debug printing * made Packet class copy/move assignable * remove ERR_NONE as this class is meant to be used with std::optional
1 parent 80caf8a commit aeed3ef

21 files changed

Lines changed: 667 additions & 442 deletions

File tree

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ option(FGE_BUILD_TESTS "Build tests" ON)
101101

102102
option(FGE_ENABLE_SERVER_NETWORK_RANDOM_LOST "enable/disable random packet lost for server" OFF)
103103
option(FGE_ENABLE_CLIENT_NETWORK_RANDOM_LOST "enable/disable random packet lost for client" OFF)
104+
option(FGE_ENABLE_PACKET_DEBUG_VERBOSE "enable/disable verbose packet debug printing" OFF)
104105

105106
#Check if Doxygen is installed
106107
if (FGE_BUILD_DOC)
@@ -184,6 +185,14 @@ if (${FGE_ENABLE_CLIENT_NETWORK_RANDOM_LOST})
184185
endif()
185186
endif()
186187

188+
if (${FGE_ENABLE_PACKET_DEBUG_VERBOSE})
189+
target_compile_definitions(${FGE_LIB_NAME} PUBLIC FGE_ENABLE_PACKET_DEBUG_VERBOSE)
190+
target_compile_definitions(${FGE_SERVER_LIB_NAME} PUBLIC FGE_ENABLE_PACKET_DEBUG_VERBOSE)
191+
if (NOT ${FGE_DEBUG})
192+
message(WARNING "FGE_ENABLE_PACKET_DEBUG_VERBOSE is enabled, but FGE_DEBUG is disabled")
193+
endif()
194+
endif()
195+
187196
target_compile_definitions(${FGE_SERVER_LIB_NAME} PUBLIC FGE_DEF_SERVER)
188197

189198
#Includes path

examples/clientServerLifeSimulator_004/client/main.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
275275
std::cout << "connection ok" << std::endl;
276276

277277
server.enableReturnPacket(true);
278-
server.getClientContext()._reorderer.setMaximumSize(FGE_NET_PACKET_REORDERER_CACHE_COMPUTE(
278+
server._client._context._reorderer.setMaximumSize(FGE_NET_PACKET_REORDERER_CACHE_COMPUTE(
279279
FGE_NET_DEFAULT_RETURN_PACKET_RATE.count(), LIFESIM_SERVER_TICK));
280280

281281
auto transmissionPacket = fge::net::CreatePacket(ls::LS_PROTOCOL_C_PLEASE_CONNECT_ME);
@@ -369,9 +369,15 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
369369
<< '\n'
370370
<< "Update count: " << mainScene->getUpdateCount() << '\n'
371371
<< "Lost packets: " << server._client.getLostPacketCount() << '\n'
372-
<< "Realm: " << static_cast<unsigned int>(server._client.getCurrentRealm())
373-
<< ", CurrentCounter: " << server._client.getCurrentPacketCounter()
374-
<< ", ClientCounter: " << server._client.getClientPacketCounter();
372+
<< "Realm: " << static_cast<unsigned int>(server._client.getCurrentRealm()) << '\n'
373+
<< "Peer counter: "
374+
<< server._client.getPacketCounter(fge::net::Client::Targets::PEER)
375+
<< ", Peer reorderedCounter: "
376+
<< server._client.getReorderedPacketCounter(fge::net::Client::Targets::PEER) << '\n'
377+
<< "Host counter: "
378+
<< server._client.getPacketCounter(fge::net::Client::Targets::HOST)
379+
<< ", Host reorderedCounter: "
380+
<< server._client.getReorderedPacketCounter(fge::net::Client::Targets::HOST);
375381

376382
latencyText->setString(tiny_utf8::string(latencyTextStream.str()));
377383

examples/clientServerLifeSimulator_004/server/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
343343
}
344344

345345
//Make sure that the client is not busy with another packet
346-
if (!it->second->isPendingPacketsEmpty())
346+
if (!it->second->isReadyToAcceptMorePendingPackets())
347347
{
348348
continue;
349349
}

includes/FastEngine/manager/network_manager.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class ChainedArguments
7474
{
7575
public:
7676
constexpr ChainedArguments(Packet const& pck, TValue* existingValue = nullptr);
77-
constexpr ChainedArguments(Packet const& pck, Error&& err, TValue* existingValue = nullptr);
77+
constexpr ChainedArguments(Packet const& pck, std::optional<Error>&& err, TValue* existingValue = nullptr);
7878
constexpr ChainedArguments(ChainedArguments const& r) = default;
7979
constexpr ChainedArguments(ChainedArguments&& r) noexcept = default;
8080

@@ -245,7 +245,7 @@ class ChainedArguments
245245

246246
Packet const* g_pck;
247247
Value g_value;
248-
Error g_error;
248+
std::optional<Error> g_error;
249249
};
250250

251251
/**

includes/FastEngine/manager/network_manager.inl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ template<class TValue>
2323
constexpr ChainedArguments<TValue>::ChainedArguments(Packet const& pck, TValue* existingValue) :
2424
g_pck(&pck),
2525
g_value(existingValue == nullptr ? Value{std::in_place_type<TValue>} : Value{existingValue}),
26-
g_error(pck.isValid() ? Error{}
27-
: Error{Error::Types::ERR_ALREADY_INVALID, pck.getReadPos(), "already invalid packet",
28-
__func__})
26+
g_error(pck.isValid() ? std::nullopt
27+
: std::optional{Error{Error::Types::ERR_ALREADY_INVALID, pck.getReadPos(),
28+
"already invalid packet", __func__}})
2929
{}
3030
template<class TValue>
31-
constexpr ChainedArguments<TValue>::ChainedArguments(Packet const& pck, Error&& err, TValue* existingValue) :
31+
constexpr ChainedArguments<TValue>::ChainedArguments(Packet const& pck,
32+
std::optional<Error>&& err,
33+
TValue* existingValue) :
3234
g_pck(&pck),
3335
g_value(existingValue == nullptr ? Value{std::in_place_type<TValue>} : Value{existingValue}),
3436
g_error(std::move(err))

includes/FastEngine/network/C_client.hpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ class FGE_API Client
240240
public:
241241
Client();
242242
~Client();
243+
244+
enum class Targets
245+
{
246+
PEER,
247+
HOST
248+
};
249+
243250
/**
244251
* \brief Constructor with default latencies
245252
*
@@ -372,6 +379,7 @@ class FGE_API Client
372379
*/
373380
void pushPacket(TransmitPacketPtr pck);
374381
void pushForcedFrontPacket(TransmitPacketPtr pck);
382+
[[nodiscard]] bool isReadyToAcceptMorePendingPackets() const;
375383
/**
376384
* \brief Pop a packet from the queue
377385
*
@@ -384,6 +392,7 @@ class FGE_API Client
384392
* \return True if the queue is empty, false otherwise
385393
*/
386394
bool isPendingPacketsEmpty() const;
395+
void allowMorePendingPackets(bool allow);
387396

388397
void disconnect(bool pushDisconnectPacket = true);
389398

@@ -392,15 +401,15 @@ class FGE_API Client
392401
void setCurrentRealm(ProtocolPacket::RealmType realm);
393402
ProtocolPacket::RealmType advanceCurrentRealm();
394403

395-
[[nodiscard]] ProtocolPacket::CounterType getCurrentPacketCounter() const;
396-
ProtocolPacket::CounterType advanceCurrentPacketCounter();
397-
void setCurrentPacketCounter(ProtocolPacket::CounterType counter);
404+
[[nodiscard]] ProtocolPacket::CounterType getPacketCounter(Targets target) const;
405+
ProtocolPacket::CounterType advancePacketCounter(Targets target);
406+
void setPacketCounter(Targets target, ProtocolPacket::CounterType count);
398407

399-
[[nodiscard]] ProtocolPacket::CounterType getClientPacketCounter() const;
400-
ProtocolPacket::CounterType advanceClientPacketCounter();
401-
void setClientPacketCounter(ProtocolPacket::CounterType counter);
402-
void resetLastReorderedPacketCounter();
403-
[[nodiscard]] ProtocolPacket::CounterType getLastReorderedPacketCounter() const;
408+
[[nodiscard]] ProtocolPacket::CounterType getReorderedPacketCounter(Targets target) const;
409+
ProtocolPacket::CounterType advanceReorderedPacketCounter(Targets target);
410+
void setReorderedPacketCounter(Targets target, ProtocolPacket::CounterType count);
411+
412+
void resetAllCounters();
404413

405414
void acknowledgeReception(ReceivedPacketPtr const& packet);
406415
[[nodiscard]] std::unordered_set<PacketCache::Label, PacketCache::Label::Hash> const& getAcknowledgedList() const;
@@ -443,9 +452,11 @@ class FGE_API Client
443452

444453
std::chrono::steady_clock::time_point g_lastRealmChangeTimePoint;
445454
ProtocolPacket::RealmType g_currentRealm{FGE_NET_DEFAULT_REALM};
446-
ProtocolPacket::CounterType g_currentPacketCounter{0};
447-
ProtocolPacket::CounterType g_lastReorderedPacketCounter{0};
448-
ProtocolPacket::CounterType g_clientPacketCounter{0};
455+
456+
ProtocolPacket::CounterType g_hostPacketCounter{0};
457+
ProtocolPacket::CounterType g_hostReorderedPacketCounter{0};
458+
ProtocolPacket::CounterType g_peerPacketCounter{0};
459+
ProtocolPacket::CounterType g_peerReorderedPacketCounter{0};
449460

450461
std::unordered_set<PacketCache::Label, PacketCache::Label::Hash> g_acknowledgedPackets;
451462
uint32_t g_lostPacketCount{0};
@@ -457,6 +468,8 @@ class FGE_API Client
457468

458469
ClientStatus g_status;
459470
CryptInfo g_cryptInfo;
471+
472+
bool g_allowMorePackets{true};
460473
};
461474

462475
/**

includes/FastEngine/network/C_error.hpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ struct FGE_API Error
2828
{
2929
enum class Types
3030
{
31-
ERR_NONE,
3231
ERR_ALREADY_INVALID,
3332
ERR_EXTRACT,
3433
ERR_RULE,
@@ -38,7 +37,22 @@ struct FGE_API Error
3837
ERR_SCENE_OLD_PACKET
3938
};
4039

41-
Types _type{Types::ERR_NONE};
40+
constexpr Error(Types type) :
41+
_type(type)
42+
{}
43+
constexpr Error(Types type, std::size_t readPos, char const* error, char const* function) :
44+
_type(type),
45+
_readPos(readPos),
46+
_error(error),
47+
_function(function)
48+
{}
49+
constexpr Error(Types type, char const* error, char const* function) :
50+
_type(type),
51+
_error(error),
52+
_function(function)
53+
{}
54+
55+
Types _type;
4256
std::size_t _readPos{0};
4357
char const* _error{nullptr};
4458
char const* _function{nullptr};

includes/FastEngine/network/C_packet.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ class FGE_API Packet
5353
public:
5454
Packet();
5555
Packet(Packet&& pck) noexcept;
56-
Packet(Packet& pck) = default;
5756
Packet(Packet const& pck) = default;
5857
explicit Packet(std::size_t reserveSize);
5958
virtual ~Packet() = default;
6059

60+
Packet& operator=(Packet const& pck) = default;
61+
Packet& operator=(Packet&& pck) noexcept;
62+
6163
void clear();
6264
void flush();
6365
void reserve(std::size_t reserveSize);

includes/FastEngine/network/C_protocol.hpp

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,17 @@
4242

4343
#define FGE_NET_BAD_ID 0
4444

45-
#define FGE_NET_PACKET_CACHE_DELAY_FACTOR 1.2f
45+
#define FGE_NET_PACKET_CACHE_DELAY_FACTOR 2.2f
4646
#define FGE_NET_PACKET_CACHE_MAX 100
4747
#define FGE_NET_PACKET_CACHE_MIN_LATENCY_MS 10
4848

4949
#define FGE_NET_DEFAULT_REALM 0
5050
#define FGE_NET_DEFAULT_PACKET_REORDERER_CACHE_SIZE 5
5151
#define FGE_NET_PACKET_REORDERER_CACHE_COMPUTE(_clientReturnRate, _serverTickRate) \
52-
(((_clientReturnRate) * FGE_NET_PACKET_CACHE_DELAY_FACTOR / (_serverTickRate) + 1) * 2)
52+
((static_cast<unsigned>(static_cast<float>(_clientReturnRate) * FGE_NET_PACKET_CACHE_DELAY_FACTOR / \
53+
static_cast<float>(_serverTickRate)) + \
54+
1) * \
55+
2)
5356

5457
#define FGE_NET_HANDSHAKE_STRING "FGE:HANDSHAKE:AZCgMVg4d4Sl2xYvZcqXqljIOqSrKX6H"
5558

@@ -62,7 +65,7 @@ class Compressor;
6265

6366
namespace fge::net
6467
{
65-
68+
class NetFluxUdp;
6669
class Client;
6770

6871
using Timestamp = uint16_t;
@@ -122,7 +125,7 @@ class FGE_API ProtocolPacket : public Packet, public std::enable_shared_from_thi
122125
constexpr static std::size_t IdPosition = 0;
123126
constexpr static std::size_t RealmPosition = sizeof(IdType);
124127
constexpr static std::size_t CounterPosition = sizeof(IdType) + sizeof(RealmType);
125-
constexpr static std::size_t LastCounterPosition = sizeof(IdType) + sizeof(RealmType) + sizeof(CounterType);
128+
constexpr static std::size_t ReorderedCounterPosition = sizeof(IdType) + sizeof(RealmType) + sizeof(CounterType);
126129

127130
inline ProtocolPacket(Packet const& pck,
128131
Identity const& id,
@@ -152,7 +155,7 @@ class FGE_API ProtocolPacket : public Packet, public std::enable_shared_from_thi
152155
[[nodiscard]] inline std::optional<IdType> retrieveFullHeaderId() const;
153156
[[nodiscard]] inline std::optional<RealmType> retrieveRealm() const;
154157
[[nodiscard]] inline std::optional<CounterType> retrieveCounter() const;
155-
[[nodiscard]] inline std::optional<CounterType> retrieveLastCounter() const;
158+
[[nodiscard]] inline std::optional<CounterType> retrieveReorderedCounter() const;
156159
[[nodiscard]] inline std::optional<Header> retrieveHeader() const;
157160

158161
[[nodiscard]] inline bool isFragmented() const;
@@ -170,7 +173,7 @@ class FGE_API ProtocolPacket : public Packet, public std::enable_shared_from_thi
170173

171174
inline ProtocolPacket& setRealm(RealmType realm);
172175
inline ProtocolPacket& setCounter(CounterType counter);
173-
inline ProtocolPacket& setLastReorderedPacketCounter(CounterType counter);
176+
inline ProtocolPacket& setReorderedCounter(CounterType counter);
174177

175178
inline void setTimestamp(Timestamp timestamp);
176179
[[nodiscard]] inline Timestamp getTimeStamp() const;
@@ -356,16 +359,26 @@ class FGE_API PacketReorderer
356359

357360
void clear();
358361

362+
bool process(Client& client, NetFluxUdp& flux, bool ignoreRealm);
363+
359364
void push(ReceivedPacketPtr&& packet);
365+
366+
[[nodiscard]] static Stats checkStat(ReceivedPacketPtr const& packet, Client const& client, bool ignoreRealm);
360367
[[nodiscard]] static Stats checkStat(ReceivedPacketPtr const& packet,
361-
ProtocolPacket::CounterType currentCounter,
362-
ProtocolPacket::RealmType currentRealm);
363-
[[nodiscard]] bool isForced() const;
364-
[[nodiscard]] std::optional<Stats> checkStat(ProtocolPacket::CounterType currentCounter,
365-
ProtocolPacket::RealmType currentRealm) const;
368+
ProtocolPacket::CounterType peerCounter,
369+
ProtocolPacket::CounterType peerReorderedCounter,
370+
ProtocolPacket::RealmType peerRealm,
371+
bool ignoreRealm);
372+
[[nodiscard]] std::optional<Stats> checkStat(Client const& client, bool ignoreRealm) const;
373+
[[nodiscard]] std::optional<Stats> checkStat(ProtocolPacket::CounterType peerCounter,
374+
ProtocolPacket::CounterType peerReorderedCounter,
375+
ProtocolPacket::RealmType peerRealm,
376+
bool ignoreRealm) const;
377+
366378
[[nodiscard]] ReceivedPacketPtr pop();
367379

368380
[[nodiscard]] bool isEmpty() const;
381+
[[nodiscard]] bool isForced() const;
369382

370383
void setMaximumSize(std::size_t size);
371384
[[nodiscard]] std::size_t getMaximumSize() const;
@@ -381,12 +394,14 @@ class FGE_API PacketReorderer
381394
Data& operator=(Data const& r) = delete;
382395
Data& operator=(Data&& r) noexcept;
383396

384-
[[nodiscard]] Stats checkStat(ProtocolPacket::CounterType currentCounter,
385-
ProtocolPacket::RealmType currentRealm) const;
397+
[[nodiscard]] Stats checkStat(ProtocolPacket::CounterType peerCounter,
398+
ProtocolPacket::CounterType peerReorderedCounter,
399+
ProtocolPacket::RealmType peerRealm,
400+
bool ignoreRealm) const;
386401

387402
ReceivedPacketPtr _packet;
388403
ProtocolPacket::CounterType _counter;
389-
ProtocolPacket::CounterType _lastCounter;
404+
ProtocolPacket::CounterType _reorderedCounter;
390405
ProtocolPacket::RealmType _realm;
391406

392407
struct Compare
@@ -395,7 +410,7 @@ class FGE_API PacketReorderer
395410
{
396411
if (l._realm == r._realm)
397412
{
398-
return l._counter > r._counter;
413+
return l._reorderedCounter > r._reorderedCounter;
399414
}
400415
return l._realm > r._realm;
401416
}
@@ -438,7 +453,7 @@ class FGE_API PacketCache
438453
};
439454
};
440455

441-
PacketCache() = default;
456+
PacketCache();
442457
PacketCache(PacketCache const& r) = delete;
443458
PacketCache(PacketCache&& r) noexcept;
444459
~PacketCache() = default;
@@ -449,6 +464,7 @@ class FGE_API PacketCache
449464
void clear();
450465
[[nodiscard]] bool isEmpty() const;
451466
[[nodiscard]] bool isEnabled() const;
467+
[[nodiscard]] bool isAlarmed() const;
452468
void enable(bool enable);
453469

454470
//Transmit
@@ -458,9 +474,7 @@ class FGE_API PacketCache
458474
void acknowledgeReception(std::span<Label> labels);
459475

460476
//Check for unacknowledged packet
461-
[[nodiscard]] bool check(std::chrono::steady_clock::time_point const& timePoint,
462-
std::chrono::milliseconds clientDelay);
463-
[[nodiscard]] TransmitPacketPtr pop();
477+
bool process(std::chrono::steady_clock::time_point const& timePoint, Client& client);
464478

465479
private:
466480
struct Data
@@ -473,15 +487,14 @@ class FGE_API PacketCache
473487
TransmitPacketPtr _packet;
474488
Label _label;
475489
std::chrono::steady_clock::time_point _time{};
490+
unsigned int _tryCount{0};
476491
};
477492

478493
mutable std::mutex g_mutex;
479494

480-
//Circular buffer
481-
std::vector<Data> g_cache{FGE_NET_PACKET_CACHE_MAX};
482-
std::size_t g_start{0};
483-
std::size_t g_end{0};
495+
std::vector<Data> g_cache;
484496

497+
bool g_alarm{false};
485498
bool g_enable{false};
486499
};
487500

0 commit comments

Comments
 (0)