diff --git a/include/Nazara/Network/ENetHost.hpp b/include/Nazara/Network/ENetHost.hpp index 3b86a1f25..344ffce82 100644 --- a/include/Nazara/Network/ENetHost.hpp +++ b/include/Nazara/Network/ENetHost.hpp @@ -64,8 +64,6 @@ namespace Nz void AddToDispatchQueue(ENetPeer* peer); void RemoveFromDispatchQueue(ENetPeer* peer); - bool CheckTimeouts(ENetPeer* peer, ENetEvent* event); - bool DispatchIncomingCommands(ENetEvent* event); bool HandleAcknowledge(ENetEvent* event, ENetPeer* peer, const ENetProtocol* command); diff --git a/include/Nazara/Network/ENetPeer.hpp b/include/Nazara/Network/ENetPeer.hpp index 377d8f734..7ccaf3d8d 100644 --- a/include/Nazara/Network/ENetPeer.hpp +++ b/include/Nazara/Network/ENetPeer.hpp @@ -68,8 +68,10 @@ namespace Nz struct IncomingCommmand; struct OutgoingCommand; - // Protocol functions inline void ChangeState(ENetPeerState state); + + bool CheckTimeouts(ENetEvent* event); + void DispatchState(ENetPeerState state); void DispatchIncomingReliableCommands(Channel& channel); @@ -85,6 +87,7 @@ namespace Nz 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); diff --git a/include/Nazara/Network/ENetPeer.inl b/include/Nazara/Network/ENetPeer.inl index 5c0f76731..1e74e0cae 100644 --- a/include/Nazara/Network/ENetPeer.inl +++ b/include/Nazara/Network/ENetPeer.inl @@ -37,6 +37,11 @@ namespace Nz m_state = state; } + + inline void ENetPeer::QueueOutgoingCommand(ENetProtocol& command) + { + QueueOutgoingCommand(command, ENetPacketRef(), 0, 0); + } } #include diff --git a/include/Nazara/Network/ENetProtocol.hpp b/include/Nazara/Network/ENetProtocol.hpp index 8b62f7dc7..0434cafc2 100644 --- a/include/Nazara/Network/ENetProtocol.hpp +++ b/include/Nazara/Network/ENetProtocol.hpp @@ -267,6 +267,14 @@ namespace Nz union NAZARA_PACKED ENetProtocol { + ENetProtocol() = default; + + ENetProtocol(UInt8 command, UInt8 channel) + { + header.command = command; + header.channelID = channel; + } + ENetProtocolCommandHeader header; ENetProtocolAcknowledge acknowledge; ENetProtocolBandwidthLimit bandwidthLimit; diff --git a/src/Nazara/Network/ENetHost.cpp b/src/Nazara/Network/ENetHost.cpp index a6e98a0c4..afa870b12 100644 --- a/src/Nazara/Network/ENetHost.cpp +++ b/src/Nazara/Network/ENetHost.cpp @@ -117,10 +117,7 @@ namespace Nz ENetPeer& peer = m_peers[peerId]; peer.InitOutgoing(channelCount, remoteAddress, ++m_randomSeed, windowSize); - ENetProtocol command; - command.header.command = ENetProtocolCommand_Connect | ENetProtocolFlag_Acknowledge; - command.header.channelID = 0xFF; - + ENetProtocol command(ENetProtocolCommand_Connect | ENetProtocolFlag_Acknowledge, 0xFF); command.connect.channelCount = HostToNet(static_cast(channelCount)); command.connect.connectID = peer.m_connectID; command.connect.data = HostToNet(data); @@ -134,8 +131,7 @@ namespace Nz command.connect.packetThrottleDeceleration = HostToNet(peer.m_packetThrottleDeceleration); command.connect.packetThrottleInterval = HostToNet(peer.m_packetThrottleInterval); command.connect.windowSize = HostToNet(peer.m_windowSize); - - peer.QueueOutgoingCommand(command, nullptr, 0, 0); + peer.QueueOutgoingCommand(command); return &peer; } @@ -350,52 +346,6 @@ namespace Nz m_dispatchQueue.UnboundedReset(peer->m_incomingPeerID); } - bool ENetHost::CheckTimeouts(ENetPeer* peer, ENetEvent* event) - { - auto currentCommand = peer->m_sentReliableCommands.begin(); - - while (currentCommand != peer->m_sentReliableCommands.end()) - { - auto outgoingCommand = currentCommand; - - ++currentCommand; - - if (ENET_TIME_DIFFERENCE(m_serviceTime, outgoingCommand->sentTime) < outgoingCommand->roundTripTimeout) - continue; - - if (peer->m_earliestTimeout == 0 || ENET_TIME_LESS(outgoingCommand->sentTime, peer->m_earliestTimeout)) - peer->m_earliestTimeout = outgoingCommand->sentTime; - - if (peer->m_earliestTimeout != 0 && (ENET_TIME_DIFFERENCE(m_serviceTime, peer->m_earliestTimeout) >= peer->m_timeoutMaximum || - (outgoingCommand->roundTripTimeout >= outgoingCommand->roundTripTimeoutLimit && ENET_TIME_DIFFERENCE(m_serviceTime, peer->m_earliestTimeout) >= peer->m_timeoutMinimum))) - { - NotifyDisconnect(peer, event); - return true; - } - - if (outgoingCommand->packet) - peer->m_reliableDataInTransit -= outgoingCommand->fragmentLength; - - ++peer->m_packetsLost; - - outgoingCommand->roundTripTimeout *= 2; - - peer->m_outgoingReliableCommands.emplace_front(std::move(*outgoingCommand)); - peer->m_sentReliableCommands.erase(outgoingCommand); - - // Okay this should just never procs, I don't see how it would be possible - /*if (currentCommand == enet_list_begin(&peer->sentReliableCommands) && - !enet_list_empty(&peer->sentReliableCommands)) - { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - - peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; - }*/ - } - - return false; - } - bool ENetHost::DispatchIncomingCommands(ENetEvent* event) { for (std::size_t bit = m_dispatchQueue.FindFirst(); bit != m_dispatchQueue.npos; bit = m_dispatchQueue.FindNext(bit)) @@ -608,9 +558,7 @@ namespace Nz windowSize = std::max(windowSize, NetToHost(command->connect.windowSize)); windowSize = Clamp(windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); - ENetProtocol verifyCommand; - verifyCommand.header.command = ENetProtocolCommand_VerifyConnect | ENetProtocolFlag_Acknowledge; - verifyCommand.header.channelID = 0xFF; + ENetProtocol verifyCommand(ENetProtocolCommand_VerifyConnect | ENetProtocolFlag_Acknowledge, 0xFF); verifyCommand.verifyConnect.outgoingPeerID = HostToNet(peer->m_incomingPeerID); verifyCommand.verifyConnect.incomingSessionID = peer->m_outgoingSessionID; verifyCommand.verifyConnect.outgoingSessionID = peer->m_incomingSessionID; @@ -623,8 +571,7 @@ namespace Nz verifyCommand.verifyConnect.packetThrottleAcceleration = HostToNet(peer->m_packetThrottleAcceleration); verifyCommand.verifyConnect.packetThrottleDeceleration = HostToNet(peer->m_packetThrottleDeceleration); verifyCommand.verifyConnect.connectID = peer->m_connectID; - - peer->QueueOutgoingCommand(verifyCommand, nullptr, 0, 0); + peer->QueueOutgoingCommand(verifyCommand); return peer; } @@ -930,7 +877,7 @@ namespace Nz { --startCommand->fragmentsRemaining; - startCommand->fragments.Set(fragmentNumber); + startCommand->fragments.Set(fragmentNumber, true); if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; @@ -1036,7 +983,7 @@ namespace Nz break; if ((incomingCommand.command.header.command & ENetProtocolCommand_Mask) != ENetProtocolCommand_SendUnreliableFragment || - totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.size()) + totalLength != incomingCommand.packet->data.GetDataSize() || fragmentCount != incomingCommand.fragments.GetSize()) return false; startCommand = &incomingCommand; @@ -1054,7 +1001,7 @@ namespace Nz { --startCommand->fragmentsRemaining; - startCommand->fragments.Set(fragmentNumber); + startCommand->fragments.Set(fragmentNumber, true); if (fragmentOffset + fragmentLength > startCommand->packet->data.GetDataSize()) fragmentLength = startCommand->packet->data.GetDataSize() - fragmentOffset; @@ -1405,8 +1352,7 @@ namespace Nz if (!currentPeer->m_acknowledgements.empty()) SendAcknowledgements(currentPeer); - if (checkForTimeouts && !currentPeer->m_sentReliableCommands.empty() && ENET_TIME_GREATER_EQUAL(m_serviceTime, currentPeer->m_nextTimeout) && - CheckTimeouts(currentPeer, event)) + if (checkForTimeouts && !currentPeer->m_sentReliableCommands.empty() && ENET_TIME_GREATER_EQUAL(m_serviceTime, currentPeer->m_nextTimeout) && currentPeer->CheckTimeouts(event)) { if (event && event->type != ENetEventType::None) return 1; @@ -1617,14 +1563,7 @@ namespace Nz if ((throttle * peer.m_outgoingDataTotal) / ENetConstants::ENetPeer_PacketThrottleScale <= peerBandwidth) continue; - peer.m_packetThrottleLimit = (peerBandwidth * ENetConstants::ENetPeer_PacketThrottleScale) / peer.m_outgoingDataTotal; - - if (peer.m_packetThrottleLimit == 0) - peer.m_packetThrottleLimit = 1; - - if (peer.m_packetThrottle > peer.m_packetThrottleLimit) - peer.m_packetThrottle = peer.m_packetThrottleLimit; - + peer.m_packetThrottleLimit = Clamp((peerBandwidth * ENetConstants::ENetPeer_PacketThrottleScale) / peer.m_outgoingDataTotal, 0, peer.m_packetThrottleLimit); peer.m_outgoingBandwidthThrottleEpoch = currentTime; peer.m_incomingDataTotal = 0; @@ -1650,9 +1589,7 @@ namespace Nz continue; peer.m_packetThrottleLimit = throttle; - - if (peer.m_packetThrottle > peer.m_packetThrottleLimit) - peer.m_packetThrottle = peer.m_packetThrottleLimit; + peer.m_packetThrottle = std::min(peer.m_packetThrottle, peer.m_packetThrottleLimit); peer.m_incomingDataTotal = 0; peer.m_outgoingDataTotal = 0; @@ -1698,9 +1635,7 @@ namespace Nz if (!peer.IsConnected()) continue; - ENetProtocol command; - command.header.command = ENetProtocolCommand_BandwidthLimit | ENetProtocolFlag_Acknowledge; - command.header.channelID = 0xFF; + ENetProtocol command(ENetProtocolCommand_BandwidthLimit | ENetProtocolFlag_Acknowledge, 0xFF); command.bandwidthLimit.outgoingBandwidth = HostToNet(m_outgoingBandwidth); if (peer.m_incomingBandwidthThrottleEpoch == currentTime) @@ -1708,7 +1643,7 @@ namespace Nz else command.bandwidthLimit.incomingBandwidth = HostToNet(bandwidthLimit); - peer.QueueOutgoingCommand(command, nullptr, 0, 0); + peer.QueueOutgoingCommand(command); } } } diff --git a/src/Nazara/Network/ENetPeer.cpp b/src/Nazara/Network/ENetPeer.cpp index 38025108f..e444a4d02 100644 --- a/src/Nazara/Network/ENetPeer.cpp +++ b/src/Nazara/Network/ENetPeer.cpp @@ -5,6 +5,15 @@ #include #include +#define ENET_TIME_OVERFLOW 86400000 + +#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) +#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) +#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) +#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) + +#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) + namespace Nz { /// Temporary @@ -49,9 +58,7 @@ namespace Nz ResetQueues(); - ENetProtocol command; - command.header.command = ENetProtocolCommand_Disconnect; - command.header.channelID = 0xFF; + ENetProtocol command(ENetProtocolCommand_Disconnect, 0xFF); command.disconnect.data = HostToNet(data); if (IsConnected()) @@ -59,7 +66,7 @@ namespace Nz else command.header.command |= ENetProtocolFlag_Unsequenced; - QueueOutgoingCommand(command, nullptr, 0, 0); + QueueOutgoingCommand(command); if (IsConnected()) { @@ -95,12 +102,9 @@ namespace Nz { ResetQueues(); - ENetProtocol command; - command.header.command = ENetProtocolCommand_Disconnect | ENetProtocolFlag_Unsequenced; - command.header.channelID = 0xFF; + ENetProtocol command(ENetProtocolCommand_Disconnect | ENetProtocolFlag_Unsequenced, 0xFF); command.disconnect.data = HostToNet(data); - - QueueOutgoingCommand(command, nullptr, 0, 0); + QueueOutgoingCommand(command); m_host->Flush(); } @@ -116,8 +120,7 @@ namespace Nz ENetProtocol command; command.header.command = ENetProtocolCommand_Ping | ENetProtocolFlag_Acknowledge; command.header.channelID = 0xFF; - - QueueOutgoingCommand(command, nullptr, 0, 0); + QueueOutgoingCommand(command); } bool ENetPeer::Receive(ENetPacketRef* packet, UInt8* channelId) @@ -299,66 +302,56 @@ namespace Nz m_packetThrottleAcceleration = acceleration; m_packetThrottleDeceleration = deceleration; - ENetProtocol command; - command.header.command = ENetProtocolCommand_ThrottleConfigure | ENetProtocolFlag_Acknowledge; - command.header.channelID = 0xFF; - + ENetProtocol command(ENetProtocolCommand_ThrottleConfigure | ENetProtocolFlag_Acknowledge, 0xFF); command.throttleConfigure.packetThrottleInterval = HostToNet(interval); command.throttleConfigure.packetThrottleAcceleration = HostToNet(acceleration); command.throttleConfigure.packetThrottleDeceleration = HostToNet(deceleration); - - QueueOutgoingCommand(command, nullptr, 0, 0); + QueueOutgoingCommand(command); } - void ENetPeer::InitIncoming(std::size_t channelCount, const IpAddress& address, ENetProtocolConnect& incomingCommand) + bool ENetPeer::CheckTimeouts(ENetEvent* event) { - m_channels.resize(channelCount); - m_address = address; + auto currentCommand = m_sentReliableCommands.begin(); + while (currentCommand != m_sentReliableCommands.end()) + { + auto outgoingCommand = currentCommand; - m_connectID = incomingCommand.connectID; - m_eventData = NetToHost(incomingCommand.data); - m_incomingBandwidth = NetToHost(incomingCommand.incomingBandwidth); - m_outgoingBandwidth = NetToHost(incomingCommand.outgoingBandwidth); - m_packetThrottleInterval = NetToHost(incomingCommand.packetThrottleInterval); - m_packetThrottleAcceleration = NetToHost(incomingCommand.packetThrottleAcceleration); - m_packetThrottleDeceleration = NetToHost(incomingCommand.packetThrottleDeceleration); - m_outgoingPeerID = NetToHost(incomingCommand.outgoingPeerID); - m_state = ENetPeerState::AcknowledgingConnect; + ++currentCommand; - UInt8 incomingSessionId, outgoingSessionId; + if (ENET_TIME_DIFFERENCE(m_host->m_serviceTime, outgoingCommand->sentTime) < outgoingCommand->roundTripTimeout) + continue; - incomingSessionId = incomingCommand.incomingSessionID == 0xFF ? m_outgoingSessionID : incomingCommand.incomingSessionID; - incomingSessionId = (incomingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); - if (incomingSessionId == m_outgoingSessionID) - incomingSessionId = (incomingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); - m_outgoingSessionID = incomingSessionId; + if (m_earliestTimeout == 0 || ENET_TIME_LESS(outgoingCommand->sentTime, m_earliestTimeout)) + m_earliestTimeout = outgoingCommand->sentTime; - outgoingSessionId = incomingCommand.outgoingSessionID == 0xFF ? m_incomingSessionID : incomingCommand.outgoingSessionID; - outgoingSessionId = (outgoingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); - if (outgoingSessionId == m_incomingSessionID) - outgoingSessionId = (outgoingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); - m_incomingSessionID = outgoingSessionId; + if (m_earliestTimeout != 0 && (ENET_TIME_DIFFERENCE(m_host->m_serviceTime, m_earliestTimeout) >= m_timeoutMaximum || + (outgoingCommand->roundTripTimeout >= outgoingCommand->roundTripTimeoutLimit && ENET_TIME_DIFFERENCE(m_host->m_serviceTime, m_earliestTimeout) >= m_timeoutMinimum))) + { + m_host->NotifyDisconnect(this, event); + return true; + } - m_mtu = Clamp(NetToHost(incomingCommand.mtu), ENetConstants::ENetProtocol_MinimumMTU, ENetConstants::ENetProtocol_MaximumMTU); + if (outgoingCommand->packet) + m_reliableDataInTransit -= outgoingCommand->fragmentLength; - if (m_host->m_outgoingBandwidth == 0 && m_incomingBandwidth == 0) - m_windowSize = ENetConstants::ENetProtocol_MaximumWindowSize; - else if (m_host->m_outgoingBandwidth == 0 || m_incomingBandwidth == 0) - m_windowSize = (std::max(m_host->m_outgoingBandwidth, m_incomingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; - else - m_windowSize = (std::min(m_host->m_outgoingBandwidth, m_incomingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; + ++m_packetsLost; - m_windowSize = Clamp(m_windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); - } + outgoingCommand->roundTripTimeout *= 2; - void ENetPeer::InitOutgoing(std::size_t channelCount, const IpAddress& address, UInt32 connectId, UInt32 windowSize) - { - m_channels.resize(channelCount); + m_outgoingReliableCommands.emplace_front(std::move(*outgoingCommand)); + m_sentReliableCommands.erase(outgoingCommand); - m_address = address; - m_connectID = connectId; - m_state = ENetPeerState::Connecting; - m_windowSize = Clamp(windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); + // Okay this should just never procs, I don't see how it would be possible + /*if (currentCommand == enet_list_begin(&peer->sentReliableCommands) && + !enet_list_empty(&peer->sentReliableCommands)) + { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + + peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; + }*/ + } + + return false; } void ENetPeer::DispatchState(ENetPeerState state) @@ -472,6 +465,57 @@ namespace Nz channel.incomingUnreliableCommands.erase(channel.incomingUnreliableCommands.begin(), droppedCommand); } + void ENetPeer::InitIncoming(std::size_t channelCount, const IpAddress& address, ENetProtocolConnect& incomingCommand) + { + m_channels.resize(channelCount); + m_address = address; + + m_connectID = incomingCommand.connectID; + m_eventData = NetToHost(incomingCommand.data); + m_incomingBandwidth = NetToHost(incomingCommand.incomingBandwidth); + m_outgoingBandwidth = NetToHost(incomingCommand.outgoingBandwidth); + m_packetThrottleInterval = NetToHost(incomingCommand.packetThrottleInterval); + m_packetThrottleAcceleration = NetToHost(incomingCommand.packetThrottleAcceleration); + m_packetThrottleDeceleration = NetToHost(incomingCommand.packetThrottleDeceleration); + m_outgoingPeerID = NetToHost(incomingCommand.outgoingPeerID); + m_state = ENetPeerState::AcknowledgingConnect; + + UInt8 incomingSessionId, outgoingSessionId; + + incomingSessionId = incomingCommand.incomingSessionID == 0xFF ? m_outgoingSessionID : incomingCommand.incomingSessionID; + incomingSessionId = (incomingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); + if (incomingSessionId == m_outgoingSessionID) + incomingSessionId = (incomingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); + m_outgoingSessionID = incomingSessionId; + + outgoingSessionId = incomingCommand.outgoingSessionID == 0xFF ? m_incomingSessionID : incomingCommand.outgoingSessionID; + outgoingSessionId = (outgoingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); + if (outgoingSessionId == m_incomingSessionID) + outgoingSessionId = (outgoingSessionId + 1) & (ENetProtocolHeaderSessionMask >> ENetProtocolHeaderSessionShift); + m_incomingSessionID = outgoingSessionId; + + m_mtu = Clamp(NetToHost(incomingCommand.mtu), ENetConstants::ENetProtocol_MinimumMTU, ENetConstants::ENetProtocol_MaximumMTU); + + if (m_host->m_outgoingBandwidth == 0 && m_incomingBandwidth == 0) + m_windowSize = ENetConstants::ENetProtocol_MaximumWindowSize; + else if (m_host->m_outgoingBandwidth == 0 || m_incomingBandwidth == 0) + m_windowSize = (std::max(m_host->m_outgoingBandwidth, m_incomingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; + else + m_windowSize = (std::min(m_host->m_outgoingBandwidth, m_incomingBandwidth) / ENetConstants::ENetPeer_WindowSizeScale) * ENetConstants::ENetProtocol_MinimumWindowSize; + + m_windowSize = Clamp(m_windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); + } + + void ENetPeer::InitOutgoing(std::size_t channelCount, const IpAddress& address, UInt32 connectId, UInt32 windowSize) + { + m_channels.resize(channelCount); + + m_address = address; + m_connectID = connectId; + m_state = ENetPeerState::Connecting; + m_windowSize = Clamp(windowSize, ENetConstants::ENetProtocol_MinimumWindowSize, ENetConstants::ENetProtocol_MaximumWindowSize); + } + void ENetPeer::OnConnect() { if (!IsConnected()) @@ -498,7 +542,7 @@ namespace Nz { std::list* commandList = nullptr; - bool found = true; + bool found = false; auto currentCommand = m_sentReliableCommands.begin(); commandList = &m_sentReliableCommands; for (; currentCommand != m_sentReliableCommands.end(); ++currentCommand)