// Copyright (C) 2017 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_ENETPEER_HPP #define NAZARA_ENETPEER_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace Nz { class ENetHost; class NAZARA_NETWORK_API ENetPeer { friend ENetHost; friend struct PacketRef; public: ENetPeer(ENetHost* host, UInt16 peerId); ENetPeer(const ENetPeer&) = delete; ENetPeer(ENetPeer&&) = default; ~ENetPeer() = default; void Disconnect(UInt32 data); void DisconnectLater(UInt32 data); void DisconnectNow(UInt32 data); inline const IpAddress& GetAddress() const; inline ENetPeerState GetState() const; inline bool HasPendingCommands(); inline bool IsConnected() const; void Ping(); bool Receive(ENetPacketRef* packet, UInt8* channelId); void Reset(); bool Send(UInt8 channelId, ENetPacketRef packetRef); bool Send(UInt8 channelId, ENetPacketFlags flags, NetPacket&& packet); void ThrottleConfigure(UInt32 interval, UInt32 acceleration, UInt32 deceleration); ENetPeer& operator=(const ENetPeer&) = delete; ENetPeer& operator=(ENetPeer&&) = default; private: void InitIncoming(std::size_t channelCount, const IpAddress& address, ENetProtocolConnect& incomingCommand); void InitOutgoing(std::size_t channelCount, const IpAddress& address, UInt32 connectId, UInt32 windowSize); struct Acknowledgement; struct Channel; struct IncomingCommmand; struct OutgoingCommand; inline void ChangeState(ENetPeerState state); bool CheckTimeouts(ENetEvent* event); void DispatchState(ENetPeerState state); void DispatchIncomingReliableCommands(Channel& channel); void DispatchIncomingUnreliableCommands(Channel& channel); void OnConnect(); void OnDisconnect(); ENetProtocolCommand RemoveSentReliableCommand(UInt16 reliableSequenceNumber, UInt8 channelId); void RemoveSentUnreliableCommands(); void ResetQueues(); bool QueueAcknowledgement(ENetProtocol* command, UInt16 sentTime); IncomingCommmand* QueueIncomingCommand(const ENetProtocol& command, const void* data, std::size_t dataLength, UInt32 flags, UInt32 fragmentCount); inline void QueueOutgoingCommand(ENetProtocol& command); void QueueOutgoingCommand(ENetProtocol& command, ENetPacketRef packet, UInt32 offset, UInt16 length); void SetupOutgoingCommand(OutgoingCommand& outgoingCommand); int Throttle(UInt32 rtt); struct Acknowledgement { ENetProtocol command; UInt32 sentTime; }; struct Channel { Channel() { incomingReliableSequenceNumber = 0; incomingUnreliableSequenceNumber = 0; outgoingReliableSequenceNumber = 0; outgoingUnreliableSequenceNumber = 0; usedReliableWindows = 0; reliableWindows.fill(0); } std::array reliableWindows; std::list incomingReliableCommands; std::list incomingUnreliableCommands; UInt16 incomingReliableSequenceNumber; UInt16 incomingUnreliableSequenceNumber; UInt16 outgoingReliableSequenceNumber; UInt16 outgoingUnreliableSequenceNumber; UInt16 usedReliableWindows; }; struct IncomingCommmand { ENetProtocol command; Bitset<> fragments; ENetPacketRef packet; UInt16 reliableSequenceNumber; UInt16 unreliableSequenceNumber; UInt32 fragmentsRemaining; }; struct OutgoingCommand { ENetProtocol command; ENetPacketRef packet; UInt16 fragmentLength; UInt16 reliableSequenceNumber; UInt16 sendAttempts; UInt16 unreliableSequenceNumber; UInt32 fragmentOffset; UInt32 roundTripTimeout; UInt32 roundTripTimeoutLimit; UInt32 sentTime; }; static constexpr std::size_t unsequencedWindow = ENetPeer_ReliableWindowSize / 32; ENetHost* m_host; IpAddress m_address; /**< Internet address of the peer */ std::array m_unsequencedWindow; std::list m_acknowledgements; std::list m_dispatchedCommands; std::list m_outgoingReliableCommands; std::list m_outgoingUnreliableCommands; std::list m_sentReliableCommands; std::list m_sentUnreliableCommands; std::size_t m_totalWaitingData; std::vector m_channels; MemoryPool m_packetPool; ENetPeerState m_state; UInt8 m_incomingSessionID; UInt8 m_outgoingSessionID; UInt16 m_incomingPeerID; UInt16 m_incomingUnsequencedGroup; UInt16 m_outgoingPeerID; UInt16 m_outgoingReliableSequenceNumber; UInt16 m_outgoingUnsequencedGroup; UInt32 m_connectID; UInt32 m_earliestTimeout; UInt32 m_eventData; UInt32 m_highestRoundTripTimeVariance; UInt32 m_incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */ UInt32 m_incomingBandwidthThrottleEpoch; UInt32 m_incomingDataTotal; UInt32 m_lastReceiveTime; UInt32 m_lastRoundTripTime; UInt32 m_lastRoundTripTimeVariance; UInt32 m_lastSendTime; UInt32 m_lowestRoundTripTime; UInt32 m_mtu; UInt32 m_nextTimeout; UInt32 m_outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */ UInt32 m_outgoingBandwidthThrottleEpoch; UInt32 m_outgoingDataTotal; UInt32 m_packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */ UInt32 m_packetLossEpoch; UInt32 m_packetLossVariance; UInt32 m_packetThrottle; UInt32 m_packetThrottleAcceleration; UInt32 m_packetThrottleCounter; UInt32 m_packetThrottleDeceleration; UInt32 m_packetThrottleEpoch; UInt32 m_packetThrottleInterval; UInt32 m_packetThrottleLimit; UInt32 m_packetsLost; UInt32 m_packetsSent; UInt32 m_pingInterval; UInt32 m_reliableDataInTransit; UInt32 m_roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgment */ UInt32 m_roundTripTimeVariance; UInt32 m_timeoutLimit; UInt32 m_timeoutMaximum; UInt32 m_timeoutMinimum; UInt32 m_windowSize; }; } #include #endif // NAZARA_ENETPEER_HPP