Move packet dispatch to return an enum that includes a pending option
Signed-off-by: puvvadar <puvvadar@amazon.com>
This commit is contained in:
@@ -16,7 +16,7 @@ namespace {{ xml.attrib['Name'] }}
|
||||
//! @param handler the handler used to handle the received packet
|
||||
//! @return boolean true on successful dispatch, false if the request was not handled
|
||||
template <typename HANDLER>
|
||||
bool DispatchPacket(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer, HANDLER& handler);
|
||||
AzNetworking::PacketDispatchResult DispatchPacket(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer, HANDLER& handler);
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
namespace {{ xml.attrib['Name'] }}
|
||||
{
|
||||
template <typename HANDLER>
|
||||
inline bool DispatchPacket(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer, HANDLER& handler)
|
||||
inline AzNetworking::PacketDispatchResult DispatchPacket(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer, HANDLER& handler)
|
||||
{
|
||||
switch (aznumeric_cast<int32_t>(packetHeader.GetPacketType()))
|
||||
{
|
||||
@@ -10,16 +10,26 @@ namespace {{ xml.attrib['Name'] }}
|
||||
case aznumeric_cast<int32_t>({{ Packet.attrib['Name'] }}::Type):
|
||||
{
|
||||
AZLOG(Debug_DispatchPackets, "Received packet %s", "{{ Packet.attrib['Name'] }}");
|
||||
{% if ('HandshakePacket' not in Packet.attrib) or (Packet.attrib['HandshakePacket'] == 'false') %}
|
||||
if (!handler.IsHandshakeComplete())
|
||||
{
|
||||
return AzNetworking::PacketDispatchResult::Pending;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{{ Packet.attrib['Name'] }} packet;
|
||||
if (!serializer.Serialize(packet, "Packet"))
|
||||
{
|
||||
return false;
|
||||
return AzNetworking::PacketDispatchResult::Failure;
|
||||
}
|
||||
if(handler.HandleRequest(connection, packetHeader, packet))
|
||||
{
|
||||
return AzNetworking::PacketDispatchResult::Success;
|
||||
}
|
||||
return handler.HandleRequest(connection, packetHeader, packet);
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
return false;
|
||||
return AzNetworking::PacketDispatchResult::Failure;
|
||||
}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace AzNetworking
|
||||
//! @param connection pointer to the connection instance generating the event
|
||||
//! @param packetHeader packet header of the associated payload
|
||||
//! @param serializer serializer instance containing the transmitted payload
|
||||
//! @return boolean true to signal success, false to disconnect with a transport error
|
||||
virtual bool OnPacketReceived(IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer) = 0;
|
||||
//! @return PacketDispatchResult result of the packet handling attempt
|
||||
virtual PacketDispatchResult OnPacketReceived(IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer) = 0;
|
||||
|
||||
//! Called when a packet is deemed lost by the remote connection.
|
||||
//! @param connection pointer to the connection instance generating the event
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
AZ_ENUM_CLASS(PacketDispatchResult
|
||||
, Success
|
||||
, Pending
|
||||
, Failure
|
||||
);
|
||||
|
||||
AZ_ENUM_CLASS(PacketFlag
|
||||
, Compressed
|
||||
, MAX
|
||||
|
||||
@@ -236,14 +236,14 @@ namespace AzNetworking
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpConnection::HandleCorePacket(IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer)
|
||||
PacketDispatchResult UdpConnection::HandleCorePacket(IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer)
|
||||
{
|
||||
switch (static_cast<CorePackets::PacketType>(header.GetPacketType()))
|
||||
{
|
||||
case CorePackets::PacketType::InitiateConnectionPacket:
|
||||
{
|
||||
AZLOG(NET_CorePackets, "Received core packet %s", "InitiateConnection");
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -253,7 +253,7 @@ namespace AzNetworking
|
||||
CorePackets::ConnectionHandshakePacket packet;
|
||||
if (!serializer.Serialize(packet, "Packet"))
|
||||
{
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
if (m_state != ConnectionState::Connected)
|
||||
@@ -264,7 +264,7 @@ namespace AzNetworking
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -274,10 +274,10 @@ namespace AzNetworking
|
||||
CorePackets::TerminateConnectionPacket packet;
|
||||
if (!serializer.Serialize(packet, "Packet"))
|
||||
{
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
Disconnect(packet.GetDisconnectReason(), TerminationEndpoint::Remote);
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -287,10 +287,10 @@ namespace AzNetworking
|
||||
CorePackets::HeartbeatPacket packet;
|
||||
if (!serializer.Serialize(packet, "Packet"))
|
||||
{
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
// Do nothing, we've already processed our ack packets
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -302,6 +302,6 @@ namespace AzNetworking
|
||||
AZ_Assert(false, "Unhandled core packet type!");
|
||||
}
|
||||
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace AzNetworking
|
||||
//! @param header the packet header received to process
|
||||
//! @param serializer the output serializer containing the transmitted packet data
|
||||
//! @return boolean true on successful handling of the received header
|
||||
bool HandleCorePacket(IConnectionListener& listener, UdpPacketHeader& header, ISerializer& serializer);
|
||||
PacketDispatchResult HandleCorePacket(IConnectionListener& listener, UdpPacketHeader& header, ISerializer& serializer);
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(UdpConnection);
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ namespace AzNetworking
|
||||
return m_sequenceGenerator.GetNextSequenceId();
|
||||
}
|
||||
|
||||
bool UdpFragmentQueue::ProcessReceivedChunk(UdpConnection* connection, IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer)
|
||||
PacketDispatchResult UdpFragmentQueue::ProcessReceivedChunk(UdpConnection* connection, IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer)
|
||||
{
|
||||
AZStd::unique_ptr<CorePackets::FragmentedPacket> packet = AZStd::make_unique<CorePackets::FragmentedPacket>();
|
||||
|
||||
if (!serializer.Serialize(*packet, "Packet"))
|
||||
{
|
||||
AZLOG(NET_FragmentQueue, "Fragment failed serialization");
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
const bool isReliable = header.GetIsReliable();
|
||||
@@ -63,14 +63,14 @@ namespace AzNetworking
|
||||
{
|
||||
// Too old to process
|
||||
AZLOG(NET_FragmentQueue, "Fragment sequence ID is outside our tracked window");
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
if (m_deliveredFragments.GetBit(static_cast<uint32_t>(sequenceDelta)))
|
||||
{
|
||||
// Received packet is a duplicate of one already forwarded to gameplay
|
||||
AZLOG(NET_FragmentQueue, "Received duplicate of fragmented packet %u, discarding", static_cast<uint32_t>(fragmentSequence));
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
|
||||
const uint32_t chunkCount = packet->GetChunkCount();
|
||||
@@ -89,7 +89,7 @@ namespace AzNetworking
|
||||
{
|
||||
// Either we disagree on the number of chunks, or chunkIndex is bigger than the expected size, bail and disconnect
|
||||
AZLOG(NET_FragmentQueue, "Malformed chunk metadata in fragmented packet, chunkIndex %u, chunkCount %u, reservedSize %u", chunkIndex, chunkCount, static_cast<uint32_t>(packetFragments.size()));
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
packetFragments[chunkIndex] = AZStd::move(packet);
|
||||
@@ -105,7 +105,7 @@ namespace AzNetworking
|
||||
}
|
||||
|
||||
// We haven't received all chunks required to complete this packet yet
|
||||
return true;
|
||||
return PacketDispatchResult::Success;
|
||||
}
|
||||
|
||||
totalPacketSize += static_cast<uint32_t>(packetFragments[index]->GetChunkBuffer().GetSize());
|
||||
@@ -119,7 +119,7 @@ namespace AzNetworking
|
||||
if (!buffer.Resize(totalPacketSize))
|
||||
{
|
||||
AZLOG_ERROR("Fragmented packet is too large to fit in UdpPacketEncodingBuffer");
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
uint8_t* bufferPointer = buffer.GetBuffer();
|
||||
@@ -141,17 +141,17 @@ namespace AzNetworking
|
||||
if (!header.SerializePacketFlags(networkSerializer))
|
||||
{
|
||||
AZLOG(NET_FragmentQueue, "Reconstructed fragmented packet failed packet flags serialization");
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
|
||||
if (!networkISerializer.Serialize(header, "Header"))
|
||||
{
|
||||
AZLOG(NET_FragmentQueue, "Reconstructed fragmented packet failed header serialization");
|
||||
return false;
|
||||
return PacketDispatchResult::Failure;
|
||||
}
|
||||
}
|
||||
connection->GetPacketTracker().ProcessReceived(connection, header);
|
||||
bool handledPacket = false;
|
||||
PacketDispatchResult handledPacket;
|
||||
if (header.GetPacketType() < aznumeric_cast<PacketType>(CorePackets::PacketType::MAX))
|
||||
{
|
||||
handledPacket = connection->HandleCorePacket(connectionListener, header, networkSerializer);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzNetworking/PacketLayer/IPacket.h>
|
||||
#include <AzNetworking/PacketLayer/IPacketHeader.h>
|
||||
#include <AzNetworking/AutoGen/CorePackets.AutoPackets.h>
|
||||
#include <AzNetworking/ConnectionLayer/SequenceGenerator.h>
|
||||
#include <AzNetworking/DataStructures/RingBufferBitset.h>
|
||||
@@ -44,8 +45,8 @@ namespace AzNetworking
|
||||
//! @param connectionListener the connection listener for delivery of completed packets
|
||||
//! @param header the chunk packet header
|
||||
//! @param serializer the serializer containing the chunk body
|
||||
//! @return boolean true if the chunk was processed, false if an error was encountered
|
||||
bool ProcessReceivedChunk(UdpConnection* connection, IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer);
|
||||
//! @return PacketDispatchResult result of processing the chunk
|
||||
PacketDispatchResult ProcessReceivedChunk(UdpConnection* connection, IConnectionListener& connectionListener, UdpPacketHeader& header, ISerializer& serializer);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace AzNetworking
|
||||
|
||||
timeoutItem->UpdateTimeoutTime(startTimeMs);
|
||||
|
||||
bool handledPacket = false;
|
||||
PacketDispatchResult handledPacket;
|
||||
if (header.GetPacketType() < aznumeric_cast<PacketType>(CorePackets::PacketType::MAX))
|
||||
{
|
||||
handledPacket = connection->HandleCorePacket(m_connectionListener, header, packetSerializer);
|
||||
@@ -287,7 +287,7 @@ namespace AzNetworking
|
||||
handledPacket = m_connectionListener.OnPacketReceived(connection, header, packetSerializer);
|
||||
}
|
||||
|
||||
if (handledPacket)
|
||||
if (handledPacket == PacketDispatchResult::Success)
|
||||
{
|
||||
connection->UpdateHeartbeat(currentTimeMs);
|
||||
if (connection->GetConnectionState() == ConnectionState::Connecting && !connection->GetDtlsEndpoint().IsConnecting())
|
||||
@@ -299,10 +299,16 @@ namespace AzNetworking
|
||||
else if (m_socket->IsEncrypted() && connection->GetDtlsEndpoint().IsConnecting() &&
|
||||
!IsHandshakePacket(connection->GetDtlsEndpoint(), header.GetPacketType()))
|
||||
{
|
||||
// It's possible for one side to finish its half of the handshake and start sending encrypted data
|
||||
// It's possible for one side to finish its half of the encryption handshake and start sending encrypted data
|
||||
// This will appear as a SerializationError due to the incomplete encryption handshake
|
||||
// If it's not an expected unencrypted type then skip it for now
|
||||
continue;
|
||||
}
|
||||
else if (handledPacket == PacketDispatchResult::Pending)
|
||||
{
|
||||
// If we did not handle due to a handshake pending completion, defer it
|
||||
continue;
|
||||
}
|
||||
else if (connection->GetConnectionState() != ConnectionState::Disconnecting)
|
||||
{
|
||||
connection->Disconnect(DisconnectReason::StreamError, TerminationEndpoint::Local);
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<Include File="Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h" />
|
||||
<Include File="Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h" />
|
||||
|
||||
<Packet Name="Connect" Desc="Client connection packet, on success the server will reply with an Accept">
|
||||
<Packet Name="Connect" HandshakePacket="true" Desc="Client connection packet, on success the server will reply with an Accept">
|
||||
<Member Type="uint16_t" Name="networkProtocolVersion" Init="0" />
|
||||
<Member Type="Multiplayer::LongNetworkString" Name="ticket" />
|
||||
</Packet>
|
||||
|
||||
<Packet Name="Accept" Desc="Server accept packet">
|
||||
<Packet Name="Accept" HandshakePacket="true" Desc="Server accept packet">
|
||||
<Member Type="Multiplayer::HostId" Name="hostId" Init="Multiplayer::InvalidHostId" />
|
||||
<Member Type="Multiplayer::LongNetworkString" Name="map" />
|
||||
</Packet>
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace Multiplayer
|
||||
;
|
||||
}
|
||||
|
||||
bool MultiplayerEditorConnection::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
|
||||
AzNetworking::PacketDispatchResult MultiplayerEditorConnection::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
|
||||
{
|
||||
return MultiplayerEditorPackets::DispatchPacket(connection, packetHeader, serializer, *this);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Multiplayer
|
||||
MultiplayerEditorConnection();
|
||||
~MultiplayerEditorConnection() = default;
|
||||
|
||||
bool IsHandshakeComplete(){ return true; };
|
||||
bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerEditorPackets::EditorServerInit& packet);
|
||||
bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerEditorPackets::EditorServerReady& packet);
|
||||
|
||||
@@ -40,7 +41,7 @@ namespace Multiplayer
|
||||
//! @{
|
||||
AzNetworking::ConnectResult ValidateConnect(const AzNetworking::IpAddress& remoteAddress, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
void OnConnect(AzNetworking::IConnection* connection) override;
|
||||
bool OnPacketReceived(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
AzNetworking::PacketDispatchResult OnPacketReceived(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
void OnPacketLost(AzNetworking::IConnection* connection, AzNetworking::PacketId packetId) override;
|
||||
void OnDisconnect(AzNetworking::IConnection* connection, AzNetworking::DisconnectReason reason, AzNetworking::TerminationEndpoint endpoint) override;
|
||||
//! @}
|
||||
|
||||
@@ -441,6 +441,11 @@ namespace Multiplayer
|
||||
MultiplayerPackets::SyncConsole m_syncPacket;
|
||||
};
|
||||
|
||||
bool MultiplayerSystemComponent::IsHandshakeComplete()
|
||||
{
|
||||
return m_didHandshake;
|
||||
}
|
||||
|
||||
bool MultiplayerSystemComponent::HandleRequest
|
||||
(
|
||||
[[maybe_unused]] AzNetworking::IConnection* connection,
|
||||
@@ -465,6 +470,8 @@ namespace Multiplayer
|
||||
|
||||
if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map)))
|
||||
{
|
||||
m_didHandshake = true;
|
||||
|
||||
// Sync our console
|
||||
ConsoleReplicator consoleReplicator(connection);
|
||||
AZ::Interface<AZ::IConsole>::Get()->VisitRegisteredFunctors([&consoleReplicator](AZ::ConsoleFunctorBase* functor) { consoleReplicator.Visit(functor); });
|
||||
@@ -480,6 +487,8 @@ namespace Multiplayer
|
||||
[[maybe_unused]] MultiplayerPackets::Accept& packet
|
||||
)
|
||||
{
|
||||
m_didHandshake = true;
|
||||
|
||||
AZ::CVarFixedString commandString = "sv_map " + packet.GetMap();
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str());
|
||||
|
||||
@@ -670,7 +679,7 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
|
||||
AzNetworking::PacketDispatchResult MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer)
|
||||
{
|
||||
return MultiplayerPackets::DispatchPacket(connection, packetHeader, serializer, *this);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace Multiplayer
|
||||
int GetTickOrder() override;
|
||||
//! @}
|
||||
|
||||
bool IsHandshakeComplete();
|
||||
bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Connect& packet);
|
||||
bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Accept& packet);
|
||||
bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ReadyForEntityUpdates& packet);
|
||||
@@ -89,7 +90,7 @@ namespace Multiplayer
|
||||
//! @{
|
||||
AzNetworking::ConnectResult ValidateConnect(const AzNetworking::IpAddress& remoteAddress, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
void OnConnect(AzNetworking::IConnection* connection) override;
|
||||
bool OnPacketReceived(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
AzNetworking::PacketDispatchResult OnPacketReceived(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
|
||||
void OnPacketLost(AzNetworking::IConnection* connection, AzNetworking::PacketId packetId) override;
|
||||
void OnDisconnect(AzNetworking::IConnection* connection, AzNetworking::DisconnectReason reason, AzNetworking::TerminationEndpoint endpoint) override;
|
||||
//! @}
|
||||
@@ -158,6 +159,7 @@ namespace Multiplayer
|
||||
double m_serverSendAccumulator = 0.0;
|
||||
float m_renderBlendFactor = 0.0f;
|
||||
float m_tickFactor = 0.0f;
|
||||
bool m_didHandshake = false;
|
||||
|
||||
#if !defined(AZ_RELEASE_BUILD)
|
||||
MultiplayerEditorConnection m_editorConnectionListener;
|
||||
|
||||
Reference in New Issue
Block a user