diff --git a/include/Nazara/Network/RUdpConnection.hpp b/include/Nazara/Network/RUdpConnection.hpp index b583bdf49..6166d787a 100644 --- a/include/Nazara/Network/RUdpConnection.hpp +++ b/include/Nazara/Network/RUdpConnection.hpp @@ -56,6 +56,8 @@ namespace Nz inline void SetProtocolId(UInt32 protocolId); inline void SetTimeBeforeAck(UInt32 ms); + inline void SimulateNetwork(double packetLoss); + void Update(); RUdpConnection& operator=(const RUdpConnection&) = delete; @@ -137,9 +139,10 @@ namespace Nz UInt64 stateData1; }; - std::unordered_map m_peerByIP; + std::bernoulli_distribution m_packetLossProbability; std::queue m_receivedMessages; std::size_t m_peerIterator; + std::unordered_map m_peerByIP; std::vector m_peers; Bitset m_activeClients; Clock m_clock; @@ -151,6 +154,7 @@ namespace Nz UInt32 m_timeBeforePing; UInt32 m_timeBeforeTimeOut; UInt64 m_currentTime; + bool m_isSimulationEnabled; bool m_shouldAcceptConnections; static std::mt19937_64 s_randomGenerator; diff --git a/include/Nazara/Network/RUdpConnection.inl b/include/Nazara/Network/RUdpConnection.inl index da63536c9..b2372285d 100644 --- a/include/Nazara/Network/RUdpConnection.inl +++ b/include/Nazara/Network/RUdpConnection.inl @@ -121,6 +121,19 @@ namespace Nz NazaraError("PacketReliability not handled (0x" + String::Number(reliability, 16) + ')'); return false; } + + inline void RUdpConnection::SimulateNetwork(double packetLoss) + { + NazaraAssert(packetLoss >= 0.0 && packetLoss <= 1.0, "Packet loss must be in range [0..1]"); + + if (packetLoss > 0.0) + { + m_isSimulationEnabled = true; + m_packetLossProbability = std::bernoulli_distribution(packetLoss); + } + else + m_isSimulationEnabled = false; + } } #include diff --git a/src/Nazara/Network/RUdpConnection.cpp b/src/Nazara/Network/RUdpConnection.cpp index 8d2bc5e32..451d08f1e 100644 --- a/src/Nazara/Network/RUdpConnection.cpp +++ b/src/Nazara/Network/RUdpConnection.cpp @@ -18,6 +18,7 @@ namespace Nz m_timeBeforePing(500'000), //< 0.5s m_timeBeforeTimeOut(10'000'000), //< 10s m_currentTime(0), + m_isSimulationEnabled(false), m_shouldAcceptConnections(true) { } @@ -34,7 +35,7 @@ namespace Nz NetPacket connectionRequestPacket(NetCode_RequestConnection); connectionRequestPacket << client.stateData1; - EnqueuePacket(client, PacketPriority_Immediate, PacketReliability_Unreliable, connectionRequestPacket); + EnqueuePacket(client, PacketPriority_Immediate, PacketReliability_Reliable, connectionRequestPacket); return true; } @@ -349,6 +350,12 @@ namespace Nz if (peer.receivedQueue.find(sequenceId) != peer.receivedQueue.end()) return; //< Ignore + if (m_isSimulationEnabled && m_packetLossProbability(s_randomGenerator)) + { + NazaraNotice(m_socket.GetBoundAddress().ToString() + ": Lost packet " + String::Number(sequenceId) + " from " + peerIp.ToString() + " for simulation purpose"); + return; + } + ///< Receiving a packet from an acknowledged client means the connection works in both ways if (peer.state == PeerState_Aknowledged && packet.GetNetCode() != NetCode_RequestConnection) {