Network/ENetHost: Add network simulator
This commit is contained in:
parent
4e2a037d6b
commit
4e517bc1e3
|
|
@ -55,6 +55,8 @@ namespace Nz
|
|||
|
||||
int Service(ENetEvent* event, UInt32 timeout);
|
||||
|
||||
void SimulateNetwork(double packetLossProbability, UInt16 minDelay, UInt16 maxDelay);
|
||||
|
||||
ENetHost& operator=(const ENetHost&) = delete;
|
||||
ENetHost& operator=(ENetHost&&) = default;
|
||||
|
||||
|
|
@ -96,6 +98,13 @@ namespace Nz
|
|||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
struct PendingPacket
|
||||
{
|
||||
IpAddress from;
|
||||
NetPacket data;
|
||||
UInt32 deliveryTime;
|
||||
};
|
||||
|
||||
std::array<ENetProtocol, ENetConstants::ENetProtocol_MaximumPacketCommands> m_commands;
|
||||
std::array<NetBuffer, ENetConstants::ENetProtocol_MaximumPacketCommands * 2 + 1> m_buffers;
|
||||
std::array<UInt8, ENetConstants::ENetProtocol_MaximumMTU> m_packetData[2];
|
||||
|
|
@ -110,7 +119,10 @@ namespace Nz
|
|||
std::size_t m_packetSize;
|
||||
std::size_t m_peerCount;
|
||||
std::size_t m_receivedDataLength;
|
||||
std::uniform_int_distribution<UInt16> m_packetDelayDistribution;
|
||||
std::vector<ENetPeer> m_peers;
|
||||
std::vector<PendingPacket> m_pendingPackets;
|
||||
UInt8* m_receivedData;
|
||||
Bitset<UInt64> m_dispatchQueue;
|
||||
MemoryPool m_packetPool;
|
||||
IpAddress m_address;
|
||||
|
|
@ -129,10 +141,8 @@ namespace Nz
|
|||
UInt32 m_totalSentPackets;
|
||||
UInt32 m_totalReceivedData;
|
||||
UInt32 m_totalReceivedPackets;
|
||||
UInt8* m_receivedData;
|
||||
bool m_continueSending;
|
||||
bool m_isSimulationEnabled;
|
||||
bool m_shouldAcceptConnections;
|
||||
bool m_recalculateBandwidthLimits;
|
||||
|
||||
static std::mt19937 s_randomGenerator;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
namespace Nz
|
||||
{
|
||||
inline ENetHost::ENetHost() :
|
||||
m_packetPool(sizeof(ENetPacket))
|
||||
m_packetPool(sizeof(ENetPacket)),
|
||||
m_isSimulationEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,6 +312,20 @@ namespace Nz
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ENetHost::SimulateNetwork(double packetLossProbability, UInt16 minDelay, UInt16 maxDelay)
|
||||
{
|
||||
NazaraAssert(maxDelay >= minDelay, "Maximum delay cannot be greater than minimum delay");
|
||||
|
||||
if (packetLossProbability <= 0.0 && minDelay == 0 && maxDelay == 0)
|
||||
m_isSimulationEnabled = false;
|
||||
else
|
||||
{
|
||||
m_isSimulationEnabled = true;
|
||||
m_packetDelayDistribution = std::uniform_int_distribution<UInt16>(minDelay, maxDelay);
|
||||
m_packetLossProbability = std::bernoulli_distribution(packetLossProbability);
|
||||
}
|
||||
}
|
||||
|
||||
bool ENetHost::InitSocket(const IpAddress& address)
|
||||
{
|
||||
if (!m_socket.Create(address.GetProtocol()))
|
||||
|
|
@ -1111,14 +1125,58 @@ namespace Nz
|
|||
{
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
{
|
||||
NetPacket packet;
|
||||
|
||||
bool shouldReceive = true;
|
||||
std::size_t receivedLength;
|
||||
if (!m_socket.Receive(m_packetData[0].data(), m_packetData[0].size(), &m_receivedAddress, &receivedLength))
|
||||
return -1; //< Error
|
||||
|
||||
if (receivedLength == 0)
|
||||
return 0;
|
||||
if (m_isSimulationEnabled)
|
||||
{
|
||||
for (auto it = m_pendingPackets.begin(); it != m_pendingPackets.end(); ++it)
|
||||
{
|
||||
if (m_serviceTime >= it->deliveryTime)
|
||||
{
|
||||
shouldReceive = false;
|
||||
|
||||
m_receivedAddress = it->from;
|
||||
receivedLength = it->data.GetDataSize();
|
||||
std::memcpy(m_packetData[0].data(), it->data.GetConstData() + NetPacket::HeaderSize, receivedLength);
|
||||
|
||||
m_pendingPackets.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldReceive)
|
||||
{
|
||||
if (!m_socket.Receive(m_packetData[0].data(), m_packetData[0].size(), &m_receivedAddress, &receivedLength))
|
||||
return -1; //< Error
|
||||
|
||||
if (receivedLength == 0)
|
||||
return 0;
|
||||
|
||||
if (m_isSimulationEnabled)
|
||||
{
|
||||
if (m_packetLossProbability(s_randomGenerator))
|
||||
continue;
|
||||
|
||||
UInt16 delay = m_packetDelayDistribution(s_randomGenerator);
|
||||
if (delay > 0)
|
||||
{
|
||||
PendingPacket pendingPacket;
|
||||
pendingPacket.deliveryTime = m_serviceTime + delay;
|
||||
pendingPacket.from = m_receivedAddress;
|
||||
pendingPacket.data.Reset(0, m_packetData[0].data(), receivedLength);
|
||||
|
||||
auto it = std::upper_bound(m_pendingPackets.begin(), m_pendingPackets.end(), pendingPacket, [] (const PendingPacket& first, const PendingPacket& second)
|
||||
{
|
||||
return first.deliveryTime < second.deliveryTime;
|
||||
});
|
||||
|
||||
m_pendingPackets.emplace(it, std::move(pendingPacket));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_receivedData = m_packetData[0].data();
|
||||
m_receivedDataLength = receivedLength;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Network/ENetHost.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <iostream>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
#define ENET_TIME_OVERFLOW 86400000
|
||||
|
|
|
|||
Loading…
Reference in New Issue