Server LuaCsForBarotrauma
MessageDefragmenter.cs
1 using System.Collections.Generic;
2 using System.Collections.Immutable;
3 using System.Linq;
4 
5 namespace Barotrauma.Networking;
6 
7 sealed class MessageDefragmenter
8 {
9  private readonly Dictionary<ushort, MessageFragment[]> partialMessages = new Dictionary<ushort, MessageFragment[]>();
10 
11  public Option<ImmutableArray<byte>> ProcessIncomingFragment(MessageFragment fragment)
12  {
13  if (!partialMessages.ContainsKey(fragment.FragmentId.MessageId))
14  {
15  partialMessages[fragment.FragmentId.MessageId] = new MessageFragment[fragment.FragmentId.FragmentCount];
16  }
17  else if (partialMessages[fragment.FragmentId.MessageId].Length != fragment.FragmentId.FragmentCount)
18  {
19  DebugConsole.AddWarning($"Got a fragment for message {fragment.FragmentId.MessageId} " +
20  $"with a mismatched expected fragment count");
21  return Option.None;
22  }
23 
24  var fragmentBuffer = partialMessages[fragment.FragmentId.MessageId];
25  if (fragment.FragmentId.FragmentIndex >= fragmentBuffer.Length)
26  {
27  DebugConsole.AddWarning($"Got a fragment for message {fragment.FragmentId.MessageId} " +
28  $"with an index greater than or equal to the expected fragment count ({fragment.FragmentId.FragmentIndex} >= {fragmentBuffer.Length})");
29  return Option.None;
30  }
31 
32  fragmentBuffer[fragment.FragmentId.FragmentIndex] = fragment;
33  if (fragmentBuffer.All(f => !f.Data.IsDefault && f.FragmentId.MessageId == fragment.FragmentId.MessageId))
34  {
35  partialMessages.Remove(fragment.FragmentId.MessageId);
36  return Option.Some(fragmentBuffer.SelectMany(f => f.Data).ToImmutableArray());
37  }
38  return Option.None;
39  }
40 }
Option< ImmutableArray< byte > > ProcessIncomingFragment(MessageFragment fragment)