using FishNet.Serializing; using System; using GameKit.Dependencies.Utilities; using UnityEngine; namespace FishNet.Managing.Transporting { internal class SplitReader : IResettable { #region Private. /// /// Writer containing the combined split packet. /// private readonly PooledWriter _writer = new(); /// /// Expected number of splits. /// private int _expectedMessages; /// /// Number of splits received so far. /// private ushort _receivedMessages; /// /// The maximum allowed bytes which can be read. This acts as a guard against overflow. /// private uint _maximumClientBytes; /// /// NetworkManager for this. /// private NetworkManager _networkManager; /// /// True if the sender of the split packet is a client. /// /// private bool _isSenderClient; #endregion public void Initialize(NetworkManager networkManager, uint maximumClientBytes, bool isSenderClient, int expectedMessages) { _networkManager = networkManager; _maximumClientBytes = maximumClientBytes; _isSenderClient = isSenderClient; _expectedMessages = expectedMessages; /* This is just a guess as to how large the end * message could be. If the writer is not the minimum * of this length then resize it. */ int estimatedBufferSize = expectedMessages * 1500; if (_writer.Capacity < estimatedBufferSize) _writer.EnsureBufferCapacity(estimatedBufferSize); } /// /// Combines split data. /// internal bool Write(PooledReader reader) { if (_isSenderClient) { long totalBytes = _writer.Length + reader.Remaining; if (totalBytes > _maximumClientBytes) { _networkManager.LogError($"A split packet of [{totalBytes}] exceeds the maximum allowed bytes of [{_maximumClientBytes}]."); return false; } } /* Empty remainder of reader into the writer. * It does not matter if parts of the reader * contain data added after the split because * once the split is fully combined the data * is parsed as though it came in as one message, * which is how data is normally read. */ ArraySegment data = reader.ReadArraySegment(reader.Remaining); _writer.WriteArraySegment(data); _receivedMessages++; return true; } /// /// Returns if all split messages have been received. /// /// internal bool TryGetFullMessage(out ArraySegment segment) { if (_receivedMessages < _expectedMessages) { segment = ArraySegment.Empty; return false; } segment = _writer.GetArraySegment(); return true; } public void ResetState() { _writer.Clear(); _expectedMessages = 0; _receivedMessages = 0; _maximumClientBytes = 0; _networkManager = null; } public void InitializeState() { } } }