Convert all remaining enums to enum classes (!)
This commit is contained in:
@@ -51,7 +51,7 @@ namespace Nz
|
||||
bool CheckEvents(ENetEvent* event);
|
||||
|
||||
ENetPeer* Connect(const IpAddress& remoteAddress, std::size_t channelCount = 0, UInt32 data = 0);
|
||||
ENetPeer* Connect(const std::string& hostName, NetProtocol protocol = NetProtocol_Any, const std::string& service = "http", ResolveError* error = nullptr, std::size_t channelCount = 0, UInt32 data = 0);
|
||||
ENetPeer* Connect(const std::string& hostName, NetProtocol protocol = NetProtocol::Any, const std::string& service = "http", ResolveError* error = nullptr, std::size_t channelCount = 0, UInt32 data = 0);
|
||||
|
||||
inline bool Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount = 0);
|
||||
bool Create(const IpAddress& listenAddress, std::size_t peerCount, std::size_t channelCount = 0);
|
||||
|
||||
@@ -29,23 +29,23 @@ namespace Nz
|
||||
|
||||
inline bool ENetHost::Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount)
|
||||
{
|
||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||
NazaraAssert(protocol != NetProtocol::Unknown, "Invalid protocol");
|
||||
|
||||
IpAddress any;
|
||||
switch (protocol)
|
||||
{
|
||||
case NetProtocol_Unknown:
|
||||
case NetProtocol::Unknown:
|
||||
NazaraInternalError("Invalid protocol");
|
||||
return false;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
case NetProtocol::IPv4:
|
||||
any = IpAddress::AnyIpV4;
|
||||
break;
|
||||
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol::Any:
|
||||
m_isUsingDualStack = true;
|
||||
// fallthrough
|
||||
case NetProtocol_IPv6:
|
||||
case NetProtocol::IPv6:
|
||||
any = IpAddress::AnyIpV6;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,123 +11,114 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
enum NetCode : UInt16
|
||||
enum class NetProtocol
|
||||
{
|
||||
NetCode_Acknowledge = 0x9A4E,
|
||||
NetCode_AcknowledgeConnection = 0xC108,
|
||||
NetCode_Ping = 0x96AC,
|
||||
NetCode_Pong = 0x974C,
|
||||
NetCode_RequestConnection = 0xF27D,
|
||||
Any,
|
||||
IPv4,
|
||||
IPv6,
|
||||
Unknown,
|
||||
|
||||
NetCode_Invalid = 0x0000
|
||||
Max = Unknown
|
||||
};
|
||||
|
||||
enum NetProtocol
|
||||
{
|
||||
NetProtocol_Any,
|
||||
NetProtocol_IPv4,
|
||||
NetProtocol_IPv6,
|
||||
NetProtocol_Unknown,
|
||||
constexpr std::size_t NetProtocolCount = static_cast<std::size_t>(NetProtocol::Max) + 1;
|
||||
|
||||
NetProtocol_Max = NetProtocol_Unknown
|
||||
enum class PacketReliability
|
||||
{
|
||||
Reliable, //< Packet will be resent if lost
|
||||
ReliableOrdered, //< Packet will be resent if lost and will only arrive in order
|
||||
Unreliable, //< Packet won't be resent if lost
|
||||
|
||||
Max = Unreliable
|
||||
};
|
||||
|
||||
enum PacketPriority
|
||||
{
|
||||
PacketPriority_High = 1, //< High-priority packet, will be sent quickly
|
||||
PacketPriority_Immediate = 0, //< Immediate priority, will be sent immediately
|
||||
PacketPriority_Medium = 2, //< Medium-priority packet, will be sent as regular
|
||||
PacketPriority_Low = 3, //< Low-priority packet, may take some time to be sent
|
||||
constexpr std::size_t PacketReliabilityCount = static_cast<std::size_t>(PacketReliability::Max) + 1;
|
||||
|
||||
PacketPriority_Lowest = PacketPriority_Low,
|
||||
PacketPriority_Highest = PacketPriority_Immediate,
|
||||
PacketPriority_Max = PacketPriority_Low
|
||||
enum class ResolveError
|
||||
{
|
||||
NoError,
|
||||
|
||||
Internal, //< An internal error occurred
|
||||
ResourceError, //< The operating system lacks the resources to proceed (insufficient memory)
|
||||
NonRecoverable, //< An nonrecoverable error occurred
|
||||
NotFound, //< No such host is known
|
||||
NotInitialized, //< Nazara network has not been initialized
|
||||
ProtocolNotSupported, //< A specified protocol is not supported by the server
|
||||
TemporaryFailure, //< A temporary failure occurred, try again
|
||||
Unknown, //< The last operation failed with an unlisted error code
|
||||
|
||||
Max = Unknown
|
||||
};
|
||||
|
||||
enum PacketReliability
|
||||
{
|
||||
PacketReliability_Reliable, //< Packet will be resent if lost
|
||||
PacketReliability_ReliableOrdered, //< Packet will be resent if lost and will only arrive in order
|
||||
PacketReliability_Unreliable, //< Packet won't be resent if lost
|
||||
constexpr std::size_t ResolveErrorCount = static_cast<std::size_t>(ResolveError::Max) + 1;
|
||||
|
||||
PacketReliability_Max = PacketReliability_Unreliable
|
||||
enum class SocketError
|
||||
{
|
||||
NoError,
|
||||
|
||||
AddressNotAvailable, //< The address is already in use (when binding/listening)
|
||||
ConnectionClosed, //< The connection has been closed
|
||||
ConnectionRefused, //< The connection attempt was refused
|
||||
DatagramSize, //< The datagram size is over the system limit
|
||||
Internal, //< The error is coming from the engine
|
||||
Interrupted, //< The operation was interrupted by a signal
|
||||
Packet, //< The packet encoding/decoding failed, probably because of corrupted data
|
||||
NetworkError, //< The network system has failed (maybe network is down)
|
||||
NotInitialized, //< Nazara network has not been initialized
|
||||
NotSupported, //< The operation is not supported (e.g. creating a bluetooth socket on a system without any bluetooth adapter)
|
||||
ResolveError, //< The hostname couldn't be resolved (more information in ResolveError code)
|
||||
ResourceError, //< The operating system lacks the resources to proceed (e.g. memory/socket descriptor)
|
||||
TimedOut, //< The operation timed out
|
||||
Unknown, //< The last operation failed with an unlisted error code
|
||||
UnreachableHost, //< The host is not reachable
|
||||
|
||||
Max = UnreachableHost
|
||||
};
|
||||
|
||||
enum ResolveError
|
||||
constexpr std::size_t SocketErrorCount = static_cast<std::size_t>(SocketError::Max) + 1;
|
||||
|
||||
enum class SocketPollEvent
|
||||
{
|
||||
ResolveError_NoError,
|
||||
Read, //< One or more sockets is ready for a read operation
|
||||
Write, //< One or more sockets is ready for a write operation
|
||||
|
||||
ResolveError_Internal, //< An internal error occurred
|
||||
ResolveError_ResourceError, //< The operating system lacks the resources to proceed (insufficient memory)
|
||||
ResolveError_NonRecoverable, //< An nonrecoverable error occurred
|
||||
ResolveError_NotFound, //< No such host is known
|
||||
ResolveError_NotInitialized, //< Nazara network has not been initialized
|
||||
ResolveError_ProtocolNotSupported, //< A specified protocol is not supported by the server
|
||||
ResolveError_TemporaryFailure, //< A temporary failure occurred, try again
|
||||
ResolveError_Unknown, //< The last operation failed with an unlisted error code
|
||||
|
||||
ResolveError_Max = ResolveError_Unknown
|
||||
Max = Write
|
||||
};
|
||||
|
||||
enum SocketError
|
||||
{
|
||||
SocketError_NoError,
|
||||
|
||||
SocketError_AddressNotAvailable, //< The address is already in use (when binding/listening)
|
||||
SocketError_ConnectionClosed, //< The connection has been closed
|
||||
SocketError_ConnectionRefused, //< The connection attempt was refused
|
||||
SocketError_DatagramSize, //< The datagram size is over the system limit
|
||||
SocketError_Internal, //< The error is coming from the engine
|
||||
SocketError_Interrupted, //< The operation was interrupted by a signal
|
||||
SocketError_Packet, //< The packet encoding/decoding failed, probably because of corrupted data
|
||||
SocketError_NetworkError, //< The network system has failed (maybe network is down)
|
||||
SocketError_NotInitialized, //< Nazara network has not been initialized
|
||||
SocketError_NotSupported, //< The operation is not supported (e.g. creating a bluetooth socket on a system without any bluetooth adapter)
|
||||
SocketError_ResolveError, //< The hostname couldn't be resolved (more information in ResolveError code)
|
||||
SocketError_ResourceError, //< The operating system lacks the resources to proceed (e.g. memory/socket descriptor)
|
||||
SocketError_TimedOut, //< The operation timed out
|
||||
SocketError_Unknown, //< The last operation failed with an unlisted error code
|
||||
SocketError_UnreachableHost, //< The host is not reachable
|
||||
|
||||
SocketError_Max = SocketError_UnreachableHost
|
||||
};
|
||||
|
||||
enum SocketPollEvent
|
||||
{
|
||||
SocketPollEvent_Read, //< One or more sockets is ready for a read operation
|
||||
SocketPollEvent_Write, //< One or more sockets is ready for a write operation
|
||||
|
||||
SocketPollEvent_Max = SocketPollEvent_Write
|
||||
};
|
||||
constexpr std::size_t SocketPollEventCount = static_cast<std::size_t>(SocketPollEvent::Max) + 1;
|
||||
|
||||
template<>
|
||||
struct EnumAsFlags<SocketPollEvent>
|
||||
{
|
||||
static constexpr SocketPollEvent max = SocketPollEvent_Max;
|
||||
static constexpr SocketPollEvent max = SocketPollEvent::Max;
|
||||
};
|
||||
|
||||
using SocketPollEventFlags = Flags<SocketPollEvent>;
|
||||
|
||||
enum SocketState
|
||||
enum class SocketState
|
||||
{
|
||||
SocketState_Bound, //< The socket is currently bound
|
||||
SocketState_Connecting, //< The socket is currently connecting
|
||||
SocketState_Connected, //< The socket is currently connected
|
||||
SocketState_NotConnected, //< The socket is not connected (or has been disconnected)
|
||||
SocketState_Resolving, //< The socket is currently resolving a host name
|
||||
Bound, //< The socket is currently bound
|
||||
Connecting, //< The socket is currently connecting
|
||||
Connected, //< The socket is currently connected
|
||||
NotConnected, //< The socket is not connected (or has been disconnected)
|
||||
Resolving, //< The socket is currently resolving a host name
|
||||
|
||||
SocketState_Max = SocketState_Resolving
|
||||
Max = Resolving
|
||||
};
|
||||
|
||||
enum SocketType
|
||||
{
|
||||
SocketType_Raw,
|
||||
SocketType_TCP,
|
||||
SocketType_UDP,
|
||||
SocketType_Unknown,
|
||||
constexpr std::size_t SocketStateCount = static_cast<std::size_t>(SocketState::Max) + 1;
|
||||
|
||||
SocketType_Max = SocketType_Unknown
|
||||
enum class SocketType
|
||||
{
|
||||
Raw,
|
||||
TCP,
|
||||
UDP,
|
||||
Unknown,
|
||||
|
||||
Max = Unknown
|
||||
};
|
||||
|
||||
constexpr std::size_t SocketTypeCount = static_cast<std::size_t>(SocketType::Max) + 1;
|
||||
}
|
||||
|
||||
#endif // NAZARA_ENUMS_NETWORK_HPP
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Nz
|
||||
|
||||
inline IpAddress::IpAddress(const IPv4& ip, UInt16 port) :
|
||||
m_ipv4(ip),
|
||||
m_protocol(NetProtocol_IPv4),
|
||||
m_protocol(NetProtocol::IPv4),
|
||||
m_port(port),
|
||||
m_isValid(true)
|
||||
{
|
||||
@@ -42,7 +42,7 @@ namespace Nz
|
||||
|
||||
inline IpAddress::IpAddress(const IPv6& ip, UInt16 port) :
|
||||
m_ipv6(ip),
|
||||
m_protocol(NetProtocol_IPv6),
|
||||
m_protocol(NetProtocol::IPv6),
|
||||
m_port(port),
|
||||
m_isValid(true)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ namespace Nz
|
||||
|
||||
inline IpAddress::IPv4 IpAddress::ToIPv4() const
|
||||
{
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol_IPv4, "Address is not a valid IPv4");
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol::IPv4, "Address is not a valid IPv4");
|
||||
|
||||
return m_ipv4;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ namespace Nz
|
||||
|
||||
inline IpAddress::IPv6 IpAddress::ToIPv6() const
|
||||
{
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol_IPv6, "IP is not a valid IPv6");
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol::IPv6, "IP is not a valid IPv6");
|
||||
|
||||
return m_ipv6;
|
||||
}
|
||||
@@ -177,7 +177,7 @@ namespace Nz
|
||||
|
||||
inline UInt32 IpAddress::ToUInt32() const
|
||||
{
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol_IPv4, "Address is not a valid IPv4");
|
||||
NazaraAssert(m_isValid && m_protocol == NetProtocol::IPv4, "Address is not a valid IPv4");
|
||||
|
||||
return UInt32(m_ipv4[0]) << 24 |
|
||||
UInt32(m_ipv4[1]) << 16 |
|
||||
@@ -231,11 +231,11 @@ namespace Nz
|
||||
// Each protocol has its variables to compare
|
||||
switch (first.m_protocol)
|
||||
{
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_Unknown:
|
||||
case NetProtocol::Any:
|
||||
case NetProtocol::Unknown:
|
||||
break;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
case NetProtocol::IPv4:
|
||||
{
|
||||
if (first.m_ipv4 != second.m_ipv4)
|
||||
return false;
|
||||
@@ -243,7 +243,7 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
case NetProtocol_IPv6:
|
||||
case NetProtocol::IPv6:
|
||||
{
|
||||
if (first.m_ipv6 != second.m_ipv6)
|
||||
return false;
|
||||
@@ -297,11 +297,11 @@ namespace Nz
|
||||
// Compare IP (thanks to std::array comparison operator)
|
||||
switch (first.m_protocol)
|
||||
{
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_Unknown:
|
||||
case NetProtocol::Any:
|
||||
case NetProtocol::Unknown:
|
||||
break;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
case NetProtocol::IPv4:
|
||||
{
|
||||
if (first.m_ipv4 != second.m_ipv4)
|
||||
return first.m_ipv4 < second.m_ipv4;
|
||||
@@ -309,7 +309,7 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
case NetProtocol_IPv6:
|
||||
case NetProtocol::IPv6:
|
||||
{
|
||||
if (first.m_ipv6 != second.m_ipv6)
|
||||
return first.m_ipv6 < second.m_ipv6;
|
||||
@@ -387,16 +387,16 @@ namespace std
|
||||
std::size_t h = 0;
|
||||
switch (ip.GetProtocol())
|
||||
{
|
||||
case Nz::NetProtocol_Any:
|
||||
case Nz::NetProtocol_Unknown:
|
||||
case Nz::NetProtocol::Any:
|
||||
case Nz::NetProtocol::Unknown:
|
||||
return std::numeric_limits<size_t>::max();
|
||||
|
||||
case Nz::NetProtocol_IPv4:
|
||||
case Nz::NetProtocol::IPv4:
|
||||
{
|
||||
h = ip.ToUInt32() + (h << 6) + (h << 16) - h;
|
||||
break;
|
||||
}
|
||||
case Nz::NetProtocol_IPv6:
|
||||
case Nz::NetProtocol::IPv6:
|
||||
{
|
||||
Nz::IpAddress::IPv6 v6 = ip.ToIPv6();
|
||||
for (std::size_t i = 0; i < v6.size(); i++)
|
||||
|
||||
@@ -12,9 +12,8 @@ namespace Nz
|
||||
/*!
|
||||
* \brief Constructs a NetPacket object by default
|
||||
*/
|
||||
|
||||
inline NetPacket::NetPacket() :
|
||||
m_netCode(NetCode_Invalid)
|
||||
m_netCode(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ namespace Nz
|
||||
|
||||
inline void NetPacket::Reset(UInt16 netCode, const void* ptr, std::size_t size)
|
||||
{
|
||||
InitStream(HeaderSize + size, HeaderSize, OpenMode_ReadOnly);
|
||||
InitStream(HeaderSize + size, HeaderSize, OpenMode::ReadOnly);
|
||||
m_buffer->Resize(HeaderSize + size);
|
||||
|
||||
if (ptr)
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Network module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_RUDPSERVER_HPP
|
||||
#define NAZARA_RUDPSERVER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Network/IpAddress.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <Nazara/Network/RUdpMessage.hpp>
|
||||
#include <Nazara/Network/UdpSocket.hpp>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_NETWORK_API RUdpConnection
|
||||
{
|
||||
friend class Network;
|
||||
|
||||
public:
|
||||
using SequenceIndex = UInt16;
|
||||
|
||||
RUdpConnection();
|
||||
RUdpConnection(const RUdpConnection&) = delete;
|
||||
RUdpConnection(RUdpConnection&&) = default;
|
||||
~RUdpConnection() = default;
|
||||
|
||||
inline void Close();
|
||||
|
||||
bool Connect(const IpAddress& remoteAddress);
|
||||
bool Connect(const std::string& hostName, NetProtocol protocol = NetProtocol_Any, const std::string& service = "http", ResolveError* error = nullptr);
|
||||
inline void Disconnect();
|
||||
|
||||
inline IpAddress GetBoundAddress() const;
|
||||
inline UInt16 GetBoundPort() const;
|
||||
inline SocketError GetLastError() const;
|
||||
|
||||
inline bool Listen(NetProtocol protocol, UInt16 port = 64266);
|
||||
bool Listen(const IpAddress& address);
|
||||
|
||||
bool PollMessage(RUdpMessage* message);
|
||||
|
||||
bool Send(const IpAddress& clientIp, PacketPriority priority, PacketReliability reliability, const NetPacket& packet);
|
||||
|
||||
inline void SetProtocolId(UInt32 protocolId);
|
||||
inline void SetTimeBeforeAck(UInt32 ms);
|
||||
|
||||
inline void SimulateNetwork(double packetLoss);
|
||||
|
||||
void Update();
|
||||
|
||||
RUdpConnection& operator=(const RUdpConnection&) = delete;
|
||||
RUdpConnection& operator=(RUdpConnection&&) = default;
|
||||
|
||||
static constexpr std::size_t MessageHeader = sizeof(UInt16) + 2 * sizeof(SequenceIndex) + sizeof(UInt32); //< Protocol ID (begin) + Sequence ID + Remote Sequence ID + Ack bitfield
|
||||
static constexpr std::size_t MessageFooter = sizeof(UInt16); //< Protocol ID (end)
|
||||
|
||||
// Signals:
|
||||
NazaraSignal(OnConnectedToPeer, RUdpConnection* /*connection*/);
|
||||
NazaraSignal(OnPeerAcknowledged, RUdpConnection* /*connection*/, const IpAddress& /*adress*/);
|
||||
NazaraSignal(OnPeerConnection, RUdpConnection* /*connection*/, const IpAddress& /*adress*/);
|
||||
NazaraSignal(OnPeerDisconnected, RUdpConnection* /*connection*/, const IpAddress& /*adress*/);
|
||||
|
||||
private:
|
||||
struct PeerData;
|
||||
struct PendingAckPacket;
|
||||
struct PendingPacket;
|
||||
|
||||
enum PeerState
|
||||
{
|
||||
PeerState_Aknowledged, //< A connection request from this peer has been received, we're waiting for another packet to validate
|
||||
PeerState_Connected, //< Connection is working in both-ways
|
||||
PeerState_Connecting, //< A connection request has been made
|
||||
PeerState_WillAck //< Connected, received one or more packets and has no packets to send, waiting before sending an empty ack packet
|
||||
};
|
||||
|
||||
void DisconnectPeer(std::size_t peerIndex);
|
||||
void EnqueuePacket(PeerData& peer, PacketPriority priority, PacketReliability reliability, const NetPacket& packet);
|
||||
void EnqueuePacketInternal(PeerData& peer, PacketPriority priority, PacketReliability reliability, NetPacket&& data);
|
||||
bool InitSocket(NetProtocol protocol);
|
||||
void ProcessAcks(PeerData& peer, SequenceIndex lastAck, UInt32 ackBits);
|
||||
PeerData& RegisterPeer(const IpAddress& address, PeerState state);
|
||||
void OnClientRequestingConnection(const IpAddress& address, SequenceIndex sequenceId, UInt64 token);
|
||||
void OnPacketLost(PeerData& peer, PendingAckPacket&& packet);
|
||||
void OnPacketReceived(const IpAddress& peerIp, NetPacket&& packet);
|
||||
void SendPacket(PeerData& peer, PendingPacket&& packet);
|
||||
|
||||
static inline unsigned int ComputeSequenceDifference(SequenceIndex sequence, SequenceIndex sequence2);
|
||||
static inline bool HasPendingPackets(PeerData& peer);
|
||||
static bool Initialize();
|
||||
static inline bool IsAckMoreRecent(SequenceIndex ack, SequenceIndex ack2);
|
||||
static inline bool IsReliable(PacketReliability reliability);
|
||||
static void Uninitialize();
|
||||
|
||||
struct PendingPacket
|
||||
{
|
||||
PacketPriority priority;
|
||||
PacketReliability reliability;
|
||||
NetPacket data;
|
||||
};
|
||||
|
||||
struct PendingAckPacket
|
||||
{
|
||||
PacketPriority priority;
|
||||
PacketReliability reliability;
|
||||
NetPacket data;
|
||||
SequenceIndex sequenceId;
|
||||
UInt64 timeSent;
|
||||
};
|
||||
|
||||
struct PeerData //TODO: Move this to RUdpClient
|
||||
{
|
||||
PeerData() = default;
|
||||
PeerData(PeerData&& other) = default;
|
||||
PeerData& operator=(PeerData&& other) = default;
|
||||
|
||||
std::array<std::vector<PendingPacket>, PacketPriority_Max + 1> pendingPackets;
|
||||
std::deque<PendingAckPacket> pendingAckQueue;
|
||||
std::set<UInt16> receivedQueue;
|
||||
std::size_t index;
|
||||
PeerState state;
|
||||
IpAddress address;
|
||||
SequenceIndex localSequence;
|
||||
SequenceIndex remoteSequence;
|
||||
UInt32 roundTripTime;
|
||||
UInt64 lastPacketTime;
|
||||
UInt64 lastPingTime;
|
||||
UInt64 stateData1;
|
||||
};
|
||||
|
||||
std::bernoulli_distribution m_packetLossProbability;
|
||||
std::queue<RUdpMessage> m_receivedMessages;
|
||||
std::size_t m_peerIterator;
|
||||
std::unordered_map<IpAddress, std::size_t> m_peerByIP;
|
||||
std::vector<PeerData> m_peers;
|
||||
Bitset<UInt64> m_activeClients;
|
||||
Clock m_clock;
|
||||
SocketError m_lastError;
|
||||
UdpSocket m_socket;
|
||||
UInt32 m_forceAckSendTime;
|
||||
UInt32 m_pingInterval;
|
||||
UInt32 m_protocol;
|
||||
UInt32 m_timeBeforePing;
|
||||
UInt32 m_timeBeforeTimeOut;
|
||||
UInt64 m_currentTime;
|
||||
bool m_isSimulationEnabled;
|
||||
bool m_shouldAcceptConnections;
|
||||
|
||||
static std::mt19937_64 s_randomGenerator;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Network/RUdpConnection.inl>
|
||||
|
||||
#endif // NAZARA_RUDPSERVER_HPP
|
||||
@@ -1,220 +0,0 @@
|
||||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Network module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Closes the connection
|
||||
*/
|
||||
|
||||
inline void RUdpConnection::Close()
|
||||
{
|
||||
m_socket.Close();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Disconnects the connection
|
||||
*
|
||||
* \see Close
|
||||
*/
|
||||
|
||||
inline void RUdpConnection::Disconnect()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the bound address
|
||||
* \return IpAddress we are linked to
|
||||
*/
|
||||
|
||||
inline IpAddress RUdpConnection::GetBoundAddress() const
|
||||
{
|
||||
return m_socket.GetBoundAddress();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the port of the bound address
|
||||
* \return Port we are linked to
|
||||
*/
|
||||
|
||||
inline UInt16 RUdpConnection::GetBoundPort() const
|
||||
{
|
||||
return m_socket.GetBoundPort();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the last error
|
||||
* \return Socket error
|
||||
*/
|
||||
|
||||
inline SocketError RUdpConnection::GetLastError() const
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Listens to a socket
|
||||
* \return true If successfully bound
|
||||
*
|
||||
* \param protocol Net protocol to listen to
|
||||
* \param port Port to listen to
|
||||
*
|
||||
* \remark Produces a NazaraAssert if protocol is unknown or any
|
||||
*/
|
||||
|
||||
inline bool RUdpConnection::Listen(NetProtocol protocol, UInt16 port)
|
||||
{
|
||||
NazaraAssert(protocol != NetProtocol_Any, "Any protocol not supported for Listen"); //< TODO
|
||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||
|
||||
IpAddress any;
|
||||
switch (protocol)
|
||||
{
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_Unknown:
|
||||
NazaraInternalError("Invalid protocol Any at this point");
|
||||
return false;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
any = IpAddress::AnyIpV4;
|
||||
break;
|
||||
|
||||
case NetProtocol_IPv6:
|
||||
any = IpAddress::AnyIpV6;
|
||||
break;
|
||||
}
|
||||
|
||||
any.SetPort(port);
|
||||
return Listen(any);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the protocol id
|
||||
*
|
||||
* \param protocolId Protocol ID like NNet
|
||||
*/
|
||||
|
||||
inline void RUdpConnection::SetProtocolId(UInt32 protocolId)
|
||||
{
|
||||
m_protocol = protocolId;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the time before ack
|
||||
*
|
||||
* \param Time before acking to send many together (in ms)
|
||||
*/
|
||||
|
||||
inline void RUdpConnection::SetTimeBeforeAck(UInt32 ms)
|
||||
{
|
||||
m_forceAckSendTime = ms * 1000; //< Store in microseconds for easier handling
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the difference of sequence
|
||||
* \return Delta between the two sequences
|
||||
*
|
||||
* \param sequence First sequence
|
||||
* \param sequence2 Second sequence
|
||||
*/
|
||||
|
||||
inline unsigned int RUdpConnection::ComputeSequenceDifference(SequenceIndex sequence, SequenceIndex sequence2)
|
||||
{
|
||||
unsigned int difference;
|
||||
if (sequence2 > sequence)
|
||||
difference = std::numeric_limits<SequenceIndex>::max() - sequence2 + sequence;
|
||||
else
|
||||
difference = sequence - sequence2;
|
||||
|
||||
return difference;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the peer has pending packets
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param peer Data relative to the peer
|
||||
*/
|
||||
|
||||
inline bool RUdpConnection::HasPendingPackets(PeerData& peer)
|
||||
{
|
||||
for (unsigned int priority = PacketPriority_Highest; priority <= PacketPriority_Lowest; ++priority)
|
||||
{
|
||||
std::vector<PendingPacket>& pendingPackets = peer.pendingPackets[priority];
|
||||
if (!pendingPackets.empty())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the ack is more recent
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param ack First sequence
|
||||
* \param ack2 Second sequence
|
||||
*/
|
||||
|
||||
inline bool RUdpConnection::IsAckMoreRecent(SequenceIndex ack, SequenceIndex ack2)
|
||||
{
|
||||
constexpr SequenceIndex maxDifference = std::numeric_limits<SequenceIndex>::max() / 2;
|
||||
|
||||
if (ack > ack2)
|
||||
return ack - ack2 <= maxDifference;
|
||||
else if (ack2 > ack)
|
||||
return ack2 - ack > maxDifference;
|
||||
else
|
||||
return false; ///< Same ack
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the connection is reliable
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \remark Produces a NazaraError if enumeration is invalid
|
||||
*/
|
||||
|
||||
inline bool RUdpConnection::IsReliable(PacketReliability reliability)
|
||||
{
|
||||
switch (reliability)
|
||||
{
|
||||
case PacketReliability_Reliable:
|
||||
case PacketReliability_ReliableOrdered:
|
||||
return true;
|
||||
|
||||
case PacketReliability_Unreliable:
|
||||
return false;
|
||||
}
|
||||
|
||||
NazaraError("PacketReliability not handled (0x" + NumberToString(reliability, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Simulates the loss of packets on network
|
||||
*
|
||||
* \param packetLoss Ratio of packet loss according to bernoulli distribution
|
||||
*
|
||||
* \remark Produces a NazaraAssert if packetLoss is not in between 0.0 and 1.0
|
||||
*/
|
||||
|
||||
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 <Nazara/Network/DebugOff.hpp>
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Network module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_RUDMESSAGE_HPP
|
||||
#define NAZARA_RUDMESSAGE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Network/IpAddress.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct RUdpMessage
|
||||
{
|
||||
IpAddress from;
|
||||
NetPacket data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_RUDMESSAGE_HPP
|
||||
@@ -29,7 +29,7 @@ namespace Nz
|
||||
~TcpClient() = default;
|
||||
|
||||
SocketState Connect(const IpAddress& remoteAddress);
|
||||
SocketState Connect(const std::string& hostName, NetProtocol protocol = NetProtocol_Any, const std::string& service = "http", ResolveError* error = nullptr);
|
||||
SocketState Connect(const std::string& hostName, NetProtocol protocol = NetProtocol::Any, const std::string& service = "http", ResolveError* error = nullptr);
|
||||
inline void Disconnect();
|
||||
|
||||
void EnableLowDelay(bool lowDelay);
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace Nz
|
||||
*/
|
||||
|
||||
inline TcpClient::TcpClient() :
|
||||
AbstractSocket(SocketType_TCP),
|
||||
Stream(StreamOption_Sequential),
|
||||
AbstractSocket(SocketType::TCP),
|
||||
Stream(StreamOption::Sequential),
|
||||
m_keepAliveInterval(1000), //TODO: Query OS default value
|
||||
m_keepAliveTime(7'200'000), //TODO: Query OS default value
|
||||
m_isKeepAliveEnabled(false), //TODO: Query OS default value
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Nz
|
||||
*/
|
||||
|
||||
inline TcpServer::TcpServer() :
|
||||
AbstractSocket(SocketType_TCP)
|
||||
AbstractSocket(SocketType::TCP)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -61,22 +61,22 @@ namespace Nz
|
||||
|
||||
inline SocketState TcpServer::Listen(NetProtocol protocol, UInt16 port, unsigned int queueSize)
|
||||
{
|
||||
NazaraAssert(protocol != NetProtocol_Any, "Any protocol not supported for Listen"); //< TODO
|
||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||
NazaraAssert(protocol != NetProtocol::Any, "Any protocol not supported for Listen"); //< TODO
|
||||
NazaraAssert(protocol != NetProtocol::Unknown, "Invalid protocol");
|
||||
|
||||
IpAddress any;
|
||||
switch (protocol)
|
||||
{
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_Unknown:
|
||||
case NetProtocol::Any:
|
||||
case NetProtocol::Unknown:
|
||||
NazaraInternalError("Invalid protocol Any at this point");
|
||||
return SocketState_NotConnected;
|
||||
return SocketState::NotConnected;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
case NetProtocol::IPv4:
|
||||
any = IpAddress::AnyIpV4;
|
||||
break;
|
||||
|
||||
case NetProtocol_IPv6:
|
||||
case NetProtocol::IPv6:
|
||||
any = IpAddress::AnyIpV6;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Nz
|
||||
*/
|
||||
|
||||
inline UdpSocket::UdpSocket() :
|
||||
AbstractSocket(SocketType_UDP)
|
||||
AbstractSocket(SocketType::UDP)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -51,16 +51,16 @@ namespace Nz
|
||||
IpAddress any;
|
||||
switch (m_protocol)
|
||||
{
|
||||
case NetProtocol_Unknown:
|
||||
case NetProtocol::Unknown:
|
||||
NazaraInternalError("Invalid protocol");
|
||||
return SocketState_NotConnected;
|
||||
return SocketState::NotConnected;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
case NetProtocol::IPv4:
|
||||
any = IpAddress::AnyIpV4;
|
||||
break;
|
||||
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_IPv6:
|
||||
case NetProtocol::Any:
|
||||
case NetProtocol::IPv6:
|
||||
any = IpAddress::AnyIpV6;
|
||||
break;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ namespace Nz
|
||||
|
||||
bool UdpSocket::Create(NetProtocol protocol)
|
||||
{
|
||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||
NazaraAssert(protocol != NetProtocol::Unknown, "Invalid protocol");
|
||||
|
||||
return Open(protocol);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user