private bool ReadFragments() { if (Header.HasFlag(PacketHeaderFlags.BlobFragments)) { while (DataReader.BaseStream.Position != DataReader.BaseStream.Length) { try { var fragment = new ClientPacketFragment(); if (!fragment.Unpack(DataReader)) { return(false); } Fragments.Add(fragment); } catch (Exception) { // corrupt packet return(false); } } } return(true); }
/// <summary> /// Processes a fragment, combining split fragments as needed, then handling them /// </summary> /// <param name="fragment">ClientPacketFragment to process</param> private void ProcessFragment(ClientPacketFragment fragment) { packetLog.DebugFormat("[{0}] Processing fragment {1}", session.LoggingIdentifier, fragment.Header.Sequence); ClientMessage message = null; // Check if this fragment is split if (fragment.Header.Count != 1) { // Packet is split packetLog.DebugFormat("[{0}] Fragment {1} is split, this index {2} of {3} fragments", session.LoggingIdentifier, fragment.Header.Sequence, fragment.Header.Index, fragment.Header.Count); if (partialFragments.TryGetValue(fragment.Header.Sequence, out var buffer)) { // Existing buffer, add this to it and check if we are finally complete. buffer.AddFragment(fragment); packetLog.DebugFormat("[{0}] Added fragment {1} to existing buffer. Buffer at {2} of {3}", session.LoggingIdentifier, fragment.Header.Sequence, buffer.Count, buffer.TotalFragments); if (buffer.Complete) { // The buffer is complete, so we can go ahead and handle packetLog.DebugFormat("[{0}] Buffer {1} is complete", session.LoggingIdentifier, buffer.Sequence); message = buffer.GetMessage(); MessageBuffer removed = null; partialFragments.TryRemove(fragment.Header.Sequence, out removed); } } else { // No existing buffer, so add a new one for this fragment sequence. packetLog.DebugFormat("[{0}] Creating new buffer {1} for this split fragment", session.LoggingIdentifier, fragment.Header.Sequence); var newBuffer = new MessageBuffer(fragment.Header.Sequence, fragment.Header.Count); newBuffer.AddFragment(fragment); packetLog.DebugFormat("[{0}] Added fragment {1} to the new buffer. Buffer at {2} of {3}", session.LoggingIdentifier, fragment.Header.Sequence, newBuffer.Count, newBuffer.TotalFragments); partialFragments.TryAdd(fragment.Header.Sequence, newBuffer); } } else { // Packet is not split, proceed with handling it. packetLog.DebugFormat("[{0}] Fragment {1} is not split", session.LoggingIdentifier, fragment.Header.Sequence); message = new ClientMessage(fragment.Data); } // If message is not null, we have a complete message to handle if (message != null) { // First check if this message is the next sequence, if it is not, add it to our outOfOrderFragments if (fragment.Header.Sequence == lastReceivedFragmentSequence + 1) { packetLog.DebugFormat("[{0}] Handling fragment {1}", session.LoggingIdentifier, fragment.Header.Sequence); HandleFragment(message); } else { packetLog.DebugFormat("[{0}] Fragment {1} is early, lastReceivedFragmentSequence = {2}", session.LoggingIdentifier, fragment.Header.Sequence, lastReceivedFragmentSequence); outOfOrderFragments.TryAdd(fragment.Header.Sequence, message); } } }
public void AddFragment(ClientPacketFragment fragment) { lock (fragments) { if (!Complete && !fragments.Any(x => x.Header.Index == fragment.Header.Index)) { fragments.Add(fragment); } } }