From b5f72baf8250491f047beab55e737d299652ad5c Mon Sep 17 00:00:00 2001 From: Tyler Howard Date: Fri, 6 Aug 2021 17:46:26 -0400 Subject: [PATCH 1/5] DST-528: Extracted Relay SDK calls out of UTP adapter for MLAPI; it now accepts a variable passed in via a setter method. Also updated the sample test project included to illustrate these changes. --- .../Runtime/UTPTransport.cs | 170 +++++------------- testproject/Assets/Scenes/SampleScene.unity | 63 ++++++- .../Assets/Scripts/CommandLineHandler.cs | 6 +- .../Assets/Scripts/ConnectionModeScript.cs | 164 +++++++++++++++-- .../Assets/Scripts/RelayJoinCodeInput.cs | 8 +- testproject/Assets/Scripts/RelayUtility.cs | 116 ++++++++++++ .../Assets/Scripts/RelayUtility.cs.meta | 11 ++ testproject/Assets/Scripts/UIController.cs | 3 +- testproject/Assets/Scripts/testproject.asmdef | 8 +- testproject/Packages/manifest.json | 20 ++- testproject/Packages/packages-lock.json | 41 ++--- .../ProjectSettings/ProjectSettings.asset | 16 +- .../ProjectSettings/ProjectVersion.txt | 4 +- 13 files changed, 431 insertions(+), 199 deletions(-) create mode 100644 testproject/Assets/Scripts/RelayUtility.cs create mode 100644 testproject/Assets/Scripts/RelayUtility.cs.meta diff --git a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs index 37358f16a1..6235788c14 100644 --- a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs +++ b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs @@ -4,12 +4,6 @@ using System.Threading.Tasks; using Unity.Networking.Transport; using Unity.Networking.Transport.Relay; -#if ENABLE_RELAY_SERVICE -using Unity.Services.Relay; -using Unity.Services.Relay.Allocations; -using Unity.Services.Relay.Models; -using Unity.Services.Core; -#endif using MLAPI.Transports.Tasks; using UnityEngine; @@ -42,14 +36,11 @@ private enum State [SerializeField] private int m_MessageBufferSize = MaximumMessageLength; [SerializeField] private string m_ServerAddress = "127.0.0.1"; [SerializeField] private ushort m_ServerPort = 7777; - [SerializeField] private int m_RelayMaxPlayers = 10; - [SerializeField] private string m_RelayServer = "https://relay-allocations.cloud.unity3d.com"; private State m_State = State.Disconnected; private NetworkDriver m_Driver; private List m_NetworkParameters; private byte[] m_MessageBuffer; - private string m_RelayJoinCode; private ulong m_ServerClientId; private NetworkPipeline m_UnreliableSequencedPipeline; @@ -58,16 +49,27 @@ private enum State public override ulong ServerClientId => m_ServerClientId; - public string RelayJoinCode => m_RelayJoinCode; - public ProtocolType Protocol => m_ProtocolType; + private RelayServerData m_RelayServerData; + + public void SetRelayServerDataInstance(RelayServerData value) + { + m_RelayServerData = value; + } + + private static readonly RelayServerData k_DefaultRelayServerData = default(RelayServerData); + private void InitDriver() { if (m_NetworkParameters.Count > 0) + { m_Driver = NetworkDriver.Create(m_NetworkParameters.ToArray()); + } else + { m_Driver = NetworkDriver.Create(); + } m_UnreliableSequencedPipeline = m_Driver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); m_ReliableSequencedPipeline = m_Driver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); @@ -79,39 +81,8 @@ private void InitDriver() private void DisposeDriver() { if (m_Driver.IsCreated) - m_Driver.Dispose(); - } - - private static RelayAllocationId ConvertFromAllocationIdBytes(byte[] allocationIdBytes) - { - unsafe { - fixed (byte* ptr = allocationIdBytes) - { - return RelayAllocationId.FromBytePointer(ptr, allocationIdBytes.Length); - } - } - } - - private static RelayHMACKey ConvertFromHMAC(byte[] hmac) - { - unsafe - { - fixed (byte* ptr = hmac) - { - return RelayHMACKey.FromBytePointer(ptr, RelayHMACKey.k_Length); - } - } - } - - private static RelayConnectionData ConvertConnectionData(byte[] connectionData) - { - unsafe - { - fixed (byte* ptr = connectionData) - { - return RelayConnectionData.FromBytePointer(ptr, RelayConnectionData.k_Length); - } + m_Driver.Dispose(); } } @@ -134,7 +105,9 @@ private NetworkPipeline SelectSendPipeline(NetworkChannel channel, int size) case NetworkDelivery.ReliableFragmentedSequenced: // No need to send on the fragmented pipeline if data is smaller than MTU. if (size < NetworkParameterConstants.MTU) + { return m_ReliableSequencedPipeline; + } return m_ReliableSequencedFragmentedPipeline; @@ -154,38 +127,15 @@ private IEnumerator ClientBindAndConnect(SocketTask task) Debug.LogError("You must have Relay SDK installed via the UDash in order to use the relay transport"); yield return null; #else - var joinTask = RelayService.AllocationsApiClient.JoinRelayAsync(new JoinRelayRequest(new JoinRequest(m_RelayJoinCode))); - - while(!joinTask.IsCompleted) - yield return null; - - if (joinTask.IsFaulted) + //This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use + //reflection, but this does not live in the context of a performance-critical loop. + if(m_RelayServerData.Equals(k_DefaultRelayServerData)) { - Debug.LogError("Join Relay request failed"); - task.IsDone = true; - task.Success = false; + Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); yield break; } - var allocation = joinTask.Result.Result.Data.Allocation; - - serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); - - var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); - - var connectionData = ConvertConnectionData(allocation.ConnectionData); - var hostConnectionData = ConvertConnectionData(allocation.HostConnectionData); - var key = ConvertFromHMAC(allocation.Key); - - Debug.Log($"client: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}"); - Debug.Log($"host: {allocation.HostConnectionData[0]} {allocation.HostConnectionData[1]}"); - - Debug.Log($"client: {allocation.AllocationId}"); - - var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref hostConnectionData, ref key); - relayServerData.ComputeNewNonce(); - - m_NetworkParameters.Add(new RelayNetworkParameter{ ServerData = relayServerData }); + m_NetworkParameters.Add(new RelayNetworkParameter{ ServerData = m_RelayServerData }); #endif } else @@ -270,54 +220,17 @@ private IEnumerator StartRelayServer(SocketTask task) Debug.LogError("You must have Relay SDK installed via the UDash in order to use the relay transport"); yield return null; #else - var allocationTask = RelayService.AllocationsApiClient.CreateAllocationAsync(new CreateAllocationRequest(new AllocationRequest(m_RelayMaxPlayers))); - - while(!allocationTask.IsCompleted) + if (m_RelayServerData.Equals(k_DefaultRelayServerData)) { - yield return null; - } - - if (allocationTask.IsFaulted) - { - Debug.LogError("Create allocation request failed"); - task.IsDone = true; - task.Success = false; + Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); yield break; } - - var allocation = allocationTask.Result.Result.Data.Allocation; - - var joinCodeTask = RelayService.AllocationsApiClient.CreateJoincodeAsync(new CreateJoincodeRequest(new JoinCodeRequest(allocation.AllocationId))); - - while(!joinCodeTask.IsCompleted) + else { - yield return null; - } + m_NetworkParameters.Add(new RelayNetworkParameter { ServerData = m_RelayServerData }); - if (joinCodeTask.IsFaulted) - { - Debug.LogError("Create join code request failed"); - task.IsDone = true; - task.Success = false; - yield break; + yield return ServerBindAndListen(task, NetworkEndPoint.AnyIpv4); } - - m_RelayJoinCode = joinCodeTask.Result.Result.Data.JoinCode; - - var serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); - // Debug.Log($"Relay Server endpoint: {allocation.RelayServer.IpV4}:{(ushort)allocation.RelayServer.Port}"); - - var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); - var connectionData = ConvertConnectionData(allocation.ConnectionData); - var key = ConvertFromHMAC(allocation.Key); - - - var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref connectionData, ref key); - relayServerData.ComputeNewNonce(); - - m_NetworkParameters.Add(new RelayNetworkParameter{ ServerData = relayServerData }); - - yield return ServerBindAndListen(task, NetworkEndPoint.AnyIpv4); #endif } @@ -396,8 +309,15 @@ private void Update() if (m_Driver.IsCreated) { m_Driver.ScheduleUpdate().Complete(); - while(AcceptConnection() && m_Driver.IsCreated); - while(ProcessEvent() && m_Driver.IsCreated); + while(AcceptConnection() && m_Driver.IsCreated) + { + ; + } + + while (ProcessEvent() && m_Driver.IsCreated) + { + ; + } } } @@ -417,14 +337,6 @@ private static unsafe NetworkConnection ParseClientId(ulong mlapiConnectionId) return *(NetworkConnection*)&mlapiConnectionId; } - public void SetRelayJoinCode(string value) - { - if (m_State == State.Disconnected) - { - m_RelayJoinCode = value; - } - } - public override void DisconnectLocalClient() { Debug.Assert(m_State == State.Connected, "DisconnectLocalClient should be called on a connected client"); @@ -470,12 +382,6 @@ public override void Init() m_NetworkParameters.Add(new FragmentationUtility.Parameters(){PayloadCapacity = maxFragmentationCapacity}); m_MessageBuffer = new byte[m_MessageBufferSize]; -#if ENABLE_RELAY_SERVICE - if (m_ProtocolType == ProtocolType.RelayUnityTransport) { - Unity.Services.Relay.RelayService.Configuration.BasePath = m_RelayServer; - UnityServices.Initialize(); - } -#endif } public override NetworkEvent PollEvent(out ulong clientId, out NetworkChannel networkChannel, out ArraySegment payload, out float receiveTime) @@ -510,7 +416,9 @@ public override void Send(ulong clientId, ArraySegment data, NetworkChanne } if (m_Driver.EndSend(writer) == size) + { return; + } } Debug.LogError("Error sending the message"); @@ -519,7 +427,9 @@ public override void Send(ulong clientId, ArraySegment data, NetworkChanne public override SocketTasks StartClient() { if (m_Driver.IsCreated) + { return SocketTask.Fault.AsTasks(); + } var task = SocketTask.Working; StartCoroutine(ClientBindAndConnect(task)); @@ -529,7 +439,9 @@ public override SocketTasks StartClient() public override SocketTasks StartServer() { if (m_Driver.IsCreated) + { return SocketTask.Fault.AsTasks(); + } var task = SocketTask.Working; switch (m_ProtocolType) diff --git a/testproject/Assets/Scenes/SampleScene.unity b/testproject/Assets/Scenes/SampleScene.unity index d62a9ab0e6..392afb240b 100644 --- a/testproject/Assets/Scenes/SampleScene.unity +++ b/testproject/Assets/Scenes/SampleScene.unity @@ -219,6 +219,18 @@ MeshFilter: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 19899154} m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &102484700 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 4850072633501053442, guid: d725b5588e1b956458798319e6541d84, + type: 3} + m_PrefabInstance: {fileID: 1928839749} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 50623966c8d88ab40982cc2b0e4c2d2e, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &225870858 GameObject: m_ObjectHideFlags: 0 @@ -586,6 +598,7 @@ MonoBehaviour: GlobalObjectIdHash: 3604669530 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!114 &402668304 MonoBehaviour: m_ObjectHideFlags: 0 @@ -815,7 +828,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 903872102732f5c4cbdd3863de5dbc97, type: 3} m_Name: m_EditorClassIdentifier: - Transport: {fileID: 620561613} + ConnectionScript: {fileID: 102484700} --- !u!114 &509741759 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1097,7 +1110,7 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 620561609} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: b84c2d8dfe509a34fb59e2b81f8e1319, type: 3} m_Name: @@ -1140,7 +1153,7 @@ MonoBehaviour: type: 3} NetworkPrefabs: - Override: 0 - Prefab: {fileID: 442217489085244684, guid: 5eca8a21314fe4278ba2571c289a9773, + Prefab: {fileID: 8133991607019124060, guid: 421bcf732fe69486d8abecfa5eee63bb, type: 3} SourcePrefabToOverride: {fileID: 0} SourceHashToOverride: 0 @@ -1195,8 +1208,6 @@ MonoBehaviour: m_MessageBufferSize: 1024 m_ServerAddress: 127.0.0.1 m_ServerPort: 7777 - m_RelayMaxPlayers: 10 - m_RelayServer: https://relay-allocations-stg.cloud.unity3d.com --- !u!1001 &627808638 PrefabInstance: m_ObjectHideFlags: 0 @@ -2179,6 +2190,7 @@ MonoBehaviour: GlobalObjectIdHash: 3972363333 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!65 &963826007 BoxCollider: m_ObjectHideFlags: 0 @@ -2270,7 +2282,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 05037a80244af4174806bc7f242e4432, type: 3} m_Name: m_EditorClassIdentifier: - UnityChanPrefab: {fileID: 442217489085244684, guid: 5eca8a21314fe4278ba2571c289a9773, + UnityChanPrefab: {fileID: 8133991607019124060, guid: 421bcf732fe69486d8abecfa5eee63bb, type: 3} --- !u!4 &1202924674 Transform: @@ -2672,6 +2684,7 @@ MonoBehaviour: GlobalObjectIdHash: 1445980162 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!54 &1397037320 Rigidbody: m_ObjectHideFlags: 0 @@ -2935,6 +2948,7 @@ MonoBehaviour: GlobalObjectIdHash: 1148320762 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!54 &1402467447 Rigidbody: m_ObjectHideFlags: 0 @@ -3345,6 +3359,7 @@ MonoBehaviour: GlobalObjectIdHash: 2710131580 AlwaysReplicateAsRoot: 0 DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!114 &1475593096 MonoBehaviour: m_ObjectHideFlags: 0 @@ -3589,11 +3604,46 @@ PrefabInstance: m_Modification: m_TransformParent: {fileID: 1333567166} m_Modifications: + - target: {fileID: 2956145122089128464, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: OnStartServerButton + objectReference: {fileID: 0} + - target: {fileID: 2956145122089128464, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: ConnectionModeScript, TestProject + objectReference: {fileID: 0} + - target: {fileID: 2956145122546206394, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: OnStartClientButton + objectReference: {fileID: 0} + - target: {fileID: 2956145122546206394, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: ConnectionModeScript, TestProject + objectReference: {fileID: 0} + - target: {fileID: 2956145122624039697, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: OnStartHostButton + objectReference: {fileID: 0} + - target: {fileID: 2956145122624039697, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_OnClick.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: ConnectionModeScript, TestProject + objectReference: {fileID: 0} - target: {fileID: 4850072633501053442, guid: d725b5588e1b956458798319e6541d84, type: 3} propertyPath: m_JoinCodeInput value: objectReference: {fileID: 509741756} + - target: {fileID: 4850072633501053442, guid: d725b5588e1b956458798319e6541d84, + type: 3} + propertyPath: m_RelayAllocationBasePath + value: https://relay-allocations-stg.services.api.unity.com + objectReference: {fileID: 0} - target: {fileID: 6633621479308595792, guid: d725b5588e1b956458798319e6541d84, type: 3} propertyPath: m_Pivot.x @@ -3802,4 +3852,3 @@ MeshFilter: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2036456027} m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} - \ No newline at end of file diff --git a/testproject/Assets/Scripts/CommandLineHandler.cs b/testproject/Assets/Scripts/CommandLineHandler.cs index 6687a82f46..16f71d1678 100644 --- a/testproject/Assets/Scripts/CommandLineHandler.cs +++ b/testproject/Assets/Scripts/CommandLineHandler.cs @@ -163,7 +163,7 @@ private void StartServer() m_CommandLineArguments.Remove("-m"); if (m_ConnectionModeScript) { - m_ConnectionModeScript.OnStartServer(); + m_ConnectionModeScript.OnStartServerButton(); } else { @@ -175,7 +175,7 @@ private void StartHost() { if (m_ConnectionModeScript) { - m_ConnectionModeScript.OnStartHost(); + m_ConnectionModeScript.OnStartHostButton(); } else { @@ -187,7 +187,7 @@ private void StartClient() { if (m_ConnectionModeScript) { - m_ConnectionModeScript.OnStartClient(); + m_ConnectionModeScript.OnStartClientButton(); } else { diff --git a/testproject/Assets/Scripts/ConnectionModeScript.cs b/testproject/Assets/Scripts/ConnectionModeScript.cs index 47f0cfdd30..82a0c3f8f2 100644 --- a/testproject/Assets/Scripts/ConnectionModeScript.cs +++ b/testproject/Assets/Scripts/ConnectionModeScript.cs @@ -3,6 +3,7 @@ using UnityEngine; using MLAPI; using MLAPI.Transports; +using System.Threading.Tasks; #if ENABLE_RELAY_SERVICE using Unity.Services.Core; using Unity.Services.Authentication; @@ -22,7 +23,28 @@ public class ConnectionModeScript : MonoBehaviour [SerializeField] private GameObject m_JoinCodeInput; + [SerializeField] + private int m_MaxConnections = 10; + private CommandLineProcessor m_CommandLineProcessor; + +#if ENABLE_RELAY_SERVICE + [SerializeField] + private string m_RelayAllocationBasePath = "https://relay-allocations-stg.services.api.unity.com"; + + private string m_RelayJoinCode; + + public void SetRelayJoinCode(string relayJoinCode) + { + m_RelayJoinCode = relayJoinCode; + } + + public string GetRelayJoinCode() + { + return m_RelayJoinCode; + } +#endif + internal void SetCommandLineHandler(CommandLineProcessor commandLineProcessor) { m_CommandLineProcessor = commandLineProcessor; @@ -38,7 +60,6 @@ internal void SetCommandLineHandler(CommandLineProcessor commandLineProcessor) public event OnNotifyConnectionEventDelegateHandler OnNotifyConnectionEventHost; public event OnNotifyConnectionEventDelegateHandler OnNotifyConnectionEventClient; - private IEnumerator WaitForNetworkManager() { while(true) @@ -68,8 +89,10 @@ private void Start() if (NetworkManager.Singleton.GetComponent().Protocol == UTPTransport.ProtocolType.RelayUnityTransport) { m_JoinCodeInput.SetActive(true); - m_ConnectionModeButtons.SetActive(false || AuthenticationService.Instance.IsSignedIn); - m_AuthenticationButtons.SetActive(NetworkManager.Singleton && !NetworkManager.Singleton.IsListening && !AuthenticationService.Instance.IsSignedIn); + //If Start() is called on the first frame update, it's not likely that the AuthenticationService is going to be instantiated yet + //Moved old logic for this out to OnServicesInitialized + m_ConnectionModeButtons.SetActive(false); + m_AuthenticationButtons.SetActive(true); } else #endif @@ -81,54 +104,161 @@ private void Start() } } + private void OnServicesInitialized() + { +#if ENABLE_RELAY_SERVICE + if (NetworkManager.Singleton.GetComponent().Protocol == UTPTransport.ProtocolType.RelayUnityTransport) + { + m_JoinCodeInput.SetActive(true); + m_ConnectionModeButtons.SetActive(false || AuthenticationService.Instance.IsSignedIn); + m_AuthenticationButtons.SetActive(NetworkManager.Singleton && !NetworkManager.Singleton.IsListening && !AuthenticationService.Instance.IsSignedIn); + } +#endif + } + /// /// Handles starting MLAPI in server mode /// - public void OnStartServer() + public void OnStartServerButton() { if (NetworkManager.Singleton && !NetworkManager.Singleton.IsListening && m_ConnectionModeButtons) { - NetworkManager.Singleton.StartServer(); - OnNotifyConnectionEventServer?.Invoke(); - m_ConnectionModeButtons.SetActive(false); +#if ENABLE_RELAY_SERVICE + StartCoroutine(StartRelayServer(StartServer)); +#else + StartServer(); +#endif + } + } + + private void StartServer() + { + NetworkManager.Singleton.StartServer(); + OnNotifyConnectionEventServer?.Invoke(); + m_ConnectionModeButtons.SetActive(false); + } +#if ENABLE_RELAY_SERVICE + /// + /// Coroutine that handles starting MLAPI in server mode if Relay is enabled + /// + private IEnumerator StartRelayServer(Action postAllocationAction) + { + m_ConnectionModeButtons.SetActive(false); + + var serverRelayUtilityTask = RelayUtility.AllocateRelayServerAndGetJoinCode(m_MaxConnections); + while (!serverRelayUtilityTask.IsCompleted) + { + yield return null; } + if (serverRelayUtilityTask.IsFaulted) + { + Debug.LogError("Exception thrown when attempting to start Relay Server. Server not started. Exception: " + serverRelayUtilityTask.Exception.Message); + yield break; + } + + m_RelayJoinCode = serverRelayUtilityTask.Result.joinCode; + + NetworkManager.Singleton.GetComponent().SetRelayServerDataInstance(serverRelayUtilityTask.Result.relayServerData); + + postAllocationAction(); } +#endif /// /// Handles starting MLAPI in host mode /// - public void OnStartHost() + public void OnStartHostButton() { if (NetworkManager.Singleton && !NetworkManager.Singleton.IsListening && m_ConnectionModeButtons) { - NetworkManager.Singleton.StartHost(); - OnNotifyConnectionEventHost?.Invoke(); - m_ConnectionModeButtons.SetActive(false); +#if ENABLE_RELAY_SERVICE + StartCoroutine(StartRelayServer(StartHost)); +#else + StartHost(); +#endif } } + private void StartHost() + { + NetworkManager.Singleton.StartHost(); + OnNotifyConnectionEventHost?.Invoke(); + m_ConnectionModeButtons.SetActive(false); + } + /// /// Handles starting MLAPI in client mode /// - public void OnStartClient() + public void OnStartClientButton() { if (NetworkManager.Singleton && !NetworkManager.Singleton.IsListening && m_ConnectionModeButtons) { - NetworkManager.Singleton.StartClient(); - OnNotifyConnectionEventClient?.Invoke(); - m_ConnectionModeButtons.SetActive(false); +#if ENABLE_RELAY_SERVICE + StartCoroutine(StartRelayClient()); +#else + StartClient(); +#endif } } + private void StartClient() + { + NetworkManager.Singleton.StartClient(); + OnNotifyConnectionEventClient?.Invoke(); + m_ConnectionModeButtons.SetActive(false); + } + +#if ENABLE_RELAY_SERVICE /// - /// Handles autenticating UnityServices, needed for Relay + /// Coroutine that kicks off Relay SDK calls to join a Relay Server instance with a join code + /// + /// + private IEnumerator StartRelayClient() + { + m_ConnectionModeButtons.SetActive(false); + + //assumes that RelayJoinCodeInput populated RelayJoinCode prior to this + var clientRelayUtilityTask = RelayUtility.JoinRelayServerFromJoinCode(m_RelayJoinCode); + + while (!clientRelayUtilityTask.IsCompleted) + { + yield return null; + } + + if (clientRelayUtilityTask.IsFaulted) + { + Debug.LogError("Exception thrown when attempting to connect to Relay Server. Exception: " + clientRelayUtilityTask.Exception.Message); + yield break; + } + + try + { + //Currently only supported by the UTPTransport adapter for MLAPI; RelayServerData as a property isn't in the base Transport interface. + ((UTPTransport)NetworkManager.Singleton.NetworkConfig.NetworkTransport).SetRelayServerDataInstance(clientRelayUtilityTask.Result); + } + catch (InvalidCastException e) + { + Debug.LogError("Transport is not UTPTransport, but attempting to start Relay Client. Client not started. Exception message: " + e.Message); + yield break; + } + + NetworkManager.Singleton.StartClient(); + OnNotifyConnectionEventClient?.Invoke(); + } +#endif + /// + /// Handles authenticating UnityServices, needed for Relay /// public async void OnSignIn() { #if ENABLE_RELAY_SERVICE - await UnityServices.Initialize(); + Unity.Services.Relay.RelayService.Configuration.BasePath = m_RelayAllocationBasePath; + + await UnityServices.InitializeAsync(); + OnServicesInitialized(); await AuthenticationService.Instance.SignInAnonymouslyAsync(); + Debug.Log($"Logging in with PlayerID {AuthenticationService.Instance.PlayerId}"); if (AuthenticationService.Instance.IsSignedIn) diff --git a/testproject/Assets/Scripts/RelayJoinCodeInput.cs b/testproject/Assets/Scripts/RelayJoinCodeInput.cs index 34b3a31e85..ee4e9ed224 100644 --- a/testproject/Assets/Scripts/RelayJoinCodeInput.cs +++ b/testproject/Assets/Scripts/RelayJoinCodeInput.cs @@ -4,7 +4,7 @@ public class RelayJoinCodeInput : MonoBehaviour { - public UTPTransport Transport; + public ConnectionModeScript ConnectionScript; private InputField m_TextInput; private void Start() @@ -15,8 +15,8 @@ private void Start() private void Update() { if (m_TextInput.IsInteractable()) { - if (!string.IsNullOrEmpty(Transport.RelayJoinCode)) { - m_TextInput.text = Transport.RelayJoinCode; + if (!string.IsNullOrEmpty(ConnectionScript.GetRelayJoinCode())) { + m_TextInput.text = ConnectionScript.GetRelayJoinCode(); m_TextInput.readOnly = true; } } @@ -24,6 +24,6 @@ private void Update() public void SetJoinCode() { - Transport.SetRelayJoinCode(m_TextInput.text); + ConnectionScript.SetRelayJoinCode(m_TextInput.text); } } diff --git a/testproject/Assets/Scripts/RelayUtility.cs b/testproject/Assets/Scripts/RelayUtility.cs new file mode 100644 index 0000000000..46c6668857 --- /dev/null +++ b/testproject/Assets/Scripts/RelayUtility.cs @@ -0,0 +1,116 @@ +using System.Threading.Tasks; +using UnityEngine; +using Unity.Networking.Transport; +using Unity.Networking.Transport.Relay; +using Unity.Services.Relay; +using Unity.Services.Relay.Allocations; +using Unity.Services.Relay.Models; + +public class RelayUtility +{ + async public static Task<(RelayServerData relayServerData, string joinCode)> AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null) + { + Response allocationResponse; + Response createJoinCodeResponse; + try + { + allocationResponse = await RelayService.AllocationsApiClient.CreateAllocationAsync(new CreateAllocationRequest(new AllocationRequest(maxConnections, region))); + } + catch + { + Debug.LogError("Relay create allocation request failed"); + throw; + } + + var allocation = allocationResponse.Result.Data.Allocation; + + var serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); + var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); + var connectionData = ConvertConnectionData(allocation.ConnectionData); + var key = ConvertFromHMAC(allocation.Key); + + Debug.Log($"server: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}"); + Debug.Log($"server: {allocation.AllocationId}"); + + var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref connectionData, ref key); + relayServerData.ComputeNewNonce(); + + try + { + createJoinCodeResponse = await RelayService.AllocationsApiClient.CreateJoincodeAsync(new CreateJoincodeRequest(new JoinCodeRequest(allocationResponse.Result.Data.Allocation.AllocationId))); + } + catch + { + Debug.LogError("Relay create join code request failed"); + throw; + } + + string joinCode = createJoinCodeResponse.Result.Data.JoinCode; + + return (relayServerData, joinCode); + } + + async public static Task JoinRelayServerFromJoinCode(string joinCode) + { + Response joinResponse; + try + { + joinResponse = await RelayService.AllocationsApiClient.JoinRelayAsync(new JoinRelayRequest(new JoinRequest(joinCode))); + } + catch + { + Debug.LogError("Relay create join code request failed"); + throw; + } + + var allocation = joinResponse.Result.Data.Allocation; + + var serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); + var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); + var connectionData = ConvertConnectionData(allocation.ConnectionData); + var hostConnectionData = ConvertConnectionData(allocation.HostConnectionData); + var key = ConvertFromHMAC(allocation.Key); + + Debug.Log($"client: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}"); + Debug.Log($"host: {allocation.HostConnectionData[0]} {allocation.HostConnectionData[1]}"); + Debug.Log($"client: {allocation.AllocationId}"); + + var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref hostConnectionData, ref key); + relayServerData.ComputeNewNonce(); + + return relayServerData; + } + + private static RelayAllocationId ConvertFromAllocationIdBytes(byte[] allocationIdBytes) + { + unsafe + { + fixed (byte* ptr = allocationIdBytes) + { + return RelayAllocationId.FromBytePointer(ptr, allocationIdBytes.Length); + } + } + } + + private static RelayHMACKey ConvertFromHMAC(byte[] hmac) + { + unsafe + { + fixed (byte* ptr = hmac) + { + return RelayHMACKey.FromBytePointer(ptr, RelayHMACKey.k_Length); + } + } + } + + private static RelayConnectionData ConvertConnectionData(byte[] connectionData) + { + unsafe + { + fixed (byte* ptr = connectionData) + { + return RelayConnectionData.FromBytePointer(ptr, RelayConnectionData.k_Length); + } + } + } +} diff --git a/testproject/Assets/Scripts/RelayUtility.cs.meta b/testproject/Assets/Scripts/RelayUtility.cs.meta new file mode 100644 index 0000000000..b7879fb3a2 --- /dev/null +++ b/testproject/Assets/Scripts/RelayUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 821a03e0e4496574c8ca6a558047e944 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/testproject/Assets/Scripts/UIController.cs b/testproject/Assets/Scripts/UIController.cs index 3a5969d3e1..72ee50189b 100644 --- a/testproject/Assets/Scripts/UIController.cs +++ b/testproject/Assets/Scripts/UIController.cs @@ -14,6 +14,7 @@ public class UIController : MonoBehaviour public GameObject JoinCode; public UTPTransport Transport; + private string m_JoinCodeString; private void Awake() { @@ -52,7 +53,7 @@ private void HideButtons() public async void OnSignIn() { #if ENABLE_RELAY_SERVICE - await UnityServices.Initialize(); + //await UnityServices.Initialize(); Debug.Log("OnSignIn"); await AuthenticationService.Instance.SignInAnonymouslyAsync(); Debug.Log($"Logging in with PlayerID {AuthenticationService.Instance.PlayerId}"); diff --git a/testproject/Assets/Scripts/testproject.asmdef b/testproject/Assets/Scripts/testproject.asmdef index d4191ebbdd..d1fe523b0b 100644 --- a/testproject/Assets/Scripts/testproject.asmdef +++ b/testproject/Assets/Scripts/testproject.asmdef @@ -7,11 +7,13 @@ "Unity.Multiplayer.MLAPI.Prototyping", "Unity.Multiplayer.Transport.UTP", "Unity.Services.Authentication", - "Unity.Services.Core" + "Unity.Services.Core", + "Unity.Networking.Transport", + "Unity.Services.Relay" ], "includePlatforms": [], "excludePlatforms": [], - "allowUnsafeCode": false, + "allowUnsafeCode": true, "overrideReferences": false, "precompiledReferences": [], "autoReferenced": true, @@ -24,4 +26,4 @@ } ], "noEngineReferences": false -} +} \ No newline at end of file diff --git a/testproject/Packages/manifest.json b/testproject/Packages/manifest.json index b188cc61ff..bb6a380797 100644 --- a/testproject/Packages/manifest.json +++ b/testproject/Packages/manifest.json @@ -1,19 +1,21 @@ { "dependencies": { - "com.unity.collab-proxy": "1.5.7", - "com.unity.ide.rider": "3.0.5", - "com.unity.ide.visualstudio": "2.0.9", + "com.unity.collab-proxy": "1.7.1", + "com.unity.ide.rider": "3.0.7", + "com.unity.ide.visualstudio": "2.0.11", "com.unity.ide.vscode": "1.2.3", + "com.unity.mathematics": "1.2.1", "com.unity.multiplayer.mlapi": "file:../../com.unity.multiplayer.mlapi", "com.unity.multiplayer.transport.utp": "file:../../com.unity.multiplayer.transport.utp", - "com.unity.package-validation-suite": "0.19.2-preview", - "com.unity.services.authentication": "0.5.0-preview", - "com.unity.services.core": "1.1.0-pre.2", - "com.unity.services.relay": "0.0.1-preview.5", + "com.unity.package-validation-suite": "0.21.0-preview", + "com.unity.services.authentication": "1.0.0-pre.3", + "com.unity.services.core": "1.1.0-pre.7", + "com.unity.services.relay": "1.0.0-preview.1", "com.unity.test-framework": "1.1.27", - "com.unity.test-framework.performance": "2.3.1-preview", + "com.unity.test-framework.performance": "2.8.0-preview", "com.unity.textmeshpro": "3.0.6", - "com.unity.timeline": "1.5.2", + "com.unity.timeline": "1.5.6", + "com.unity.transport": "1.0.0-pre.1", "com.unity.ugui": "1.0.0", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", diff --git a/testproject/Packages/packages-lock.json b/testproject/Packages/packages-lock.json index b5cc63a745..ca7346c954 100644 --- a/testproject/Packages/packages-lock.json +++ b/testproject/Packages/packages-lock.json @@ -2,7 +2,7 @@ "dependencies": { "com.unity.burst": { "version": "1.5.3", - "depth": 3, + "depth": 2, "source": "registry", "dependencies": { "com.unity.mathematics": "1.2.1" @@ -10,7 +10,7 @@ "url": "https://packages.unity.com" }, "com.unity.collab-proxy": { - "version": "1.5.7", + "version": "1.7.1", "depth": 0, "source": "registry", "dependencies": { @@ -20,7 +20,7 @@ }, "com.unity.collections": { "version": "1.0.0-pre.3", - "depth": 2, + "depth": 1, "source": "registry", "dependencies": { "com.unity.burst": "1.5.3", @@ -36,14 +36,16 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "3.0.5", + "version": "3.0.7", "depth": 0, "source": "registry", - "dependencies": {}, + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.9", + "version": "2.0.11", "depth": 0, "source": "registry", "dependencies": { @@ -70,7 +72,7 @@ }, "com.unity.mathematics": { "version": "1.2.1", - "depth": 2, + "depth": 0, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" @@ -110,7 +112,7 @@ "url": "https://packages.unity.com" }, "com.unity.package-validation-suite": { - "version": "0.19.2-preview", + "version": "0.21.0-preview", "depth": 0, "source": "registry", "dependencies": { @@ -119,32 +121,31 @@ "url": "https://packages.unity.com" }, "com.unity.services.authentication": { - "version": "0.5.0-preview", + "version": "1.0.0-pre.3", "depth": 0, "source": "registry", "dependencies": { "com.unity.nuget.newtonsoft-json": "2.0.0", - "com.unity.services.core": "1.1.0-pre.2", + "com.unity.services.core": "1.1.0-pre.7", "com.unity.modules.unitywebrequest": "1.0.0" }, "url": "https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-candidates" }, "com.unity.services.core": { - "version": "1.1.0-pre.2", + "version": "1.1.0-pre.7", "depth": 0, "source": "registry", "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.nuget.newtonsoft-json": "2.0.0" + "com.unity.modules.unitywebrequest": "1.0.0" }, "url": "https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-candidates" }, "com.unity.services.relay": { - "version": "0.0.1-preview.5", + "version": "1.0.0-preview.1", "depth": 0, "source": "registry", "dependencies": { - "com.unity.services.core": "1.1.0-pre.2", + "com.unity.services.core": "1.1.0-pre.4", "com.unity.modules.unitywebrequest": "1.0.0", "com.unity.modules.unitywebrequestassetbundle": "1.0.0", "com.unity.modules.unitywebrequestaudio": "1.0.0", @@ -166,12 +167,12 @@ "url": "https://packages.unity.com" }, "com.unity.test-framework.performance": { - "version": "2.3.1-preview", + "version": "2.8.0-preview", "depth": 0, "source": "registry", "dependencies": { "com.unity.test-framework": "1.1.0", - "com.unity.nuget.newtonsoft-json": "2.0.0-preview" + "com.unity.modules.jsonserialize": "1.0.0" }, "url": "https://packages.unity.com" }, @@ -185,7 +186,7 @@ "url": "https://packages.unity.com" }, "com.unity.timeline": { - "version": "1.5.2", + "version": "1.5.6", "depth": 0, "source": "registry", "dependencies": { @@ -197,8 +198,8 @@ "url": "https://packages.unity.com" }, "com.unity.transport": { - "version": "0.9.0-preview.3", - "depth": 1, + "version": "1.0.0-pre.1", + "depth": 0, "source": "registry", "dependencies": { "com.unity.collections": "1.0.0-pre.3", diff --git a/testproject/ProjectSettings/ProjectSettings.asset b/testproject/ProjectSettings/ProjectSettings.asset index 96699ff538..8dd731d6ee 100644 --- a/testproject/ProjectSettings/ProjectSettings.asset +++ b/testproject/ProjectSettings/ProjectSettings.asset @@ -555,6 +555,7 @@ PlayerSettings: ps4videoRecordingFeaturesUsed: 0 ps4contentSearchFeaturesUsed: 0 ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 ps4GPU800MHz: 1 ps4attribEyeToEyeDistanceSettingVR: 0 ps4IncludedModules: [] @@ -580,7 +581,7 @@ PlayerSettings: webGLThreadsSupport: 0 webGLDecompressionFallback: 0 scriptingDefineSymbols: - 1: AUTHENTICATION_TESTING_STAGING_UAS; + 1: AUTHENTICATION_TESTING_STAGING_UAS additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: {} @@ -656,7 +657,14 @@ PlayerSettings: XboxOneOverrideIdentityPublisher: vrEditorSettings: {} cloudServicesEnabled: + Analytics: 0 + Build: 0 + Collab: 0 + Game Performance: 0 + Purchasing: 0 + UDP: 0 UNet: 1 + Unity Ads: 0 luminIcon: m_Name: m_ModelFolderPath: @@ -670,11 +678,11 @@ PlayerSettings: m_VersionName: apiCompatibilityLevel: 6 activeInputHandler: 0 - cloudProjectId: 29e7e6bb-3cf4-46ea-bdc9-b9581a9d0b47 + cloudProjectId: 41b4b759-38bb-46fb-9eb2-b233a90bade7 framebufferDepthMemorylessMode: 0 qualitySettingsNames: [] - projectName: testproject - organizationId: mlapi-test + projectName: relay-stg + organizationId: relay-stg cloudEnabled: 0 legacyClampBlendShapeWeights: 0 virtualTexturingSupportEnabled: 0 diff --git a/testproject/ProjectSettings/ProjectVersion.txt b/testproject/ProjectSettings/ProjectVersion.txt index 79c71bce82..5ac0724b15 100644 --- a/testproject/ProjectSettings/ProjectVersion.txt +++ b/testproject/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2020.3.12f1 -m_EditorVersionWithRevision: 2020.3.12f1 (b3b2c6512326) +m_EditorVersion: 2020.3.15f2 +m_EditorVersionWithRevision: 2020.3.15f2 (6cf78cb77498) From c0ea32860c1ef079ed5bdaefa3c4152e6e9a06e9 Mon Sep 17 00:00:00 2001 From: Tyler Howard Date: Mon, 9 Aug 2021 14:16:57 -0400 Subject: [PATCH 2/5] DST-528: Made some changes that address feedback comments; mainly restructured the manner that code external to UTPTransport passes in the requisite relay server data so that external code doesn't need to know about the internal data structures that UTPTransport uses. --- .../Runtime/UTPTransport.cs | 80 ++++++++++++++----- ...com.unity.multiplayer.transport.utp.asmdef | 12 +-- .../Assets/Scripts/ConnectionModeScript.cs | 38 +++------ .../Assets/Scripts/RelayJoinCodeInput.cs | 6 +- testproject/Assets/Scripts/RelayUtility.cs | 62 +------------- testproject/Assets/Scripts/UIController.cs | 2 +- testproject/Packages/manifest.json | 4 +- testproject/Packages/packages-lock.json | 6 +- 8 files changed, 86 insertions(+), 124 deletions(-) diff --git a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs index 6235788c14..84ae1799f0 100644 --- a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs +++ b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs @@ -53,12 +53,8 @@ private enum State private RelayServerData m_RelayServerData; - public void SetRelayServerDataInstance(RelayServerData value) - { - m_RelayServerData = value; - } - private static readonly RelayServerData k_DefaultRelayServerData = default(RelayServerData); + private static RelayServerData DefaultRelayServerData => k_DefaultRelayServerData; private void InitDriver() { @@ -123,20 +119,15 @@ private IEnumerator ClientBindAndConnect(SocketTask task) if (m_ProtocolType == ProtocolType.RelayUnityTransport) { -#if !ENABLE_RELAY_SERVICE - Debug.LogError("You must have Relay SDK installed via the UDash in order to use the relay transport"); - yield return null; -#else //This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use - //reflection, but this does not live in the context of a performance-critical loop. - if(m_RelayServerData.Equals(k_DefaultRelayServerData)) + //reflection, but this does not live in the context of a performance-critical loop, it runs once at initial connection time. + if(m_RelayServerData.Equals(DefaultRelayServerData)) { Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); yield break; } m_NetworkParameters.Add(new RelayNetworkParameter{ ServerData = m_RelayServerData }); -#endif } else { @@ -173,8 +164,6 @@ private IEnumerator ClientBindAndConnect(SocketTask task) { Debug.LogError("Client failed to connect to server"); } - - } task.IsDone = true; @@ -206,21 +195,70 @@ private IEnumerator ServerBindAndListen(SocketTask task, NetworkEndPoint endPoin { Debug.LogError("Server failed to listen"); } + } + task.IsDone = true; + } + private static RelayAllocationId ConvertFromAllocationIdBytes(byte[] allocationIdBytes) + { + unsafe + { + fixed (byte* ptr = allocationIdBytes) + { + return RelayAllocationId.FromBytePointer(ptr, allocationIdBytes.Length); + } } + } - task.IsDone = true; + private static RelayHMACKey ConvertFromHMAC(byte[] hmac) + { + unsafe + { + fixed (byte* ptr = hmac) + { + return RelayHMACKey.FromBytePointer(ptr, RelayHMACKey.k_Length); + } + } } + private static RelayConnectionData ConvertConnectionData(byte[] connectionData) + { + unsafe + { + fixed (byte* ptr = connectionData) + { + return RelayConnectionData.FromBytePointer(ptr, RelayConnectionData.k_Length); + } + } + } + + public void SetRelayServerData(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] keyBytes, byte[] connectionDataBytes, byte[] hostConnectionDataBytes = null) + { + RelayConnectionData hostConnectionData; + + var serverEndpoint = NetworkEndPoint.Parse(ipv4address, port); + var allocationId = ConvertFromAllocationIdBytes(allocationIdBytes); + var key = ConvertFromHMAC(keyBytes); + var connectionData = ConvertConnectionData(connectionDataBytes); + + if (hostConnectionDataBytes != null) + { + hostConnectionData = ConvertConnectionData(hostConnectionDataBytes); + } + else + { + hostConnectionData = connectionData; + } + m_RelayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref hostConnectionData, ref key); + m_RelayServerData.ComputeNewNonce(); + } private IEnumerator StartRelayServer(SocketTask task) { -#if !ENABLE_RELAY_SERVICE - Debug.LogError("You must have Relay SDK installed via the UDash in order to use the relay transport"); - yield return null; -#else - if (m_RelayServerData.Equals(k_DefaultRelayServerData)) + //This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use + //reflection, but this does not live in the context of a performance-critical loop, it runs once at initial connection time. + if (m_RelayServerData.Equals(DefaultRelayServerData)) { Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); yield break; @@ -231,7 +269,6 @@ private IEnumerator StartRelayServer(SocketTask task) yield return ServerBindAndListen(task, NetworkEndPoint.AnyIpv4); } -#endif } private bool AcceptConnection() @@ -374,7 +411,6 @@ public override void Init() m_NetworkParameters = new List(); - // If we want to be able to actually handle messages MaximumMessageLength bytes in // size, we need to allow a bit more than that in FragmentationUtility since this needs // to account for headers and such. 128 bytes is plenty enough for such overhead. diff --git a/com.unity.multiplayer.transport.utp/Runtime/com.unity.multiplayer.transport.utp.asmdef b/com.unity.multiplayer.transport.utp/Runtime/com.unity.multiplayer.transport.utp.asmdef index 696ebfb440..622b00484c 100644 --- a/com.unity.multiplayer.transport.utp/Runtime/com.unity.multiplayer.transport.utp.asmdef +++ b/com.unity.multiplayer.transport.utp/Runtime/com.unity.multiplayer.transport.utp.asmdef @@ -6,9 +6,7 @@ "Unity.Jobs", "Unity.Burst", "Unity.Multiplayer.MLAPI.Runtime", - "Unity.Networking.Transport", - "Unity.Services.Relay", - "Unity.Services.Core" + "Unity.Networking.Transport" ], "includePlatforms": [], "excludePlatforms": [], @@ -17,12 +15,6 @@ "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], - "versionDefines": [ - { - "name": "com.unity.services.relay", - "expression": "0.0.1-preview.3", - "define": "ENABLE_RELAY_SERVICE" - } - ], + "versionDefines": [], "noEngineReferences": false } \ No newline at end of file diff --git a/testproject/Assets/Scripts/ConnectionModeScript.cs b/testproject/Assets/Scripts/ConnectionModeScript.cs index 82a0c3f8f2..185f1d9042 100644 --- a/testproject/Assets/Scripts/ConnectionModeScript.cs +++ b/testproject/Assets/Scripts/ConnectionModeScript.cs @@ -3,7 +3,7 @@ using UnityEngine; using MLAPI; using MLAPI.Transports; -using System.Threading.Tasks; + #if ENABLE_RELAY_SERVICE using Unity.Services.Core; using Unity.Services.Authentication; @@ -32,17 +32,8 @@ public class ConnectionModeScript : MonoBehaviour [SerializeField] private string m_RelayAllocationBasePath = "https://relay-allocations-stg.services.api.unity.com"; - private string m_RelayJoinCode; - - public void SetRelayJoinCode(string relayJoinCode) - { - m_RelayJoinCode = relayJoinCode; - } - - public string GetRelayJoinCode() - { - return m_RelayJoinCode; - } + [HideInInspector] + public string RelayJoinCode { get; set; } #endif internal void SetCommandLineHandler(CommandLineProcessor commandLineProcessor) @@ -157,9 +148,12 @@ private IEnumerator StartRelayServer(Action postAllocationAction) yield break; } - m_RelayJoinCode = serverRelayUtilityTask.Result.joinCode; + var (ipv4address, port, allocationIdBytes, connectionData, key, joinCode) = serverRelayUtilityTask.Result; - NetworkManager.Singleton.GetComponent().SetRelayServerDataInstance(serverRelayUtilityTask.Result.relayServerData); + RelayJoinCode = joinCode; + + //When starting a relay server, both instances of connection data are identical. + NetworkManager.Singleton.GetComponent().SetRelayServerData(ipv4address, port, allocationIdBytes, key, connectionData); postAllocationAction(); } @@ -219,7 +213,7 @@ private IEnumerator StartRelayClient() m_ConnectionModeButtons.SetActive(false); //assumes that RelayJoinCodeInput populated RelayJoinCode prior to this - var clientRelayUtilityTask = RelayUtility.JoinRelayServerFromJoinCode(m_RelayJoinCode); + var clientRelayUtilityTask = RelayUtility.JoinRelayServerFromJoinCode(RelayJoinCode); while (!clientRelayUtilityTask.IsCompleted) { @@ -232,16 +226,10 @@ private IEnumerator StartRelayClient() yield break; } - try - { - //Currently only supported by the UTPTransport adapter for MLAPI; RelayServerData as a property isn't in the base Transport interface. - ((UTPTransport)NetworkManager.Singleton.NetworkConfig.NetworkTransport).SetRelayServerDataInstance(clientRelayUtilityTask.Result); - } - catch (InvalidCastException e) - { - Debug.LogError("Transport is not UTPTransport, but attempting to start Relay Client. Client not started. Exception message: " + e.Message); - yield break; - } + var (ipv4address, port, allocationIdBytes, connectionData, hostConnectionData, key) = clientRelayUtilityTask.Result; + + //When connecting as a client to a relay server, connectionData and hostConnectionData are different. + NetworkManager.Singleton.GetComponent().SetRelayServerData(ipv4address, port, allocationIdBytes, key, connectionData, hostConnectionData); NetworkManager.Singleton.StartClient(); OnNotifyConnectionEventClient?.Invoke(); diff --git a/testproject/Assets/Scripts/RelayJoinCodeInput.cs b/testproject/Assets/Scripts/RelayJoinCodeInput.cs index ee4e9ed224..ea4aa8815d 100644 --- a/testproject/Assets/Scripts/RelayJoinCodeInput.cs +++ b/testproject/Assets/Scripts/RelayJoinCodeInput.cs @@ -15,8 +15,8 @@ private void Start() private void Update() { if (m_TextInput.IsInteractable()) { - if (!string.IsNullOrEmpty(ConnectionScript.GetRelayJoinCode())) { - m_TextInput.text = ConnectionScript.GetRelayJoinCode(); + if (!string.IsNullOrEmpty(ConnectionScript.RelayJoinCode)) { + m_TextInput.text = ConnectionScript.RelayJoinCode; m_TextInput.readOnly = true; } } @@ -24,6 +24,6 @@ private void Update() public void SetJoinCode() { - ConnectionScript.SetRelayJoinCode(m_TextInput.text); + ConnectionScript.RelayJoinCode = m_TextInput.text; } } diff --git a/testproject/Assets/Scripts/RelayUtility.cs b/testproject/Assets/Scripts/RelayUtility.cs index 46c6668857..9bf63bce77 100644 --- a/testproject/Assets/Scripts/RelayUtility.cs +++ b/testproject/Assets/Scripts/RelayUtility.cs @@ -1,14 +1,12 @@ using System.Threading.Tasks; using UnityEngine; -using Unity.Networking.Transport; -using Unity.Networking.Transport.Relay; using Unity.Services.Relay; using Unity.Services.Relay.Allocations; using Unity.Services.Relay.Models; public class RelayUtility { - async public static Task<(RelayServerData relayServerData, string joinCode)> AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null) + async public static Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[] key, string joinCode)> AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null) { Response allocationResponse; Response createJoinCodeResponse; @@ -24,17 +22,9 @@ public class RelayUtility var allocation = allocationResponse.Result.Data.Allocation; - var serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); - var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); - var connectionData = ConvertConnectionData(allocation.ConnectionData); - var key = ConvertFromHMAC(allocation.Key); - Debug.Log($"server: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}"); Debug.Log($"server: {allocation.AllocationId}"); - var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref connectionData, ref key); - relayServerData.ComputeNewNonce(); - try { createJoinCodeResponse = await RelayService.AllocationsApiClient.CreateJoincodeAsync(new CreateJoincodeRequest(new JoinCodeRequest(allocationResponse.Result.Data.Allocation.AllocationId))); @@ -45,12 +35,10 @@ public class RelayUtility throw; } - string joinCode = createJoinCodeResponse.Result.Data.JoinCode; - - return (relayServerData, joinCode); + return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.Key, createJoinCodeResponse.Result.Data.JoinCode); } - async public static Task JoinRelayServerFromJoinCode(string joinCode) + async public static Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[] hostConnectionData, byte[] key)> JoinRelayServerFromJoinCode(string joinCode) { Response joinResponse; try @@ -65,52 +53,10 @@ async public static Task JoinRelayServerFromJoinCode(string joi var allocation = joinResponse.Result.Data.Allocation; - var serverEndpoint = NetworkEndPoint.Parse(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port); - var allocationId = ConvertFromAllocationIdBytes(allocation.AllocationIdBytes); - var connectionData = ConvertConnectionData(allocation.ConnectionData); - var hostConnectionData = ConvertConnectionData(allocation.HostConnectionData); - var key = ConvertFromHMAC(allocation.Key); - Debug.Log($"client: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}"); Debug.Log($"host: {allocation.HostConnectionData[0]} {allocation.HostConnectionData[1]}"); Debug.Log($"client: {allocation.AllocationId}"); - var relayServerData = new RelayServerData(ref serverEndpoint, 0, ref allocationId, ref connectionData, ref hostConnectionData, ref key); - relayServerData.ComputeNewNonce(); - - return relayServerData; - } - - private static RelayAllocationId ConvertFromAllocationIdBytes(byte[] allocationIdBytes) - { - unsafe - { - fixed (byte* ptr = allocationIdBytes) - { - return RelayAllocationId.FromBytePointer(ptr, allocationIdBytes.Length); - } - } - } - - private static RelayHMACKey ConvertFromHMAC(byte[] hmac) - { - unsafe - { - fixed (byte* ptr = hmac) - { - return RelayHMACKey.FromBytePointer(ptr, RelayHMACKey.k_Length); - } - } - } - - private static RelayConnectionData ConvertConnectionData(byte[] connectionData) - { - unsafe - { - fixed (byte* ptr = connectionData) - { - return RelayConnectionData.FromBytePointer(ptr, RelayConnectionData.k_Length); - } - } + return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.HostConnectionData, allocation.Key); } } diff --git a/testproject/Assets/Scripts/UIController.cs b/testproject/Assets/Scripts/UIController.cs index 72ee50189b..678445a0c1 100644 --- a/testproject/Assets/Scripts/UIController.cs +++ b/testproject/Assets/Scripts/UIController.cs @@ -53,7 +53,7 @@ private void HideButtons() public async void OnSignIn() { #if ENABLE_RELAY_SERVICE - //await UnityServices.Initialize(); + await UnityServices.InitializeAsync(); Debug.Log("OnSignIn"); await AuthenticationService.Instance.SignInAnonymouslyAsync(); Debug.Log($"Logging in with PlayerID {AuthenticationService.Instance.PlayerId}"); diff --git a/testproject/Packages/manifest.json b/testproject/Packages/manifest.json index bb6a380797..0b493d2cbf 100644 --- a/testproject/Packages/manifest.json +++ b/testproject/Packages/manifest.json @@ -8,8 +8,8 @@ "com.unity.multiplayer.mlapi": "file:../../com.unity.multiplayer.mlapi", "com.unity.multiplayer.transport.utp": "file:../../com.unity.multiplayer.transport.utp", "com.unity.package-validation-suite": "0.21.0-preview", - "com.unity.services.authentication": "1.0.0-pre.3", - "com.unity.services.core": "1.1.0-pre.7", + "com.unity.services.authentication": "1.0.0-pre.4", + "com.unity.services.core": "1.1.0-pre.8", "com.unity.services.relay": "1.0.0-preview.1", "com.unity.test-framework": "1.1.27", "com.unity.test-framework.performance": "2.8.0-preview", diff --git a/testproject/Packages/packages-lock.json b/testproject/Packages/packages-lock.json index ca7346c954..f2acdb609d 100644 --- a/testproject/Packages/packages-lock.json +++ b/testproject/Packages/packages-lock.json @@ -121,18 +121,18 @@ "url": "https://packages.unity.com" }, "com.unity.services.authentication": { - "version": "1.0.0-pre.3", + "version": "1.0.0-pre.4", "depth": 0, "source": "registry", "dependencies": { "com.unity.nuget.newtonsoft-json": "2.0.0", - "com.unity.services.core": "1.1.0-pre.7", + "com.unity.services.core": "1.1.0-pre.8", "com.unity.modules.unitywebrequest": "1.0.0" }, "url": "https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-candidates" }, "com.unity.services.core": { - "version": "1.1.0-pre.7", + "version": "1.1.0-pre.8", "depth": 0, "source": "registry", "dependencies": { From 90f619487045c13c694211d144594dad6e423248 Mon Sep 17 00:00:00 2001 From: Tyler Howard Date: Mon, 9 Aug 2021 14:23:09 -0400 Subject: [PATCH 3/5] DST-528: Removing minor changes that were erroneously left in when taking other approaches. --- testproject/Assets/Scripts/UIController.cs | 1 - testproject/Assets/Scripts/testproject.asmdef | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/testproject/Assets/Scripts/UIController.cs b/testproject/Assets/Scripts/UIController.cs index 678445a0c1..29752e65b8 100644 --- a/testproject/Assets/Scripts/UIController.cs +++ b/testproject/Assets/Scripts/UIController.cs @@ -14,7 +14,6 @@ public class UIController : MonoBehaviour public GameObject JoinCode; public UTPTransport Transport; - private string m_JoinCodeString; private void Awake() { diff --git a/testproject/Assets/Scripts/testproject.asmdef b/testproject/Assets/Scripts/testproject.asmdef index d1fe523b0b..d963bcca5c 100644 --- a/testproject/Assets/Scripts/testproject.asmdef +++ b/testproject/Assets/Scripts/testproject.asmdef @@ -13,7 +13,7 @@ ], "includePlatforms": [], "excludePlatforms": [], - "allowUnsafeCode": true, + "allowUnsafeCode": false, "overrideReferences": false, "precompiledReferences": [], "autoReferenced": true, From 897f72965a097d45617479efc29d2de51f099564 Mon Sep 17 00:00:00 2001 From: Tyler Howard Date: Tue, 10 Aug 2021 10:40:32 -0400 Subject: [PATCH 4/5] DST-528: Addressing minor code review changes. --- .../Runtime/UTPTransport.cs | 15 ++++++++------- testproject/Assets/Scripts/testproject.asmdef | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs index 84ae1799f0..56c0f8c3e1 100644 --- a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs +++ b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs @@ -53,9 +53,6 @@ private enum State private RelayServerData m_RelayServerData; - private static readonly RelayServerData k_DefaultRelayServerData = default(RelayServerData); - private static RelayServerData DefaultRelayServerData => k_DefaultRelayServerData; - private void InitDriver() { if (m_NetworkParameters.Count > 0) @@ -121,9 +118,11 @@ private IEnumerator ClientBindAndConnect(SocketTask task) { //This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use //reflection, but this does not live in the context of a performance-critical loop, it runs once at initial connection time. - if(m_RelayServerData.Equals(DefaultRelayServerData)) + if(m_RelayServerData.Equals(default(RelayServerData))) { - Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); + Debug.LogError("You must call SetRelayServerData() at least once before calling StartRelayServer."); + task.IsDone = true; + task.Success = false; yield break; } @@ -258,9 +257,11 @@ private IEnumerator StartRelayServer(SocketTask task) { //This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use //reflection, but this does not live in the context of a performance-critical loop, it runs once at initial connection time. - if (m_RelayServerData.Equals(DefaultRelayServerData)) + if (m_RelayServerData.Equals(default(RelayServerData))) { - Debug.LogError("You must set the RelayServerData property to something different from the default value before calling StartRelayServer."); + Debug.LogError("You must call SetRelayServerData() at least once before calling StartRelayServer."); + task.IsDone = true; + task.Success = false; yield break; } else diff --git a/testproject/Assets/Scripts/testproject.asmdef b/testproject/Assets/Scripts/testproject.asmdef index d963bcca5c..f03814a8f2 100644 --- a/testproject/Assets/Scripts/testproject.asmdef +++ b/testproject/Assets/Scripts/testproject.asmdef @@ -8,7 +8,6 @@ "Unity.Multiplayer.Transport.UTP", "Unity.Services.Authentication", "Unity.Services.Core", - "Unity.Networking.Transport", "Unity.Services.Relay" ], "includePlatforms": [], From 4526a37c5655c3c0b396c34b4da0d53bd64281b7 Mon Sep 17 00:00:00 2001 From: Tyler Howard Date: Tue, 10 Aug 2021 10:43:29 -0400 Subject: [PATCH 5/5] Revert "Revert "Feature/initial relay utp remove relay sdk calls (#1032)" (#1033)" This reverts commit cd545291db9e6fed5c08474cdc704397e2e271ca. --- testproject/Assets/Scripts/testproject.asmdef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testproject/Assets/Scripts/testproject.asmdef b/testproject/Assets/Scripts/testproject.asmdef index f03814a8f2..20d772ff3d 100644 --- a/testproject/Assets/Scripts/testproject.asmdef +++ b/testproject/Assets/Scripts/testproject.asmdef @@ -25,4 +25,4 @@ } ], "noEngineReferences": false -} \ No newline at end of file +}