From 97b4acd53f0139a21e7963db819bbfd4d54b1441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albin=20Cor=C3=A9n?= Date: Tue, 3 Sep 2019 20:07:37 +0200 Subject: [PATCH] fix: Removed alloc HandleIncomingData Fixes: #279 --- MLAPI/Core/NetworkingManager.cs | 214 +++++++++++++++---------------- MLAPI/Serialization/BitStream.cs | 19 ++- 2 files changed, 120 insertions(+), 113 deletions(-) diff --git a/MLAPI/Core/NetworkingManager.cs b/MLAPI/Core/NetworkingManager.cs index 0f36c0879f..5496ad706c 100644 --- a/MLAPI/Core/NetworkingManager.cs +++ b/MLAPI/Core/NetworkingManager.cs @@ -876,127 +876,127 @@ private void HandleRawTransportPoll(NetEventType eventType, ulong clientId, stri } } + private readonly BitStream inputStreamWrapper = new BitStream(new byte[0]); + private void HandleIncomingData(ulong clientId, string channelName, ArraySegment data, float receiveTime) { if (LogHelper.CurrentLogLevel <= LogLevel.Developer) LogHelper.LogInfo("Unwrapping Data Header"); - using (BitStream inputStream = new BitStream(data.Array)) - { - inputStream.SetLength(data.Count + data.Offset); - inputStream.Position = data.Offset; + inputStreamWrapper.SetTarget(data.Array); + inputStreamWrapper.SetLength(data.Count + data.Offset); + inputStreamWrapper.Position = data.Offset; - using (BitStream messageStream = MessagePacker.UnwrapMessage(inputStream, clientId, out byte messageType, out SecuritySendFlags security)) + using (BitStream messageStream = MessagePacker.UnwrapMessage(inputStreamWrapper, clientId, out byte messageType, out SecuritySendFlags security)) + { + if (messageStream == null) { - if (messageStream == null) - { - if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Message unwrap could not be completed. Was the header corrupt? Crypto error?"); - return; - } - else if (messageType == MLAPIConstants.INVALID) - { - if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Message unwrap read an invalid messageType"); - return; - } + if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Message unwrap could not be completed. Was the header corrupt? Crypto error?"); + return; + } + else if (messageType == MLAPIConstants.INVALID) + { + if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Message unwrap read an invalid messageType"); + return; + } - uint headerByteSize = (uint)Arithmetic.VarIntSize(messageType); - NetworkProfiler.StartEvent(TickType.Receive, (uint)(data.Count - headerByteSize), channelName, messageType); + uint headerByteSize = (uint)Arithmetic.VarIntSize(messageType); + NetworkProfiler.StartEvent(TickType.Receive, (uint)(data.Count - headerByteSize), channelName, messageType); - if (LogHelper.CurrentLogLevel <= LogLevel.Developer) LogHelper.LogInfo("Data Header: messageType=" + messageType); + if (LogHelper.CurrentLogLevel <= LogLevel.Developer) LogHelper.LogInfo("Data Header: messageType=" + messageType); - // Client tried to send a network message that was not the connection request before he was accepted. - if (IsServer && (NetworkConfig.EnableEncryption && PendingClients.ContainsKey(clientId) && PendingClients[clientId].ConnectionState == PendingClient.State.PendingHail && messageType != MLAPIConstants.MLAPI_CERTIFICATE_HAIL_RESPONSE) || - (PendingClients.ContainsKey(clientId) && PendingClients[clientId].ConnectionState == PendingClient.State.PendingConnection && messageType != MLAPIConstants.MLAPI_CONNECTION_REQUEST)) - { - if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Message recieved from clientId " + clientId + " before it has been accepted"); - return; - } + // Client tried to send a network message that was not the connection request before he was accepted. + if (IsServer && (NetworkConfig.EnableEncryption && PendingClients.ContainsKey(clientId) && PendingClients[clientId].ConnectionState == PendingClient.State.PendingHail && messageType != MLAPIConstants.MLAPI_CERTIFICATE_HAIL_RESPONSE) || + (PendingClients.ContainsKey(clientId) && PendingClients[clientId].ConnectionState == PendingClient.State.PendingConnection && messageType != MLAPIConstants.MLAPI_CONNECTION_REQUEST)) + { + if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Message recieved from clientId " + clientId + " before it has been accepted"); + return; + } - #region INTERNAL MESSAGE + #region INTERNAL MESSAGE - switch (messageType) - { - case MLAPIConstants.MLAPI_CONNECTION_REQUEST: - if (IsServer) - InternalMessageHandler.HandleConnectionRequest(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_CONNECTION_APPROVED: - if (IsClient) - InternalMessageHandler.HandleConnectionApproved(clientId, messageStream, receiveTime); - break; - case MLAPIConstants.MLAPI_ADD_OBJECT: - if (IsClient) InternalMessageHandler.HandleAddObject(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_DESTROY_OBJECT: - if (IsClient) InternalMessageHandler.HandleDestroyObject(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_SWITCH_SCENE: - if (IsClient) InternalMessageHandler.HandleSwitchScene(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_CHANGE_OWNER: - if (IsClient) InternalMessageHandler.HandleChangeOwner(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_ADD_OBJECTS: - if (IsClient) InternalMessageHandler.HandleAddObjects(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_DESTROY_OBJECTS: - if (IsClient) InternalMessageHandler.HandleDestroyObjects(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_TIME_SYNC: - if (IsClient) InternalMessageHandler.HandleTimeSync(clientId, messageStream, receiveTime); - break; - case MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA: - InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_NETWORKED_VAR_UPDATE: - InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_SERVER_RPC: - if (IsServer) InternalMessageHandler.HandleServerRPC(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_SERVER_RPC_REQUEST: - if (IsServer) InternalMessageHandler.HandleServerRPCRequest(clientId, messageStream, channelName, security); - break; - case MLAPIConstants.MLAPI_SERVER_RPC_RESPONSE: - if (IsClient) InternalMessageHandler.HandleServerRPCResponse(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_CLIENT_RPC: - if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_CLIENT_RPC_REQUEST: - if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security); - break; - case MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE: - if (IsServer) InternalMessageHandler.HandleClientRPCResponse(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_UNNAMED_MESSAGE: - InternalMessageHandler.HandleUnnamedMessage(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_NAMED_MESSAGE: - InternalMessageHandler.HandleNamedMessage(clientId, messageStream); - break; + switch (messageType) + { + case MLAPIConstants.MLAPI_CONNECTION_REQUEST: + if (IsServer) + InternalMessageHandler.HandleConnectionRequest(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_CONNECTION_APPROVED: + if (IsClient) + InternalMessageHandler.HandleConnectionApproved(clientId, messageStream, receiveTime); + break; + case MLAPIConstants.MLAPI_ADD_OBJECT: + if (IsClient) InternalMessageHandler.HandleAddObject(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_DESTROY_OBJECT: + if (IsClient) InternalMessageHandler.HandleDestroyObject(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_SWITCH_SCENE: + if (IsClient) InternalMessageHandler.HandleSwitchScene(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_CHANGE_OWNER: + if (IsClient) InternalMessageHandler.HandleChangeOwner(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_ADD_OBJECTS: + if (IsClient) InternalMessageHandler.HandleAddObjects(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_DESTROY_OBJECTS: + if (IsClient) InternalMessageHandler.HandleDestroyObjects(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_TIME_SYNC: + if (IsClient) InternalMessageHandler.HandleTimeSync(clientId, messageStream, receiveTime); + break; + case MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA: + InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_NETWORKED_VAR_UPDATE: + InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_SERVER_RPC: + if (IsServer) InternalMessageHandler.HandleServerRPC(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_SERVER_RPC_REQUEST: + if (IsServer) InternalMessageHandler.HandleServerRPCRequest(clientId, messageStream, channelName, security); + break; + case MLAPIConstants.MLAPI_SERVER_RPC_RESPONSE: + if (IsClient) InternalMessageHandler.HandleServerRPCResponse(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_CLIENT_RPC: + if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_CLIENT_RPC_REQUEST: + if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security); + break; + case MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE: + if (IsServer) InternalMessageHandler.HandleClientRPCResponse(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_UNNAMED_MESSAGE: + InternalMessageHandler.HandleUnnamedMessage(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_NAMED_MESSAGE: + InternalMessageHandler.HandleNamedMessage(clientId, messageStream); + break; #if !DISABLE_CRYPTOGRAPHY - case MLAPIConstants.MLAPI_CERTIFICATE_HAIL: - if (IsClient) InternalMessageHandler.HandleHailRequest(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_CERTIFICATE_HAIL_RESPONSE: - if (IsServer) InternalMessageHandler.HandleHailResponse(clientId, messageStream); - break; - case MLAPIConstants.MLAPI_GREETINGS: - if (IsClient) InternalMessageHandler.HandleGreetings(clientId, messageStream); - break; - #endif - case MLAPIConstants.MLAPI_CLIENT_SWITCH_SCENE_COMPLETED: - if (IsServer) InternalMessageHandler.HandleClientSwitchSceneCompleted(clientId, messageStream); - break; - default: - if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Read unrecognized messageType " + messageType); - break; - } + case MLAPIConstants.MLAPI_CERTIFICATE_HAIL: + if (IsClient) InternalMessageHandler.HandleHailRequest(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_CERTIFICATE_HAIL_RESPONSE: + if (IsServer) InternalMessageHandler.HandleHailResponse(clientId, messageStream); + break; + case MLAPIConstants.MLAPI_GREETINGS: + if (IsClient) InternalMessageHandler.HandleGreetings(clientId, messageStream); + break; +#endif + case MLAPIConstants.MLAPI_CLIENT_SWITCH_SCENE_COMPLETED: + if (IsServer) InternalMessageHandler.HandleClientSwitchSceneCompleted(clientId, messageStream); + break; + default: + if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogError("Read unrecognized messageType " + messageType); + break; + } - #endregion + #endregion - NetworkProfiler.EndEvent(); - } + NetworkProfiler.EndEvent(); } } diff --git a/MLAPI/Serialization/BitStream.cs b/MLAPI/Serialization/BitStream.cs index 86119b63bc..a9284bad74 100644 --- a/MLAPI/Serialization/BitStream.cs +++ b/MLAPI/Serialization/BitStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using static MLAPI.Serialization.Arithmetic; @@ -9,7 +9,7 @@ namespace MLAPI.Serialization /// A stream that can be used at the bit level /// public class BitStream : Stream - { + { const int initialCapacity = 16; const float initialGrowthFactor = 2.0f; private byte[] target; @@ -54,6 +54,13 @@ public BitStream(byte[] target) BitLength = (ulong)(target.Length << 3); } + internal void SetTarget(byte[] target) + { + this.target = target; + BitLength = (ulong)(target.Length << 3); + Position = 0; + } + /// /// Whether or not the stream will grow the buffer to accomodate more data. /// @@ -299,12 +306,12 @@ public override void Write(byte[] buffer, int offset, int count) public override void WriteByte(byte value) { // Check bit alignment. If misaligned, each byte written has to be misaligned - if (BitAligned) + if (BitAligned) { if (Position + 1 >= target.Length) Grow(1); target[Position] = value; Position += 1; - } + } else { if (Position + 1 + 1 >= target.Length) Grow(1); @@ -386,7 +393,7 @@ public void CopyFrom(Stream s, int count = -1) { long currentPosition = s.Position; s.Position = 0; - + int read; bool readToEnd = count < 0; while ((readToEnd || count-- > 0) && (read = s.ReadByte()) != -1) @@ -485,7 +492,7 @@ public void PadStream() WriteBit(false); } } - + /// /// Reads zeros until the the stream is byte aligned ///