diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index d662e6dc5c..8c4bb1122e 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -10,6 +10,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +- Added `UnityTransport.GetEndpoint` method to provide a way to obtain `NetworkEndpoint` information of a connection via client identifier. (#3130) - Added `NetworkTransport.OnEarlyUpdate` and `NetworkTransport.OnPostLateUpdate` methods to provide more control over handling transport related events at the start and end of each frame. (#3113) ### Fixed diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index d3962e0fa1..4a3edac16b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1262,6 +1262,30 @@ public override ulong GetCurrentRtt(ulong clientId) return (ulong)ExtractRtt(ParseClientId(clientId)); } + /// + /// Provides the for the NGO client identifier specified. + /// + /// + /// - This is only really useful for direct connections. + /// - Relay connections and clients connected using a distributed authority network topology will not provide the client's actual endpoint information. + /// - For LAN topologies this should work as long as it is a direct connection and not a relay connection. + /// + /// NGO client identifier to get endpoint information about. + /// + public NetworkEndpoint GetEndpoint(ulong clientId) + { + if (m_Driver.IsCreated && m_NetworkManager != null && m_NetworkManager.IsListening) + { + var transportId = m_NetworkManager.ConnectionManager.ClientIdToTransportId(clientId); + var networkConnection = ParseClientId(transportId); + if (m_Driver.GetConnectionState(networkConnection) == NetworkConnection.State.Connected) + { + return m_Driver.GetRemoteEndpoint(networkConnection); + } + } + return new NetworkEndpoint(); + } + /// /// Initializes the transport /// diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs index 788758c90d..484f6301fd 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs @@ -1,6 +1,9 @@ using System; using System.Collections; using NUnit.Framework; +using Unity.Netcode.TestHelpers.Runtime; +using Unity.Netcode.Transports.UTP; +using Unity.Networking.Transport; using UnityEngine; using UnityEngine.TestTools; @@ -157,4 +160,49 @@ public override void DisconnectLocalClient() } } } + + /// + /// Verifies the UnityTransport.GetEndpoint method returns + /// valid NetworkEndpoint information. + /// + internal class TransportEndpointTests : NetcodeIntegrationTest + { + protected override int NumberOfClients => 2; + + [UnityTest] + public IEnumerator GetEndpointReportedCorrectly() + { + var serverUnityTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as UnityTransport; + var serverEndpoint = new NetworkEndpoint(); + var clientEndpoint = new NetworkEndpoint(); + foreach (var client in m_ClientNetworkManagers) + { + var unityTransport = client.NetworkConfig.NetworkTransport as UnityTransport; + serverEndpoint = unityTransport.GetEndpoint(m_ServerNetworkManager.LocalClientId); + clientEndpoint = serverUnityTransport.GetEndpoint(client.LocalClientId); + Assert.IsTrue(serverEndpoint.IsValid); + Assert.IsTrue(clientEndpoint.IsValid); + Assert.IsTrue(clientEndpoint.Address.Split(":")[0] == unityTransport.ConnectionData.Address); + Assert.IsTrue(serverEndpoint.Address.Split(":")[0] == serverUnityTransport.ConnectionData.Address); + Assert.IsTrue(serverEndpoint.Port == unityTransport.ConnectionData.Port); + Assert.IsTrue(clientEndpoint.Port >= serverUnityTransport.ConnectionData.Port); + } + + // Now validate that when disconnected it returns a non-valid NetworkEndPoint + var clientId = m_ClientNetworkManagers[0].LocalClientId; + m_ClientNetworkManagers[0].Shutdown(); + yield return s_DefaultWaitForTick; + + serverEndpoint = (m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport as UnityTransport).GetEndpoint(m_ServerNetworkManager.LocalClientId); + clientEndpoint = serverUnityTransport.GetEndpoint(clientId); + Assert.IsFalse(serverEndpoint.IsValid); + Assert.IsFalse(clientEndpoint.IsValid); + + // Validate that invalid client identifiers return an invalid NetworkEndPoint + serverEndpoint = (m_ClientNetworkManagers[0].NetworkConfig.NetworkTransport as UnityTransport).GetEndpoint((ulong)UnityEngine.Random.Range(NumberOfClients + 1, 30)); + clientEndpoint = serverUnityTransport.GetEndpoint((ulong)UnityEngine.Random.Range(NumberOfClients + 1, 30)); + Assert.IsFalse(serverEndpoint.IsValid); + Assert.IsFalse(clientEndpoint.IsValid); + } + } } diff --git a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs index 277e8f8836..b09dd5e291 100644 --- a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs @@ -22,7 +22,6 @@ public enum UseSceneManagement SceneManagementDisabled } - private bool m_EnableSceneManagement; private NetworkObject m_NetworkObject; private bool m_NetworkObjectWasSpawned; private bool m_NetworkBehaviourIsHostWasSet; @@ -85,7 +84,7 @@ protected override IEnumerator OnTearDown() protected override void OnServerAndClientsCreated() { - m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; + m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_UseSceneManagement; m_NetworkObjectTestComponent.ConfigureClientConnected(m_ServerNetworkManager, OnClientConnectedCallback); } @@ -108,7 +107,7 @@ public enum ShutdownChecks protected override void OnNewClientCreated(NetworkManager networkManager) { - networkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; + networkManager.NetworkConfig.EnableSceneManagement = m_UseSceneManagement; foreach (var prefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) { networkManager.NetworkConfig.Prefabs.Add(prefab);