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(); }