Move packet dispatch to return an enum that includes a pending option

Signed-off-by: puvvadar <puvvadar@amazon.com>
monroegm-disable-blank-issue-2
puvvadar 4 years ago
parent 97a053a540
commit decf15df21

@ -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;

Loading…
Cancel
Save