Merge pull request #1334 from aws-lumberyard-dev/mp_session_order

Fix session validation ticket not being passed correctly and cleanup shutdown signaling
This commit is contained in:
AMZN-puvvadar
2021-06-16 09:40:09 -07:00
committed by GitHub
3 changed files with 35 additions and 30 deletions
@@ -179,7 +179,10 @@ namespace Multiplayer
AZ::TickBus::Handler::BusConnect();
AzFramework::SessionNotificationBus::Handler::BusConnect();
m_networkInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(AZ::Name(MPNetworkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this);
m_consoleCommandHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent());
if (AZ::Interface<AZ::IConsole>::Get())
{
m_consoleCommandHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent());
}
AZ::Interface<IMultiplayer>::Register(this);
AZ::Interface<AzFramework::ISessionHandlingClientRequests>::Register(this);
@@ -191,6 +194,8 @@ namespace Multiplayer
{
AZ::Interface<AzFramework::ISessionHandlingClientRequests>::Unregister(this);
AZ::Interface<IMultiplayer>::Unregister(this);
m_consoleCommandHandler.Disconnect();
AZ::Interface<INetworking>::Get()->DestroyNetworkInterface(AZ::Name(MPNetworkInterfaceName));
AzFramework::SessionNotificationBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
}
@@ -199,19 +204,10 @@ namespace Multiplayer
{
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
m_pendingConnectionTickets.push(config.m_playerSessionId);
AZStd::string hostname = config.m_dnsName.empty() ? config.m_ipAddress : config.m_dnsName;
const IpAddress ipAddress(hostname.c_str(), config.m_port, m_networkInterface->GetType());
ConnectionId connectionId = m_networkInterface->Connect(ipAddress);
AzNetworking::IConnection* connection = m_networkInterface->GetConnectionSet().GetConnection(connectionId);
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{
connection->SetUserData(new ClientToServerConnectionData(connection, *this, config.m_playerSessionId));
}
else
{
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->SetProviderTicket(config.m_playerSessionId);
}
m_networkInterface->Connect(ipAddress);
return true;
}
@@ -584,15 +580,16 @@ namespace Multiplayer
datum.m_isInvited = false;
datum.m_agentType = MultiplayerAgentType::Client;
AZStd::string providerTicket;
if (connection->GetConnectionRole() == ConnectionRole::Connector)
{
AZLOG_INFO("New outgoing connection to remote address: %s", connection->GetRemoteAddress().GetString().c_str());
AZ::CVarFixedString providerTicket;
if (connection->GetUserData() != nullptr)
if (!m_pendingConnectionTickets.empty())
{
providerTicket = reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->GetProviderTicket();
providerTicket = m_pendingConnectionTickets.front();
m_pendingConnectionTickets.pop();
}
connection->SendReliablePacket(MultiplayerPackets::Connect(0, providerTicket));
connection->SendReliablePacket(MultiplayerPackets::Connect(0, providerTicket.c_str()));
}
else
{
@@ -622,7 +619,11 @@ namespace Multiplayer
{
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{
connection->SetUserData(new ClientToServerConnectionData(connection, *this));
connection->SetUserData(new ClientToServerConnectionData(connection, *this, providerTicket));
}
else
{
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->SetProviderTicket(providerTicket);
}
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>();
@@ -646,14 +647,10 @@ namespace Multiplayer
AZStd::string reasonString = ToString(reason);
AZLOG_INFO("%s due to %s from remote address: %s", endpointString, reasonString.c_str(), connection->GetRemoteAddress().GetString().c_str());
if (connection->GetConnectionRole() == ConnectionRole::Acceptor)
// The client is disconnecting
if (GetAgentType() == MultiplayerAgentType::Client)
{
// The authority is shutting down its connection
m_shutdownEvent.Signal(m_networkInterface);
}
else if (GetAgentType() == MultiplayerAgentType::Client && connection->GetConnectionRole() == ConnectionRole::Connector)
{
// The client is disconnecting
AZ_Assert(connection->GetConnectionRole() == ConnectionRole::Connector, "Client connection role should only ever be Connector");
m_clientDisconnectedEvent.Signal();
}
@@ -669,7 +666,7 @@ namespace Multiplayer
if (m_agentType == MultiplayerAgentType::DedicatedServer || m_agentType == MultiplayerAgentType::ClientServer)
{
if (AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get() != nullptr &&
connection->GetConnectionRole() == ConnectionRole::Connector)
connection->GetConnectionRole() == ConnectionRole::Acceptor)
{
AzFramework::PlayerConnectionConfig config;
config.m_playerConnectionId = aznumeric_cast<uint32_t>(connection->GetConnectionId());
@@ -680,12 +677,15 @@ namespace Multiplayer
// Signal to session management when there are no remaining players in a dedicated server for potential cleanup
// We avoid this for client server as the host itself is a user
if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Connector)
if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Acceptor)
{
if (AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get() != nullptr
&& m_networkInterface->GetConnectionSet().GetConnectionCount() == 0)
if (m_networkInterface->GetConnectionSet().GetConnectionCount() == 0)
{
AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->HandleDestroySession();
m_shutdownEvent.Signal(m_networkInterface);
if (AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get() != nullptr)
{
AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->HandleDestroySession();
}
}
}
}
@@ -146,6 +146,8 @@ namespace Multiplayer
ConnectionAcquiredEvent m_connAcquiredEvent;
ClientDisconnectedEvent m_clientDisconnectedEvent;
AZStd::queue<AZStd::string> m_pendingConnectionTickets;
AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 };
HostFrameId m_lastReplicatedHostFrameId = InvalidHostFrameId;
@@ -35,14 +35,16 @@ namespace UnitTest
m_initHandler = Multiplayer::SessionInitEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestInitEvent(value); });
m_mpComponent->AddSessionInitHandler(m_initHandler);
m_shutdownHandler = Multiplayer::SessionInitEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestShutdownEvent(value); });
m_shutdownHandler = Multiplayer::SessionShutdownEvent::Handler([this](AzNetworking::INetworkInterface* value) { TestShutdownEvent(value); });
m_mpComponent->AddSessionShutdownHandler(m_shutdownHandler);
m_connAcquiredHandler = Multiplayer::ConnectionAcquiredEvent::Handler([this](Multiplayer::MultiplayerAgentDatum value) { TestConnectionAcquiredEvent(value); });
m_mpComponent->AddConnectionAcquiredHandler(m_connAcquiredHandler);
m_mpComponent->Activate();
}
void TearDown() override
{
m_mpComponent->Deactivate();
delete m_mpComponent;
delete m_netComponent;
AZ::NameDictionary::Destroy();
@@ -86,6 +88,7 @@ namespace UnitTest
TEST_F(MultiplayerSystemTests, TestShutdownEvent)
{
m_mpComponent->InitializeMultiplayer(Multiplayer::MultiplayerAgentType::DedicatedServer);
IMultiplayerConnectionMock connMock1 = IMultiplayerConnectionMock(AzNetworking::ConnectionId(), AzNetworking::IpAddress(), AzNetworking::ConnectionRole::Acceptor);
IMultiplayerConnectionMock connMock2 = IMultiplayerConnectionMock(AzNetworking::ConnectionId(), AzNetworking::IpAddress(), AzNetworking::ConnectionRole::Connector);
m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local);