diff --git a/Code/Framework/AzFramework/AzFramework/Session/ISessionHandlingRequests.h b/Code/Framework/AzFramework/AzFramework/Session/ISessionHandlingRequests.h
index 10c1d1cdd5..d55f38f65c 100644
--- a/Code/Framework/AzFramework/AzFramework/Session/ISessionHandlingRequests.h
+++ b/Code/Framework/AzFramework/AzFramework/Session/ISessionHandlingRequests.h
@@ -46,7 +46,7 @@ namespace AzFramework
};
//! ISessionHandlingClientRequests
- //! Requests made to the client to manage their connection to a session
+ //! Requests made to the client to manage their membership in a session
class ISessionHandlingClientRequests
{
public:
@@ -87,11 +87,11 @@ namespace AzFramework
// Retrieves the file location of a pem-encoded TLS certificate for Client to Server communication
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
// empty string.
- virtual AZStd::string GetExternalSessionCertificate() = 0;
+ virtual AZ::IO::Path GetExternalSessionCertificate() = 0;
// Retrieves the file location of a pem-encoded TLS certificate for Server to Server communication
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
// empty string.
- virtual AZStd::string GetInternalSessionCertificate() = 0;
+ virtual AZ::IO::Path GetInternalSessionCertificate() = 0;
};
} // namespace AzFramework
diff --git a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml
index 642832805d..ce8931107f 100644
--- a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml
+++ b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml
@@ -9,6 +9,7 @@
+
diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp
index ee308f6ed8..11207df27d 100644
--- a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp
+++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp
@@ -21,10 +21,12 @@ namespace Multiplayer
ClientToServerConnectionData::ClientToServerConnectionData
(
AzNetworking::IConnection* connection,
- AzNetworking::IConnectionListener& connectionListener
+ AzNetworking::IConnectionListener& connectionListener,
+ AZStd::string providerTicket
)
: m_connection(connection)
, m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer)
+ , m_providerTicket(providerTicket)
{
m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount);
m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs);
diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h
index 2e7be47842..52c5dea00d 100644
--- a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h
+++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h
@@ -24,7 +24,8 @@ namespace Multiplayer
ClientToServerConnectionData
(
AzNetworking::IConnection* connection,
- AzNetworking::IConnectionListener& connectionListener
+ AzNetworking::IConnectionListener& connectionListener,
+ AZStd::string providerTicket = ""
);
~ClientToServerConnectionData() override;
@@ -38,8 +39,11 @@ namespace Multiplayer
void SetCanSendUpdates(bool canSendUpdates) override;
//! @}
+ AZStd::string GetProviderTicket() const;
+
private:
EntityReplicationManager m_entityReplicationManager;
+ AZStd::string m_providerTicket;
AzNetworking::IConnection* m_connection = nullptr;
bool m_canSendUpdates = true;
};
diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl
index 6d4a332b6e..f23c8dd1d9 100644
--- a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl
+++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl
@@ -21,4 +21,9 @@ namespace Multiplayer
{
m_canSendUpdates = canSendUpdates;
}
+
+ inline AZStd::string ClientToServerConnectionData::GetProviderTicket() const
+ {
+ return m_providerTicket;
+ }
}
diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h
index faa11bc225..c171cdbe5d 100644
--- a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h
+++ b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h
@@ -41,6 +41,8 @@ namespace Multiplayer
NetworkEntityHandle GetPrimaryPlayerEntity();
const NetworkEntityHandle& GetPrimaryPlayerEntity() const;
+ AZStd::string GetProviderTicket() const;
+ void SetProviderTicket(AZStd::string);
private:
void OnControlledEntityRemove();
@@ -51,6 +53,7 @@ namespace Multiplayer
NetworkEntityHandle m_controlledEntity;
EntityStopEvent::Handler m_controlledEntityRemovedHandler;
EntityServerMigrationEvent::Handler m_controlledEntityMigrationHandler;
+ AZStd::string m_ticket;
AzNetworking::IConnection* m_connection = nullptr;
bool m_canSendUpdates = false;
};
diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.inl b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.inl
index 0a4215a363..0427936f00 100644
--- a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.inl
+++ b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.inl
@@ -32,4 +32,14 @@ namespace Multiplayer
{
return m_controlledEntity;
}
+
+ inline AZStd::string ServerToClientConnectionData::GetProviderTicket() const
+ {
+ return m_ticket;
+ }
+
+ inline void ServerToClientConnectionData::SetProviderTicket(AZStd::string ticket)
+ {
+ m_ticket = ticket;
+ }
}
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
index 6f8569251f..d0d2c609b3 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
@@ -176,7 +176,13 @@ namespace Multiplayer
INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
const IpAddress ipAddress(config.m_ipAddress.c_str(), config.m_port, networkInterface->GetType());
- networkInterface->Connect(ipAddress);
+ ConnectionId connectionId = networkInterface->Connect(ipAddress);
+
+ AzNetworking::IConnection* connection = 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));
+ }
return true;
}
@@ -196,18 +202,23 @@ namespace Multiplayer
bool MultiplayerSystemComponent::OnCreateSessionBegin(const AzFramework::SessionConfig& sessionConfig)
{
// Check if session manager has a certificate for us and pass it along if so
- AZ::CVarFixedString externalCertPath = AZ::CVarFixedString(AZ::Interface::Get()->GetExternalSessionCertificate());
- if (!externalCertPath.empty())
+ if (AZ::Interface::Get() != nullptr)
{
- AZ::CVarFixedString commandString = "net_SslExternalCertificateFile " + externalCertPath;
- AZ::Interface::Get()->PerformCommand(commandString.c_str());
- }
+ AZ::CVarFixedString externalCertPath = AZ::CVarFixedString(
+ AZ::Interface::Get()->GetExternalSessionCertificate().c_str());
+ if (!externalCertPath.empty())
+ {
+ AZ::CVarFixedString commandString = "net_SslExternalCertificateFile " + externalCertPath;
+ AZ::Interface::Get()->PerformCommand(commandString.c_str());
+ }
- AZ::CVarFixedString internalCertPath = AZ::CVarFixedString(AZ::Interface::Get()->GetInternalSessionCertificate());
- if (!internalCertPath.empty())
- {
- AZ::CVarFixedString commandString = "net_SslInternalCertificateFile " + internalCertPath;
- AZ::Interface::Get()->PerformCommand(commandString.c_str());
+ AZ::CVarFixedString internalCertPath = AZ::CVarFixedString(
+ AZ::Interface::Get()->GetInternalSessionCertificate().c_str());
+ if (!internalCertPath.empty())
+ {
+ AZ::CVarFixedString commandString = "net_SslInternalCertificateFile " + internalCertPath;
+ AZ::Interface::Get()->PerformCommand(commandString.c_str());
+ }
}
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
@@ -370,6 +381,17 @@ namespace Multiplayer
{
if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map)))
{
+ // Validate our session with the provider if any
+ if (AZ::Interface::Get() != nullptr)
+ {
+ AzFramework::PlayerConnectionConfig config;
+ config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId());
+ config.m_playerSessionId = packet.GetTicket();
+ AZ::Interface::Get()->ValidatePlayerJoinSession(config);
+
+ reinterpret_cast(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str());
+ }
+
// Sync our console
ConsoleReplicator consoleReplicator(connection);
AZ::Interface::Get()->VisitRegisteredFunctors([&consoleReplicator](AZ::ConsoleFunctorBase* functor) { consoleReplicator.Visit(functor); });
@@ -525,16 +547,17 @@ namespace Multiplayer
if (connection->GetConnectionRole() == ConnectionRole::Connector)
{
AZLOG_INFO("New outgoing connection to remote address: %s", connection->GetRemoteAddress().GetString().c_str());
- connection->SendReliablePacket(MultiplayerPackets::Connect(0));
+ AZ::CVarFixedString providerTicket;
+ if (connection->GetUserData() != nullptr)
+ {
+ providerTicket = reinterpret_cast(connection->GetUserData())->GetProviderTicket();
+ }
+ connection->SendReliablePacket(MultiplayerPackets::Connect(0, providerTicket));
}
else
{
AZLOG_INFO("New incoming connection from remote address: %s", connection->GetRemoteAddress().GetString().c_str());
m_connAcquiredEvent.Signal(datum);
- AzFramework::PlayerConnectionConfig config;
- config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId());
- config.m_playerSessionId = AZStd::to_string(config.m_playerConnectionId);
- AZ::Interface::Get()->ValidatePlayerJoinSession(config);
}
// Hosts will spawn a new default player prefab for the user that just connected
@@ -600,20 +623,22 @@ namespace Multiplayer
// Signal to session management that a user has left the server
if (m_agentType == MultiplayerAgentType::DedicatedServer || m_agentType == MultiplayerAgentType::ClientServer)
{
- if (connection->GetConnectionRole() == ConnectionRole::Connector)
+ if (AZ::Interface::Get() != nullptr &&
+ connection->GetConnectionRole() == ConnectionRole::Connector)
{
AzFramework::PlayerConnectionConfig config;
config.m_playerConnectionId = aznumeric_cast(connection->GetConnectionId());
- config.m_playerSessionId = AZStd::to_string(config.m_playerConnectionId);
+ config.m_playerSessionId = reinterpret_cast(connection->GetUserData())->GetProviderTicket();
AZ::Interface::Get()->HandlePlayerLeaveSession(config);
}
}
// 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)
+ if (m_agentType == MultiplayerAgentType::DedicatedServer && connection->GetConnectionRole() == ConnectionRole::Connector)
{
- if (m_networkInterface->GetConnectionSet().GetConnectionCount() == 0)
+ if (AZ::Interface::Get() != nullptr
+ && m_networkInterface->GetConnectionSet().GetConnectionCount() == 0)
{
AZ::Interface::Get()->HandleDestroySession();
}