From 00f689ec01973688264ec371c3214a7bcf7b7e13 Mon Sep 17 00:00:00 2001 From: Andrew Spiering Date: Wed, 13 Oct 2021 17:34:28 -0700 Subject: [PATCH 1/4] fix: Fixing issue with adapter bugs --- .../Runtime/UnityTransport.cs | 55 +++++++++++-------- .../Components/NetworkTransform.cs | 4 +- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs index 742fee37df..c7a4e21093 100644 --- a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs +++ b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs @@ -43,14 +43,18 @@ private enum State [SerializeField] private ProtocolType m_ProtocolType; [SerializeField] private int m_MessageBufferSize = MaximumMessageLength; + + [Tooltip("The maximum size of possible fragmented packet")] + [SerializeField] private int m_FragmentationBufferSize = MaximumMessageLength; + [SerializeField] private int m_ReciveQueueSize = 128; [SerializeField] private int m_SendQueueSize = 128; [Tooltip("The maximum size of the send queue for batching Netcode events")] [SerializeField] private int m_SendQueueBatchSize = 4096; - [SerializeField] private string m_ServerAddress = "127.0.0.1"; - [SerializeField] private ushort m_ServerPort = 7777; + [SerializeField] + public NetworkEndPoint ConnectionData { get; private set; } private State m_State = State.Disconnected; private NetworkDriver m_Driver; @@ -171,7 +175,7 @@ private bool ClientBindAndConnect() } else { - serverEndpoint = NetworkEndPoint.Parse(m_ServerAddress, m_ServerPort); + serverEndpoint = ConnectionData; } InitDriver(); @@ -273,8 +277,15 @@ public void SetRelayServerData(string ipv4Address, ushort port, byte[] allocatio /// public void SetConnectionData(string ipv4Address, ushort port) { - m_ServerAddress = ipv4Address; - m_ServerPort = port; + ConnectionData = NetworkEndPoint.Parse(ipv4Address, port); + } + + /// + /// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call + /// + public void SetConnectionData(NetworkEndPoint endPoint) + { + ConnectionData = endPoint; } private bool StartRelayServer() @@ -372,25 +383,23 @@ private bool ProcessEvent() private unsafe void ReadData(int size, ref DataStreamReader reader, ref NetworkConnection networkConnection) { - if (size > m_MessageBufferSize) + if (size > m_FragmentationBufferSize + 128) { - Debug.LogError("The received message does not fit into the message buffer"); + Debug.LogError($"The received message does not fit into the message buffer {size} {m_MessageBufferSize}"); } else { unsafe { - fixed (byte* buffer = &m_MessageBuffer[0]) - { - reader.ReadBytes(buffer, size); - } + using var data = new NativeArray(size, Allocator.Temp); + reader.ReadBytes(data); + + InvokeOnTransportEvent(NetcodeNetworkEvent.Data, + ParseClientId(networkConnection), + new ArraySegment(data.ToArray(), 0, size), + Time.realtimeSinceStartup + ); } - - InvokeOnTransportEvent(NetcodeNetworkEvent.Data, - ParseClientId(networkConnection), - new ArraySegment(m_MessageBuffer, 0, size), - Time.realtimeSinceStartup - ); } } @@ -498,7 +507,7 @@ public override void Initialize() // 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. - var maxFragmentationCapacity = MaximumMessageLength + 128; + var maxFragmentationCapacity = m_FragmentationBufferSize + 128; m_NetworkParameters.Add(new FragmentationUtility.Parameters() { PayloadCapacity = maxFragmentationCapacity }); m_NetworkParameters.Add(new BaselibNetworkParameter() { @@ -506,8 +515,6 @@ public override void Initialize() receiveQueueCapacity = m_ReciveQueueSize, sendQueueCapacity = m_SendQueueSize }); - - m_MessageBuffer = new byte[m_MessageBufferSize]; } public override NetcodeNetworkEvent PollEvent(out ulong clientId, out ArraySegment payload, out float receiveTime) @@ -556,7 +563,6 @@ private unsafe void SendBatchedMessage(ulong clientId, ref NativeArray dat { var payloadSize = data.Length + 1; // One extra byte to mark whether this message is batched or not var result = m_Driver.BeginSend(pipeline, ParseClientId(clientId), out var writer, payloadSize); - if (result == 0) { if (data.IsCreated) @@ -573,13 +579,14 @@ private unsafe void SendBatchedMessage(ulong clientId, ref NativeArray dat } } - Debug.LogError($"Error sending the message {result}"); + Debug.LogError($"Error sending the message {result} {data.Length}"); } private unsafe void SendMessageInstantly(ulong clientId, ArraySegment data, NetworkPipeline pipeline) { var payloadSize = data.Count + 1 + 4; // 1 byte to indicate if the message is batched and 4 for the payload size var result = m_Driver.BeginSend(pipeline, ParseClientId(clientId), out var writer, payloadSize); + if (result == 0) { if (data.Array != null) @@ -604,7 +611,7 @@ private unsafe void SendMessageInstantly(ulong clientId, ArraySegment data } } - Debug.LogError($"Error sending the message {result}"); + Debug.LogError($"Error sending instantly the message {result} {data.Count}"); } /// @@ -657,7 +664,7 @@ public override bool StartServer() switch (m_ProtocolType) { case ProtocolType.UnityTransport: - return ServerBindAndListen(NetworkEndPoint.Parse(m_ServerAddress, m_ServerPort)); + return ServerBindAndListen(ConnectionData); case ProtocolType.RelayUnityTransport: return StartRelayServer(); default: diff --git a/com.unity.netcode.gameobjects/Components/NetworkTransform.cs b/com.unity.netcode.gameobjects/Components/NetworkTransform.cs index 72ac13de21..5333e9ef16 100644 --- a/com.unity.netcode.gameobjects/Components/NetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Components/NetworkTransform.cs @@ -681,7 +681,7 @@ private void OnNetworkStateChanged(NetworkTransformState oldState, NetworkTransf private void Awake() { - m_Transform = transform; + // ReplNetworkState.NetworkVariableChannel = NetworkChannel.PositionUpdate; // todo figure this out, talk with Matt/Fatih, this should be unreliable @@ -690,6 +690,8 @@ private void Awake() public override void OnNetworkSpawn() { + m_Transform = transform; + CanCommitToTransform = IsServer; m_CachedIsServer = IsServer; m_CachedNetworkManager = NetworkManager; From bb6d4c0143d349657bf7dd98f0aec615505487ab Mon Sep 17 00:00:00 2001 From: Andrew Spiering Date: Thu, 14 Oct 2021 13:00:06 -0700 Subject: [PATCH 2/4] Adding some error message resolution and cleanup serializedfields --- .../Runtime/UnityTransport.cs | 81 ++++++++++++++----- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs index c7a4e21093..17e1e7e61e 100644 --- a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs +++ b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs @@ -19,6 +19,49 @@ public interface INetworkStreamDriverConstructor void CreateDriver(UnityTransport transport, out NetworkDriver driver, out NetworkPipeline unreliableSequencedPipeline, out NetworkPipeline reliableSequencedPipeline, out NetworkPipeline reliableSequencedFragmentedPipeline); } + public static class ErrorUtilities + { + private const string k_NetworkSuccess = "Success"; + private const string k_NetworkIdMismatch = "NetworkId is invalid, likely caused by stale connection {0}."; + private const string k_NetworkVersionMismatch = "NetworkVersion is invalid, likely caused by stale connection {0}."; + private const string k_NetworkStateMismatch = "Sending data while connecting on connectionId{0} is now allowed"; + private const string k_NetworkPacketOverflow = "Unable to allocate packet due to buffer overflow."; + private const string k_NetworkSendQueueFull = "Currently unable to queue packet as there is too many inflight packets."; + private const string k_NetworkHeaderInvalid = "Invalid Unity Transport Protocol header."; + private const string k_NetworkDriverParallelForErr = "The parallel network driver needs to process a single unique connection per job, processing a single connection multiple times in a parallel for is not supported."; + private const string k_NetworkSendHandleInvalid = "Invalid NetworkInterface Send Handle. Likely caused by pipeline send data corruption."; + private const string k_NetworkArgumentMismatch = "Invalid NetworkEndpoint Arguments."; + + public static string ErrorToString(Networking.Transport.Error.StatusCode error, ulong connectionId) + { + switch (error) + { + case Networking.Transport.Error.StatusCode.Success: + return k_NetworkSuccess; + case Networking.Transport.Error.StatusCode.NetworkIdMismatch: + return string.Format(k_NetworkIdMismatch, connectionId); + case Networking.Transport.Error.StatusCode.NetworkVersionMismatch: + return string.Format(k_NetworkVersionMismatch, connectionId); + case Networking.Transport.Error.StatusCode.NetworkStateMismatch: + return string.Format(k_NetworkStateMismatch, connectionId); + case Networking.Transport.Error.StatusCode.NetworkPacketOverflow: + return k_NetworkPacketOverflow; + case Networking.Transport.Error.StatusCode.NetworkSendQueueFull: + return k_NetworkSendQueueFull; + case Networking.Transport.Error.StatusCode.NetworkHeaderInvalid: + return k_NetworkHeaderInvalid; + case Networking.Transport.Error.StatusCode.NetworkDriverParallelForErr: + return k_NetworkDriverParallelForErr; + case Networking.Transport.Error.StatusCode.NetworkSendHandleInvalid: + return k_NetworkSendHandleInvalid; + case Networking.Transport.Error.StatusCode.NetworkArgumentMismatch: + return k_NetworkArgumentMismatch; + } + + return $"Unknown ErrorCode {Enum.GetName(typeof(Networking.Transport.Error.StatusCode), error)}"; + } + } + public class UnityTransport : NetworkTransport, INetworkStreamDriverConstructor { public enum ProtocolType @@ -34,24 +77,25 @@ private enum State Connected, } - public const int MaximumMessageLength = 6 * 1024; + public const int InitialBatchQueueSize = 6 * 1024; + public const int InitialMaxPacketSize = NetworkParameterConstants.MTU; #pragma warning disable IDE1006 // Naming Styles public static INetworkStreamDriverConstructor s_DriverConstructor; #pragma warning restore IDE1006 // Naming Styles public INetworkStreamDriverConstructor DriverConstructor => s_DriverConstructor != null ? s_DriverConstructor : this; + [Tooltip("Which protocol should be selected Relay/Non-Relay")] [SerializeField] private ProtocolType m_ProtocolType; - [SerializeField] private int m_MessageBufferSize = MaximumMessageLength; - [Tooltip("The maximum size of possible fragmented packet")] - [SerializeField] private int m_FragmentationBufferSize = MaximumMessageLength; + [Tooltip("Maximum size in bytes for a given packet")] + [SerializeField] private int m_MaximumPacketSize = InitialMaxPacketSize; - [SerializeField] private int m_ReciveQueueSize = 128; - [SerializeField] private int m_SendQueueSize = 128; + [Tooltip("The maximum amount of packets that can be in the send/recv queues")] + [SerializeField] private int m_MaxPacketQueueSize = 128; - [Tooltip("The maximum size of the send queue for batching Netcode events")] - [SerializeField] private int m_SendQueueBatchSize = 4096; + [Tooltip("The maximum size in bytes of the send queue for batching Netcode events")] + [SerializeField] private int m_SendQueueBatchSize = InitialBatchQueueSize; [SerializeField] public NetworkEndPoint ConnectionData { get; private set; } @@ -383,9 +427,9 @@ private bool ProcessEvent() private unsafe void ReadData(int size, ref DataStreamReader reader, ref NetworkConnection networkConnection) { - if (size > m_FragmentationBufferSize + 128) + if (size > m_SendQueueBatchSize) { - Debug.LogError($"The received message does not fit into the message buffer {size} {m_MessageBufferSize}"); + Debug.LogError($"The received message does not fit into the message buffer: {size} {m_SendQueueBatchSize}"); } else { @@ -447,7 +491,6 @@ public override void DisconnectLocalClient() m_State = State.Disconnected; - // If we successfully disconnect we dispatch a local disconnect message // this how uNET and other transports worked and so this is just keeping with the old behavior // should be also noted on the client this will call shutdown on the NetworkManager and the Transport @@ -500,20 +543,19 @@ public override void Initialize() { Debug.Assert(sizeof(ulong) == UnsafeUtility.SizeOf(), "Netcode connection id size does not match UTP connection id size"); - Debug.Assert(m_MessageBufferSize > 5, "Message buffer size must be greater than 5"); + Debug.Assert(m_MaximumPacketSize > 5, "Message buffer size must be greater than 5"); 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. - var maxFragmentationCapacity = m_FragmentationBufferSize + 128; - m_NetworkParameters.Add(new FragmentationUtility.Parameters() { PayloadCapacity = maxFragmentationCapacity }); + m_NetworkParameters.Add(new FragmentationUtility.Parameters() { PayloadCapacity = m_SendQueueBatchSize }); m_NetworkParameters.Add(new BaselibNetworkParameter() { - maximumPayloadSize = (uint)m_MessageBufferSize, - receiveQueueCapacity = m_ReciveQueueSize, - sendQueueCapacity = m_SendQueueSize + maximumPayloadSize = (uint)m_MaximumPacketSize, + receiveQueueCapacity = m_MaxPacketQueueSize, + sendQueueCapacity = m_MaxPacketQueueSize }); } @@ -579,7 +621,7 @@ private unsafe void SendBatchedMessage(ulong clientId, ref NativeArray dat } } - Debug.LogError($"Error sending the message {result} {data.Length}"); + Debug.LogError($"Error sending the message: {ErrorUtilities.ErrorToString((Networking.Transport.Error.StatusCode)result, clientId)}"); } private unsafe void SendMessageInstantly(ulong clientId, ArraySegment data, NetworkPipeline pipeline) @@ -611,7 +653,7 @@ private unsafe void SendMessageInstantly(ulong clientId, ArraySegment data } } - Debug.LogError($"Error sending instantly the message {result} {data.Count}"); + Debug.LogError($"Error sending the message: {ErrorUtilities.ErrorToString((Networking.Transport.Error.StatusCode)result, clientId)}"); } /// @@ -750,7 +792,6 @@ public void CreateDriver(UnityTransport transport, out NetworkDriver driver, out } } - // -------------- Utility Types ------------------------------------------------------------------------------- /// From a19209fa9406d08b7d95d5b38ef43aefde34bc3a Mon Sep 17 00:00:00 2001 From: Andrew Spiering Date: Thu, 14 Oct 2021 16:49:17 -0700 Subject: [PATCH 3/4] fix: Adding a ConnectionAddressData wraper because NetworkEndpoint is not serializable. --- .../Runtime/UnityTransport.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs index 17e1e7e61e..381327941c 100644 --- a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs +++ b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs @@ -80,6 +80,9 @@ private enum State public const int InitialBatchQueueSize = 6 * 1024; public const int InitialMaxPacketSize = NetworkParameterConstants.MTU; + private static ConnectionAddressData s_DefaultConnectionAddressData = new ConnectionAddressData() + { Address = "127.0.0.1", Port = 7777 }; + #pragma warning disable IDE1006 // Naming Styles public static INetworkStreamDriverConstructor s_DriverConstructor; #pragma warning restore IDE1006 // Naming Styles @@ -97,8 +100,20 @@ private enum State [Tooltip("The maximum size in bytes of the send queue for batching Netcode events")] [SerializeField] private int m_SendQueueBatchSize = InitialBatchQueueSize; - [SerializeField] - public NetworkEndPoint ConnectionData { get; private set; } + [Serializable] + public struct ConnectionAddressData + { + [SerializeField] public string Address; + [SerializeField] public int Port; + + public static implicit operator NetworkEndPoint(ConnectionAddressData d) => + NetworkEndPoint.Parse(d.Address, (ushort)d.Port); + + public static implicit operator ConnectionAddressData(NetworkEndPoint d) => + new ConnectionAddressData() { Address = d.Address.Split(':')[0], Port = d.Port }; + } + + public ConnectionAddressData ConnectionData = s_DefaultConnectionAddressData; private State m_State = State.Disconnected; private NetworkDriver m_Driver; @@ -321,7 +336,8 @@ public void SetRelayServerData(string ipv4Address, ushort port, byte[] allocatio /// public void SetConnectionData(string ipv4Address, ushort port) { - ConnectionData = NetworkEndPoint.Parse(ipv4Address, port); + ConnectionData.Address = ipv4Address; + ConnectionData.Port = port; } /// From af2d703c6362193f47471b2f134b9a6e2c127c6b Mon Sep 17 00:00:00 2001 From: Andrew Spiering Date: Thu, 14 Oct 2021 17:19:45 -0700 Subject: [PATCH 4/4] fix: Fix test --- .../Tests/Runtime/Helpers/DriverClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.adapter.utp/Tests/Runtime/Helpers/DriverClient.cs b/com.unity.netcode.adapter.utp/Tests/Runtime/Helpers/DriverClient.cs index 8f577cb61b..79d6c67afc 100644 --- a/com.unity.netcode.adapter.utp/Tests/Runtime/Helpers/DriverClient.cs +++ b/com.unity.netcode.adapter.utp/Tests/Runtime/Helpers/DriverClient.cs @@ -35,7 +35,7 @@ public class DriverClient : MonoBehaviour private void Awake() { - var maxCap = UnityTransport.MaximumMessageLength + 128; + var maxCap = UnityTransport.InitialBatchQueueSize + 128; var fragParams = new FragmentationUtility.Parameters() { PayloadCapacity = maxCap }; m_Driver = NetworkDriver.Create(fragParams);