From b5797dfa12b11a307c55525c64b8abbb5b9c16af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 30 Jan 2017 18:08:21 +0100 Subject: [PATCH] Network/ENetHost: Move handling to ENetPeer --- include/Nazara/Network/ENetHost.hpp | 13 +- include/Nazara/Network/ENetPeer.hpp | 15 +- src/Nazara/Network/ENetHost.cpp | 473 +--------------------------- src/Nazara/Network/ENetPeer.cpp | 449 +++++++++++++++++++++++++- 4 files changed, 475 insertions(+), 475 deletions(-) diff --git a/include/Nazara/Network/ENetHost.hpp b/include/Nazara/Network/ENetHost.hpp index 0dcf58a86..fe9956538 100644 --- a/include/Nazara/Network/ENetHost.hpp +++ b/include/Nazara/Network/ENetHost.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// 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 @@ -68,19 +68,8 @@ namespace Nz bool DispatchIncomingCommands(ENetEvent* event); - bool HandleAcknowledge(ENetEvent* event, ENetPeer* peer, const ENetProtocol* command); - bool HandleBandwidthLimit(ENetPeer* peer, const ENetProtocol* command); ENetPeer* HandleConnect(ENetProtocolHeader* header, ENetProtocol* command); - bool HandleDisconnect(ENetPeer* peer, const ENetProtocol* command); bool HandleIncomingCommands(ENetEvent* event); - bool HandlePing(ENetPeer* peer, const ENetProtocol* command); - bool HandleSendFragment(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData); - bool HandleSendReliable(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData); - bool HandleSendUnreliable(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData); - bool HandleSendUnreliableFragment(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData); - bool HandleSendUnsequenced(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData); - bool HandleThrottleConfigure(ENetPeer* peer, const ENetProtocol* command); - bool HandleVerifyConnect(ENetEvent* event, ENetPeer* peer, ENetProtocol* command); int ReceiveIncomingCommands(ENetEvent* event); diff --git a/include/Nazara/Network/ENetPeer.hpp b/include/Nazara/Network/ENetPeer.hpp index aa3c9f2da..c0d24f6f6 100644 --- a/include/Nazara/Network/ENetPeer.hpp +++ b/include/Nazara/Network/ENetPeer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// 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 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -77,6 +78,18 @@ namespace Nz void DispatchIncomingReliableCommands(Channel& channel); void DispatchIncomingUnreliableCommands(Channel& channel); + bool HandleAcknowledge(const ENetProtocol* command, ENetEvent* event); + bool HandleBandwidthLimit(const ENetProtocol* command); + bool HandleDisconnect(const ENetProtocol* command); + bool HandlePing(const ENetProtocol* command); + bool HandleSendFragment(const ENetProtocol* command, UInt8** data); + bool HandleSendReliable(const ENetProtocol* command, UInt8** data); + bool HandleSendUnreliable(const ENetProtocol* command, UInt8** data); + bool HandleSendUnreliableFragment(const ENetProtocol* command, UInt8** data); + bool HandleSendUnsequenced(const ENetProtocol* command, UInt8** data); + bool HandleThrottleConfigure(const ENetProtocol* command); + bool HandleVerifyConnect(const ENetProtocol* command, ENetEvent* event); + void OnConnect(); void OnDisconnect(); diff --git a/src/Nazara/Network/ENetHost.cpp b/src/Nazara/Network/ENetHost.cpp index 3587e19d1..4da174baf 100644 --- a/src/Nazara/Network/ENetHost.cpp +++ b/src/Nazara/Network/ENetHost.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -411,116 +411,6 @@ namespace Nz return false; } - bool ENetHost::HandleAcknowledge(ENetEvent* event, ENetPeer* peer, const ENetProtocol* command) - { - if (peer->GetState() == ENetPeerState::Disconnected || peer->GetState() == ENetPeerState::Zombie) - return true; - - UInt32 receivedSentTime = NetToHost(command->acknowledge.receivedSentTime); - receivedSentTime |= m_serviceTime & 0xFFFF0000; - if ((receivedSentTime & 0x8000) > (m_serviceTime & 0x8000)) - receivedSentTime -= 0x10000; - - if (ENET_TIME_LESS(m_serviceTime, receivedSentTime)) - return true; - - peer->m_lastReceiveTime = m_serviceTime; - peer->m_earliestTimeout = 0; - - UInt32 roundTripTime = ENET_TIME_DIFFERENCE(m_serviceTime, receivedSentTime); - - peer->Throttle(roundTripTime); - - peer->m_roundTripTimeVariance -= peer->m_roundTripTimeVariance / 4; - - if (roundTripTime >= peer->m_roundTripTime) - { - peer->m_roundTripTime += (roundTripTime - peer->m_roundTripTime) / 8; - peer->m_roundTripTimeVariance += (roundTripTime - peer->m_roundTripTime) / 4; - } - else - { - peer->m_roundTripTime -= (peer->m_roundTripTime - roundTripTime) / 8; - peer->m_roundTripTimeVariance += (peer->m_roundTripTime - roundTripTime) / 4; - } - - if (peer->m_roundTripTime < peer->m_lowestRoundTripTime) - peer->m_lowestRoundTripTime = peer->m_roundTripTime; - - if (peer->m_roundTripTimeVariance > peer->m_highestRoundTripTimeVariance) - peer->m_highestRoundTripTimeVariance = peer->m_roundTripTimeVariance; - - if (peer->m_packetThrottleEpoch == 0 || ENET_TIME_DIFFERENCE(m_serviceTime, peer->m_packetThrottleEpoch) >= peer->m_packetThrottleInterval) - { - peer->m_lastRoundTripTime = peer->m_lowestRoundTripTime; - peer->m_lastRoundTripTimeVariance = peer->m_highestRoundTripTimeVariance; - peer->m_lowestRoundTripTime = peer->m_roundTripTime; - peer->m_highestRoundTripTimeVariance = peer->m_roundTripTimeVariance; - peer->m_packetThrottleEpoch = m_serviceTime; - } - - UInt16 receivedReliableSequenceNumber = NetToHost(command->acknowledge.receivedReliableSequenceNumber); - - ENetProtocolCommand commandNumber = peer->RemoveSentReliableCommand(receivedReliableSequenceNumber, command->header.channelID); - - switch (peer->GetState()) - { - case ENetPeerState::AcknowledgingConnect: - if (commandNumber != ENetProtocolCommand_VerifyConnect) - return false; - - NotifyConnect(peer, event); - break; - - case ENetPeerState::Disconnecting: - if (commandNumber != ENetProtocolCommand_Disconnect) - return false; - - NotifyDisconnect(peer, event); - break; - - case ENetPeerState::DisconnectLater: - if (!peer->HasPendingCommands()) - peer->Disconnect(peer->m_eventData); - - break; - - default: - break; - } - - return true; - } - - bool ENetHost::HandleBandwidthLimit(ENetPeer* peer, const ENetProtocol* command) - { - if (!peer->IsConnected()) - return false; - - if (peer->m_incomingBandwidth != 0) - --m_bandwidthLimitedPeers; - - peer->m_incomingBandwidth = NetToHost(command->bandwidthLimit.incomingBandwidth); - peer->m_outgoingBandwidth = NetToHost(command->bandwidthLimit.outgoingBandwidth); - - if (peer->m_incomingBandwidth != 0) - ++m_bandwidthLimitedPeers; - - if (peer->m_incomingBandwidth == 0 && m_outgoingBandwidth == 0) - peer->m_windowSize = ENetConstants::ENetProtocol_MaximumWindowSize; - else - { - if (peer->m_incomingBandwidth == 0 || m_outgoingBandwidth == 0) - peer->m_windowSize = (std::max(peer->m_incomingBandwidth, m_outgoingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; - else - peer->m_windowSize = (std::min(peer->m_incomingBandwidth, m_outgoingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; - - peer->m_windowSize = Clamp(peer->m_windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); - } - - return true; - } - ENetPeer* ENetHost::HandleConnect(ENetProtocolHeader* /*header*/, ENetProtocol* command) { UInt32 channelCount = NetToHost(command->connect.channelCount); @@ -590,37 +480,6 @@ namespace Nz return peer; } - bool ENetHost::HandleDisconnect(ENetPeer* peer, const ENetProtocol * command) - { - if (peer->GetState() == ENetPeerState::Disconnected || peer->GetState() == ENetPeerState::Zombie || peer->GetState() == ENetPeerState::AcknowledgingDisconnect) - return true; - - peer->ResetQueues(); - - if (peer->GetState() == ENetPeerState::ConnectionSucceeded || peer->GetState() == ENetPeerState::Disconnecting || peer->GetState() == ENetPeerState::Connecting) - peer->DispatchState(ENetPeerState::Zombie); - else - { - if (!peer->IsConnected()) - { - if (peer->GetState() == ENetPeerState::ConnectionPending) - m_recalculateBandwidthLimits = true; - - peer->Reset(); - } - else - if (command->header.command & ENetProtocolFlag_Acknowledge) - peer->ChangeState(ENetPeerState::AcknowledgingDisconnect); - else - peer->DispatchState(ENetPeerState::Zombie); - } - - if (peer->GetState() != ENetPeerState::Disconnected) - peer->m_eventData = NetToHost(command->disconnect.data); - - return true; - } - bool ENetHost::HandleIncomingCommands(ENetEvent* event) { if (m_receivedDataLength < NazaraOffsetOf(ENetProtocolHeader, sentTime)) @@ -702,7 +561,7 @@ namespace Nz switch (commandNumber) { case ENetProtocolCommand_Acknowledge: - if (!HandleAcknowledge(event, peer, command)) + if (!peer->HandleAcknowledge(command, event)) return commandError(); break; @@ -718,61 +577,61 @@ namespace Nz break; case ENetProtocolCommand_VerifyConnect: - if (!HandleVerifyConnect(event, peer, command)) + if (!peer->HandleVerifyConnect(command, event)) return commandError(); break; case ENetProtocolCommand_Disconnect: - if (!HandleDisconnect(peer, command)) + if (!peer->HandleDisconnect(command)) return commandError(); break; case ENetProtocolCommand_Ping: - if (!HandlePing(peer, command)) + if (!peer->HandlePing(command)) return commandError(); break; case ENetProtocolCommand_SendReliable: - if (!HandleSendReliable(peer, command, ¤tData)) + if (!peer->HandleSendReliable(command, ¤tData)) return commandError(); break; case ENetProtocolCommand_SendUnreliable: - if (!HandleSendUnreliable(peer, command, ¤tData)) + if (!peer->HandleSendUnreliable(command, ¤tData)) return commandError(); break; case ENetProtocolCommand_SendUnsequenced: - if (!HandleSendUnsequenced(peer, command, ¤tData)) + if (!peer->HandleSendUnsequenced(command, ¤tData)) return commandError(); break; case ENetProtocolCommand_SendFragment: - if (!HandleSendFragment(peer, command, ¤tData)) + if (!peer->HandleSendFragment(command, ¤tData)) return commandError(); break; case ENetProtocolCommand_BandwidthLimit: - if (!HandleBandwidthLimit(peer, command)) + if (!peer->HandleBandwidthLimit(command)) return commandError(); break; case ENetProtocolCommand_ThrottleConfigure: - if (!HandleThrottleConfigure(peer, command)) + if (!peer->HandleThrottleConfigure(command)) return commandError(); break; case ENetProtocolCommand_SendUnreliableFragment: - if (!HandleSendUnreliableFragment(peer, command, ¤tData)) + if (!peer->HandleSendUnreliableFragment(command, ¤tData)) return commandError(); break; @@ -813,314 +672,6 @@ namespace Nz return commandError(); } - bool ENetHost::HandlePing(ENetPeer* peer, const ENetProtocol* /*command*/) - { - if (!peer->IsConnected()) - return false; - - return true; - } - - bool ENetHost::HandleSendFragment(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData) - { - if (command->header.channelID >= peer->m_channels.size() || !peer->IsConnected()) - return false; - - UInt16 fragmentLength = NetToHost(command->sendFragment.dataLength); - *currentData += fragmentLength; - if (fragmentLength >= m_maximumPacketSize || *currentData < m_receivedData || *currentData > &m_receivedData[m_receivedDataLength]) - return false; - - ENetPeer::Channel& channel = peer->m_channels[command->header.channelID]; - UInt32 startSequenceNumber = NetToHost(command->sendFragment.startSequenceNumber); - UInt16 startWindow = startSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; - UInt16 currentWindow = channel.incomingReliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; - - if (startSequenceNumber < channel.incomingReliableSequenceNumber) - startWindow += ENetConstants::ENetPeer_ReliableWindows; - - if (startWindow < currentWindow || startWindow >= currentWindow + ENetConstants::ENetPeer_FreeReliableWindows - 1) - return true; - - UInt32 fragmentNumber = NetToHost(command->sendFragment.fragmentNumber); - UInt32 fragmentCount = NetToHost(command->sendFragment.fragmentCount); - UInt32 fragmentOffset = NetToHost(command->sendFragment.fragmentOffset); - UInt32 totalLength = NetToHost(command->sendFragment.totalLength); - - if (fragmentCount > ENetConstants::ENetProtocol_MaximumFragmentCount || fragmentNumber >= fragmentCount || totalLength > m_maximumPacketSize || - fragmentOffset >= totalLength || fragmentLength > totalLength - fragmentOffset) - return false; - - ENetPeer::IncomingCommmand* startCommand = nullptr; - for (auto currentCommand = channel.incomingReliableCommands.rbegin(); currentCommand != channel.incomingReliableCommands.rend(); ++currentCommand) - { - ENetPeer::IncomingCommmand& incomingCommand = *currentCommand; - - if (startSequenceNumber >= channel.incomingReliableSequenceNumber) - { - if (incomingCommand.reliableSequenceNumber < channel.incomingReliableSequenceNumber) - continue; - } - else if (incomingCommand.reliableSequenceNumber >= channel.incomingReliableSequenceNumber) - break; - - if (incomingCommand.reliableSequenceNumber <= startSequenceNumber) - { - if (incomingCommand.reliableSequenceNumber < startSequenceNumber) - break; - - if ((incomingCommand.command.header.command & ENetProtocolCommand_Mask) != ENetProtocolCommand_SendFragment || - totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.GetSize()) - return false; - - startCommand = &incomingCommand; - break; - } - } - - if (startCommand) - { - ENetProtocol hostCommand = *command; - hostCommand.header.reliableSequenceNumber = startSequenceNumber; - - if (!peer->QueueIncomingCommand(hostCommand, nullptr, totalLength, ENetPacketFlag_Reliable, fragmentCount)) - return false; - } - - if (!startCommand->fragments.Test(fragmentNumber)) - { - --startCommand->fragmentsRemaining; - - startCommand->fragments.Set(fragmentNumber, true); - - if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) - fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; - - std::memcpy(startCommand->packet->data.GetData() + Nz::NetPacket::HeaderSize + fragmentOffset, reinterpret_cast(command) + sizeof(ENetProtocolSendFragment), fragmentLength); - - if (startCommand->fragmentsRemaining <= 0) - peer->DispatchIncomingReliableCommands(channel); - } - - return false; - } - - bool ENetHost::HandleSendReliable(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData) - { - if (command->header.channelID >= peer->m_channels.size() || !peer->IsConnected()) - return false; - - UInt16 dataLength = NetToHost(command->sendReliable.dataLength); - *currentData += dataLength; - if (dataLength >= m_maximumPacketSize || *currentData < m_receivedData || *currentData > &m_receivedData[m_receivedDataLength]) - return false; - - if (!peer->QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendReliable), dataLength, ENetPacketFlag_Reliable, 0)) - return false; - - return true; - } - - bool ENetHost::HandleSendUnreliable(ENetPeer * peer, const ENetProtocol * command, UInt8 ** currentData) - { - if (command->header.channelID >= peer->m_channels.size() || !peer->IsConnected()) - return false; - - UInt16 dataLength = NetToHost(command->sendUnreliable.dataLength); - *currentData += dataLength; - if (dataLength >= m_maximumPacketSize || *currentData < m_receivedData || *currentData > &m_receivedData[m_receivedDataLength]) - return false; - - if (!peer->QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendUnreliable), dataLength, 0, 0)) - return false; - - return true; - } - - bool ENetHost::HandleSendUnreliableFragment(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData) - { - if (command->header.channelID >= peer->m_channels.size() || !peer->IsConnected()) - return false; - - UInt16 fragmentLength = NetToHost(command->sendFragment.dataLength); - *currentData += fragmentLength; - if (fragmentLength >= m_maximumPacketSize || *currentData < m_receivedData || *currentData > &m_receivedData[m_receivedDataLength]) - return false; - - ENetPeer::Channel& channel = peer->m_channels[command->header.channelID]; - UInt32 reliableSequenceNumber = command->header.reliableSequenceNumber; - UInt32 startSequenceNumber = NetToHost(command->sendFragment.startSequenceNumber); - - UInt16 reliableWindow = reliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; - UInt16 currentWindow = channel.incomingReliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; - - if (startSequenceNumber < channel.incomingReliableSequenceNumber) - reliableWindow += ENetConstants::ENetPeer_ReliableWindows; - - if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENetConstants::ENetPeer_FreeReliableWindows - 1) - return true; - - if (reliableSequenceNumber == channel.incomingReliableSequenceNumber && startSequenceNumber <= channel.incomingUnreliableSequenceNumber) - return true; - - UInt32 fragmentNumber = NetToHost(command->sendFragment.fragmentNumber); - UInt32 fragmentCount = NetToHost(command->sendFragment.fragmentCount); - UInt32 fragmentOffset = NetToHost(command->sendFragment.fragmentOffset); - UInt32 totalLength = NetToHost(command->sendFragment.totalLength); - - if (fragmentCount > ENetConstants::ENetProtocol_MaximumFragmentCount || fragmentNumber >= fragmentCount || totalLength > m_maximumPacketSize || - fragmentOffset >= totalLength || fragmentLength > totalLength - fragmentOffset) - return false; - - ENetPeer::IncomingCommmand* startCommand = nullptr; - for (auto currentCommand = channel.incomingUnreliableCommands.rbegin(); currentCommand != channel.incomingUnreliableCommands.rend(); ++currentCommand) - { - ENetPeer::IncomingCommmand& incomingCommand = *currentCommand; - - if (startSequenceNumber >= channel.incomingReliableSequenceNumber) - { - if (incomingCommand.reliableSequenceNumber < channel.incomingReliableSequenceNumber) - continue; - } - else if (incomingCommand.reliableSequenceNumber >= channel.incomingReliableSequenceNumber) - break; - - if (incomingCommand.reliableSequenceNumber < reliableSequenceNumber) - break; - - if (incomingCommand.reliableSequenceNumber > reliableSequenceNumber) - continue; - - if (incomingCommand.unreliableSequenceNumber <= startSequenceNumber) - { - if (incomingCommand.unreliableSequenceNumber < startSequenceNumber) - break; - - if ((incomingCommand.command.header.command & ENetProtocolCommand_Mask) != ENetProtocolCommand_SendUnreliableFragment || - totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.GetSize()) - return false; - - startCommand = &incomingCommand; - break; - } - } - - if (startCommand) - { - if (!peer->QueueIncomingCommand(*command, nullptr, totalLength, ENetPacketFlag_UnreliableFragment, fragmentCount)) - return false; - } - - if (!startCommand->fragments.Test(fragmentNumber)) - { - --startCommand->fragmentsRemaining; - - startCommand->fragments.Set(fragmentNumber, true); - - if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) - fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; - - std::memcpy(startCommand->packet->data.GetData() + Nz::NetPacket::HeaderSize + fragmentOffset, reinterpret_cast(command) + sizeof(ENetProtocolSendFragment), fragmentLength); - - if (startCommand->fragmentsRemaining <= 0) - peer->DispatchIncomingUnreliableCommands(channel); - } - - return true; - } - - bool ENetHost::HandleSendUnsequenced(ENetPeer* peer, const ENetProtocol* command, UInt8** currentData) - { - if (command->header.channelID >= peer->m_channels.size() || !peer->IsConnected()) - return false; - - std::size_t dataLength = NetToHost(command->sendUnsequenced.dataLength); - *currentData += dataLength; - if (dataLength >= m_maximumPacketSize || *currentData < m_receivedData || *currentData > &m_receivedData[m_receivedDataLength]) - return false; - - UInt32 unsequencedGroup = NetToHost(command->sendUnsequenced.unsequencedGroup); - UInt32 index = unsequencedGroup % ENetConstants::ENetPeer_UnsequencedWindowSize; - - if (unsequencedGroup < peer->m_incomingUnsequencedGroup) - unsequencedGroup += 0x10000; - - if (unsequencedGroup >= static_cast(peer->m_incomingUnsequencedGroup) + ENetConstants::ENetPeer_UnsequencedWindows * ENetConstants::ENetPeer_UnsequencedWindowSize) - return true; - - unsequencedGroup &= 0xFFFF; - - if (unsequencedGroup - index != peer->m_incomingUnsequencedGroup) - { - peer->m_incomingUnsequencedGroup = unsequencedGroup - index; - - peer->m_unsequencedWindow.fill(0); - } - else if (peer->m_unsequencedWindow[index / 32] & (1 << (index % 32))) - return true; - - if (!peer->QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendUnsequenced), dataLength, ENetPacketFlag_Unsequenced, 0)) - return false; - - peer->m_unsequencedWindow[index / 32] |= 1 << (index % 32); - - return true; - } - - bool ENetHost::HandleThrottleConfigure(ENetPeer* peer, const ENetProtocol* command) - { - if (!peer->IsConnected()) - return false; - - peer->m_packetThrottleInterval = NetToHost(command->throttleConfigure.packetThrottleInterval); - peer->m_packetThrottleAcceleration = NetToHost(command->throttleConfigure.packetThrottleAcceleration); - peer->m_packetThrottleDeceleration = NetToHost(command->throttleConfigure.packetThrottleDeceleration); - - return true; - } - - bool ENetHost::HandleVerifyConnect(ENetEvent* event, ENetPeer* peer, ENetProtocol* command) - { - if (peer->GetState() != ENetPeerState::Connecting) - return true; - - UInt32 channelCount = NetToHost(command->verifyConnect.channelCount); - - if (channelCount < ENetConstants::ENetProtocol_MinimumChannelCount || channelCount > ENetConstants::ENetProtocol_MaximumChannelCount || - NetToHost(command->verifyConnect.packetThrottleInterval) != peer->m_packetThrottleInterval || - NetToHost(command->verifyConnect.packetThrottleAcceleration) != peer->m_packetThrottleAcceleration || - NetToHost(command->verifyConnect.packetThrottleDeceleration) != peer->m_packetThrottleDeceleration || - command->verifyConnect.connectID != peer->m_connectID) - { - peer->m_eventData = 0; - - peer->DispatchState(ENetPeerState::Zombie); - - return false; - } - - peer->RemoveSentReliableCommand(1, 0xFF); - - if (channelCount < peer->m_channels.size()) - peer->m_channels.resize(channelCount); - - peer->m_outgoingPeerID = NetToHost(command->verifyConnect.outgoingPeerID); - peer->m_incomingSessionID = command->verifyConnect.incomingSessionID; - peer->m_outgoingSessionID = command->verifyConnect.outgoingSessionID; - - UInt32 mtu = Clamp(NetToHost(command->verifyConnect.mtu), ENetConstants::ENetProtocol_MinimumMTU, ENetConstants::ENetProtocol_MaximumMTU); - peer->m_mtu = std::min(peer->m_mtu, mtu); - - UInt32 windowSize = Clamp(NetToHost(command->verifyConnect.windowSize), ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); - peer->m_windowSize = std::min(peer->m_windowSize, windowSize); - - peer->m_incomingBandwidth = NetToHost(command->verifyConnect.incomingBandwidth); - peer->m_outgoingBandwidth = NetToHost(command->verifyConnect.outgoingBandwidth); - - NotifyConnect(peer, event); - return true; - } - int ENetHost::ReceiveIncomingCommands(ENetEvent* event) { for (unsigned int i = 0; i < 256; ++i) diff --git a/src/Nazara/Network/ENetPeer.cpp b/src/Nazara/Network/ENetPeer.cpp index d0181a01d..e90d77954 100644 --- a/src/Nazara/Network/ENetPeer.cpp +++ b/src/Nazara/Network/ENetPeer.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -469,6 +469,453 @@ namespace Nz channel.incomingUnreliableCommands.erase(channel.incomingUnreliableCommands.begin(), droppedCommand); } + bool ENetPeer::HandleAcknowledge(const ENetProtocol* command, ENetEvent* event) + { + if (m_state == ENetPeerState::Disconnected || m_state == ENetPeerState::Zombie) + return true; + + UInt32 serviceTime = m_host->m_serviceTime; + UInt32 receivedSentTime = NetToHost(command->acknowledge.receivedSentTime); + receivedSentTime |= serviceTime & 0xFFFF0000; + if ((receivedSentTime & 0x8000) > (serviceTime & 0x8000)) + receivedSentTime -= 0x10000; + + if (ENET_TIME_LESS(serviceTime, receivedSentTime)) + return true; + + m_lastReceiveTime = serviceTime; + m_earliestTimeout = 0; + + UInt32 roundTripTime = ENET_TIME_DIFFERENCE(serviceTime, receivedSentTime); + + Throttle(roundTripTime); + + m_roundTripTimeVariance -= m_roundTripTimeVariance / 4; + + if (roundTripTime >= m_roundTripTime) + { + m_roundTripTime += (roundTripTime - m_roundTripTime) / 8; + m_roundTripTimeVariance += (roundTripTime - m_roundTripTime) / 4; + } + else + { + m_roundTripTime -= (m_roundTripTime - roundTripTime) / 8; + m_roundTripTimeVariance += (m_roundTripTime - roundTripTime) / 4; + } + + m_lowestRoundTripTime = std::min(m_lowestRoundTripTime, m_roundTripTime); + m_highestRoundTripTimeVariance = std::max(m_highestRoundTripTimeVariance, m_roundTripTimeVariance); + + if (m_packetThrottleEpoch == 0 || ENET_TIME_DIFFERENCE(serviceTime, m_packetThrottleEpoch) >= m_packetThrottleInterval) + { + m_lastRoundTripTime = m_lowestRoundTripTime; + m_lastRoundTripTimeVariance = m_highestRoundTripTimeVariance; + m_lowestRoundTripTime = m_roundTripTime; + m_highestRoundTripTimeVariance = m_roundTripTimeVariance; + m_packetThrottleEpoch = serviceTime; + } + + UInt16 receivedReliableSequenceNumber = NetToHost(command->acknowledge.receivedReliableSequenceNumber); + + ENetProtocolCommand commandNumber = RemoveSentReliableCommand(receivedReliableSequenceNumber, command->header.channelID); + + switch (m_state) + { + case ENetPeerState::AcknowledgingConnect: + if (commandNumber != ENetProtocolCommand_VerifyConnect) + return false; + + m_host->NotifyConnect(this, event); + break; + + case ENetPeerState::Disconnecting: + if (commandNumber != ENetProtocolCommand_Disconnect) + return false; + + m_host->NotifyDisconnect(this, event); + break; + + case ENetPeerState::DisconnectLater: + if (!HasPendingCommands()) + Disconnect(m_eventData); + + break; + + default: + break; + } + + return true; + } + + bool ENetPeer::HandleBandwidthLimit(const ENetProtocol* command) + { + if (!IsConnected()) + return false; + + if (m_incomingBandwidth != 0) + --m_host->m_bandwidthLimitedPeers; + + m_incomingBandwidth = NetToHost(command->bandwidthLimit.incomingBandwidth); + m_outgoingBandwidth = NetToHost(command->bandwidthLimit.outgoingBandwidth); + + if (m_incomingBandwidth != 0) + ++m_host->m_bandwidthLimitedPeers; + + if (m_incomingBandwidth == 0 && m_host->m_outgoingBandwidth == 0) + m_windowSize = ENetConstants::ENetProtocol_MaximumWindowSize; + else + { + if (m_incomingBandwidth == 0 || m_host->m_outgoingBandwidth == 0) + m_windowSize = (std::max(m_incomingBandwidth, m_host->m_outgoingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; + else + m_windowSize = (std::min(m_incomingBandwidth, m_host->m_outgoingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; + + m_windowSize = Clamp(m_windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); + } + + return true; + } + + bool ENetPeer::HandleDisconnect(const ENetProtocol* command) + { + if (m_state == ENetPeerState::Disconnected || m_state == ENetPeerState::Zombie || m_state == ENetPeerState::AcknowledgingDisconnect) + return true; + + ResetQueues(); + + if (m_state == ENetPeerState::ConnectionSucceeded || m_state == ENetPeerState::Disconnecting || m_state == ENetPeerState::Connecting) + DispatchState(ENetPeerState::Zombie); + else + { + if (!IsConnected()) + { + if (m_state == ENetPeerState::ConnectionPending) + m_host->m_recalculateBandwidthLimits = true; + + Reset(); + } + else + if (command->header.command & ENetProtocolFlag_Acknowledge) + ChangeState(ENetPeerState::AcknowledgingDisconnect); + else + DispatchState(ENetPeerState::Zombie); + } + + if (m_state != ENetPeerState::Disconnected) + m_eventData = NetToHost(command->disconnect.data); + + return true; + } + + bool ENetPeer::HandlePing(const ENetProtocol* /*command*/) + { + if (!IsConnected()) + return false; + + return true; + } + + bool ENetPeer::HandleSendFragment(const ENetProtocol* command, UInt8** data) + { + if (command->header.channelID >= m_channels.size() || !IsConnected()) + return false; + + UInt16 fragmentLength = NetToHost(command->sendFragment.dataLength); + *data += fragmentLength; + if (fragmentLength >= m_host->m_maximumPacketSize || *data < m_host->m_receivedData || *data > &m_host->m_receivedData[m_host->m_receivedDataLength]) + return false; + + ENetPeer::Channel& channel = m_channels[command->header.channelID]; + UInt32 startSequenceNumber = NetToHost(command->sendFragment.startSequenceNumber); + UInt16 startWindow = startSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; + UInt16 currentWindow = channel.incomingReliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; + + if (startSequenceNumber < channel.incomingReliableSequenceNumber) + startWindow += ENetConstants::ENetPeer_ReliableWindows; + + if (startWindow < currentWindow || startWindow >= currentWindow + ENetConstants::ENetPeer_FreeReliableWindows - 1) + return true; + + UInt32 fragmentNumber = NetToHost(command->sendFragment.fragmentNumber); + UInt32 fragmentCount = NetToHost(command->sendFragment.fragmentCount); + UInt32 fragmentOffset = NetToHost(command->sendFragment.fragmentOffset); + UInt32 totalLength = NetToHost(command->sendFragment.totalLength); + + if (fragmentCount > ENetConstants::ENetProtocol_MaximumFragmentCount || fragmentNumber >= fragmentCount || totalLength > m_host->m_maximumPacketSize || + fragmentOffset >= totalLength || fragmentLength > totalLength - fragmentOffset) + return false; + + ENetPeer::IncomingCommmand* startCommand = nullptr; + for (auto currentCommand = channel.incomingReliableCommands.rbegin(); currentCommand != channel.incomingReliableCommands.rend(); ++currentCommand) + { + ENetPeer::IncomingCommmand& incomingCommand = *currentCommand; + + if (startSequenceNumber >= channel.incomingReliableSequenceNumber) + { + if (incomingCommand.reliableSequenceNumber < channel.incomingReliableSequenceNumber) + continue; + } + else if (incomingCommand.reliableSequenceNumber >= channel.incomingReliableSequenceNumber) + break; + + if (incomingCommand.reliableSequenceNumber <= startSequenceNumber) + { + if (incomingCommand.reliableSequenceNumber < startSequenceNumber) + break; + + if ((incomingCommand.command.header.command & ENetProtocolCommand_Mask) != ENetProtocolCommand_SendFragment || + totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.GetSize()) + return false; + + startCommand = &incomingCommand; + break; + } + } + + if (startCommand) + { + ENetProtocol hostCommand = *command; + hostCommand.header.reliableSequenceNumber = startSequenceNumber; + + if (!QueueIncomingCommand(hostCommand, nullptr, totalLength, ENetPacketFlag_Reliable, fragmentCount)) + return false; + } + + if (!startCommand->fragments.Test(fragmentNumber)) + { + --startCommand->fragmentsRemaining; + + startCommand->fragments.Set(fragmentNumber, true); + + if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) + fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; + + std::memcpy(startCommand->packet->data.GetData() + NetPacket::HeaderSize + fragmentOffset, reinterpret_cast(command) + sizeof(ENetProtocolSendFragment), fragmentLength); + + if (startCommand->fragmentsRemaining <= 0) + DispatchIncomingReliableCommands(channel); + } + + return false; + } + + bool ENetPeer::HandleSendReliable(const ENetProtocol* command, UInt8** data) + { + if (command->header.channelID >= m_channels.size() || !IsConnected()) + return false; + + UInt16 dataLength = NetToHost(command->sendReliable.dataLength); + *data += dataLength; + if (dataLength >= m_host->m_maximumPacketSize || *data < m_host->m_receivedData || *data > &m_host->m_receivedData[m_host->m_receivedDataLength]) + return false; + + if (!QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendReliable), dataLength, ENetPacketFlag_Reliable, 0)) + return false; + + return true; + } + + bool ENetPeer::HandleSendUnreliable(const ENetProtocol* command, UInt8** data) + { + if (command->header.channelID >= m_channels.size() || !IsConnected()) + return false; + + UInt16 dataLength = NetToHost(command->sendUnreliable.dataLength); + *data += dataLength; + if (dataLength >= m_host->m_maximumPacketSize || *data < m_host->m_receivedData || *data > &m_host->m_receivedData[m_host->m_receivedDataLength]) + return false; + + if (!QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendUnreliable), dataLength, 0, 0)) + return false; + + return true; + } + + bool ENetPeer::HandleSendUnreliableFragment(const ENetProtocol* command, UInt8** data) + { + if (command->header.channelID >= m_channels.size() || !IsConnected()) + return false; + + UInt16 fragmentLength = NetToHost(command->sendFragment.dataLength); + *data += fragmentLength; + if (fragmentLength >= m_host->m_maximumPacketSize || *data < m_host->m_receivedData || *data > &m_host->m_receivedData[m_host->m_receivedDataLength]) + return false; + + ENetPeer::Channel& channel = m_channels[command->header.channelID]; + UInt32 reliableSequenceNumber = command->header.reliableSequenceNumber; + UInt32 startSequenceNumber = NetToHost(command->sendFragment.startSequenceNumber); + + UInt16 reliableWindow = reliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; + UInt16 currentWindow = channel.incomingReliableSequenceNumber / ENetConstants::ENetPeer_ReliableWindowSize; + + if (startSequenceNumber < channel.incomingReliableSequenceNumber) + reliableWindow += ENetConstants::ENetPeer_ReliableWindows; + + if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENetConstants::ENetPeer_FreeReliableWindows - 1) + return true; + + if (reliableSequenceNumber == channel.incomingReliableSequenceNumber && startSequenceNumber <= channel.incomingUnreliableSequenceNumber) + return true; + + UInt32 fragmentNumber = NetToHost(command->sendFragment.fragmentNumber); + UInt32 fragmentCount = NetToHost(command->sendFragment.fragmentCount); + UInt32 fragmentOffset = NetToHost(command->sendFragment.fragmentOffset); + UInt32 totalLength = NetToHost(command->sendFragment.totalLength); + + if (fragmentCount > ENetConstants::ENetProtocol_MaximumFragmentCount || fragmentNumber >= fragmentCount || totalLength > m_host->m_maximumPacketSize || + fragmentOffset >= totalLength || fragmentLength > totalLength - fragmentOffset) + return false; + + ENetPeer::IncomingCommmand* startCommand = nullptr; + for (auto currentCommand = channel.incomingUnreliableCommands.rbegin(); currentCommand != channel.incomingUnreliableCommands.rend(); ++currentCommand) + { + ENetPeer::IncomingCommmand& incomingCommand = *currentCommand; + + if (startSequenceNumber >= channel.incomingReliableSequenceNumber) + { + if (incomingCommand.reliableSequenceNumber < channel.incomingReliableSequenceNumber) + continue; + } + else if (incomingCommand.reliableSequenceNumber >= channel.incomingReliableSequenceNumber) + break; + + if (incomingCommand.reliableSequenceNumber < reliableSequenceNumber) + break; + + if (incomingCommand.reliableSequenceNumber > reliableSequenceNumber) + continue; + + if (incomingCommand.unreliableSequenceNumber <= startSequenceNumber) + { + if (incomingCommand.unreliableSequenceNumber < startSequenceNumber) + break; + + if ((incomingCommand.command.header.command & ENetProtocolCommand_Mask) != ENetProtocolCommand_SendUnreliableFragment || + totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.GetSize()) + return false; + + startCommand = &incomingCommand; + break; + } + } + + if (startCommand) + { + if (!QueueIncomingCommand(*command, nullptr, totalLength, ENetPacketFlag_UnreliableFragment, fragmentCount)) + return false; + } + + if (!startCommand->fragments.Test(fragmentNumber)) + { + --startCommand->fragmentsRemaining; + + startCommand->fragments.Set(fragmentNumber, true); + + if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) + fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; + + std::memcpy(startCommand->packet->data.GetData() + NetPacket::HeaderSize + fragmentOffset, reinterpret_cast(command) + sizeof(ENetProtocolSendFragment), fragmentLength); + + if (startCommand->fragmentsRemaining <= 0) + DispatchIncomingUnreliableCommands(channel); + } + + return true; + } + + bool ENetPeer::HandleSendUnsequenced(const ENetProtocol* command, UInt8** data) + { + if (command->header.channelID >= m_channels.size() || !IsConnected()) + return false; + + std::size_t dataLength = NetToHost(command->sendUnsequenced.dataLength); + *data += dataLength; + if (dataLength >= m_host->m_maximumPacketSize || *data < m_host->m_receivedData || *data > &m_host->m_receivedData[m_host->m_receivedDataLength]) + return false; + + UInt32 unsequencedGroup = NetToHost(command->sendUnsequenced.unsequencedGroup); + UInt32 index = unsequencedGroup % ENetConstants::ENetPeer_UnsequencedWindowSize; + + if (unsequencedGroup < m_incomingUnsequencedGroup) + unsequencedGroup += 0x10000; + + if (unsequencedGroup >= static_cast(m_incomingUnsequencedGroup) + ENetConstants::ENetPeer_UnsequencedWindows * ENetConstants::ENetPeer_UnsequencedWindowSize) + return true; + + unsequencedGroup &= 0xFFFF; + + if (unsequencedGroup - index != m_incomingUnsequencedGroup) + { + m_incomingUnsequencedGroup = unsequencedGroup - index; + + m_unsequencedWindow.fill(0); + } + else if (m_unsequencedWindow[index / 32] & (1 << (index % 32))) + return true; + + if (!QueueIncomingCommand(*command, reinterpret_cast(command) + sizeof(ENetProtocolSendUnsequenced), dataLength, ENetPacketFlag_Unsequenced, 0)) + return false; + + m_unsequencedWindow[index / 32] |= 1 << (index % 32); + + return true; + } + + bool ENetPeer::HandleThrottleConfigure(const ENetProtocol* command) + { + if (!IsConnected()) + return false; + + m_packetThrottleInterval = NetToHost(command->throttleConfigure.packetThrottleInterval); + m_packetThrottleAcceleration = NetToHost(command->throttleConfigure.packetThrottleAcceleration); + m_packetThrottleDeceleration = NetToHost(command->throttleConfigure.packetThrottleDeceleration); + + return true; + } + + bool ENetPeer::HandleVerifyConnect(const ENetProtocol* command, ENetEvent* event) + { + if (m_state != ENetPeerState::Connecting) + return true; + + UInt32 channelCount = NetToHost(command->verifyConnect.channelCount); + + if (channelCount < ENetConstants::ENetProtocol_MinimumChannelCount || channelCount > ENetConstants::ENetProtocol_MaximumChannelCount || + NetToHost(command->verifyConnect.packetThrottleInterval) != m_packetThrottleInterval || + NetToHost(command->verifyConnect.packetThrottleAcceleration) != m_packetThrottleAcceleration || + NetToHost(command->verifyConnect.packetThrottleDeceleration) != m_packetThrottleDeceleration || + command->verifyConnect.connectID != m_connectID) + { + m_eventData = 0; + + DispatchState(ENetPeerState::Zombie); + + return false; + } + + RemoveSentReliableCommand(1, 0xFF); + + if (channelCount < m_channels.size()) + m_channels.resize(channelCount); + + m_outgoingPeerID = NetToHost(command->verifyConnect.outgoingPeerID); + m_incomingSessionID = command->verifyConnect.incomingSessionID; + m_outgoingSessionID = command->verifyConnect.outgoingSessionID; + + UInt32 mtu = Clamp(NetToHost(command->verifyConnect.mtu), ENetConstants::ENetProtocol_MinimumMTU, ENetConstants::ENetProtocol_MaximumMTU); + m_mtu = std::min(m_mtu, mtu); + + UInt32 windowSize = Clamp(NetToHost(command->verifyConnect.windowSize), ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); + m_windowSize = std::min(m_windowSize, windowSize); + + m_incomingBandwidth = NetToHost(command->verifyConnect.incomingBandwidth); + m_outgoingBandwidth = NetToHost(command->verifyConnect.outgoingBandwidth); + + m_host->NotifyConnect(this, event); + return true; + } + void ENetPeer::InitIncoming(std::size_t channelCount, const IpAddress& address, ENetProtocolConnect& incomingCommand) { m_channels.resize(channelCount);