From 469566c0e48c14edd673a2490828245c5feecded Mon Sep 17 00:00:00 2001 From: Skipcast Date: Sun, 16 Jan 2022 23:38:56 +0100 Subject: [PATCH] Fixed p2p related crash when multiple messages are received in a short amount of time --- JKMP.Plugin.Multiplayer/Networking/Framed.cs | 25 ++++++--- .../Networking/ReusableTCS.cs | 52 ------------------- 2 files changed, 19 insertions(+), 58 deletions(-) delete mode 100644 JKMP.Plugin.Multiplayer/Networking/ReusableTCS.cs diff --git a/JKMP.Plugin.Multiplayer/Networking/Framed.cs b/JKMP.Plugin.Multiplayer/Networking/Framed.cs index 3338b83..5262194 100644 --- a/JKMP.Plugin.Multiplayer/Networking/Framed.cs +++ b/JKMP.Plugin.Multiplayer/Networking/Framed.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -16,7 +17,8 @@ namespace JKMP.Plugin.Multiplayer.Networking { private bool isRunning = true; - private readonly ReusableTCS tcs = new(); + private TaskCompletionSource? tcs = new(); + private readonly Queue queuedMessages = new(); private readonly TCodec codec; private readonly byte[] sendBuffer = new byte[4096]; @@ -54,8 +56,9 @@ private async Task StartPolling() Logger.Error(ex, "An unhandled exception was raised when decoding message from {steamId}", packet.SteamId); continue; } - - await tcs.SetResult(message); + + queuedMessages.Enqueue(message); + tcs?.TrySetResult(true); } await Task.Delay(33).ConfigureAwait(false); // poll around 30 times per second @@ -73,9 +76,19 @@ private async Task StartPolling() if (!isRunning) return default; - await tcs; - TData? result = tcs.GetResult(); - tcs.Reset(); + if (tcs != null) + { + await tcs.Task; + tcs = null; + } + + TData result = queuedMessages.Dequeue(); + + if (queuedMessages.Count == 0) + { + tcs = new(); + } + return result; } diff --git a/JKMP.Plugin.Multiplayer/Networking/ReusableTCS.cs b/JKMP.Plugin.Multiplayer/Networking/ReusableTCS.cs deleted file mode 100644 index 93ca910..0000000 --- a/JKMP.Plugin.Multiplayer/Networking/ReusableTCS.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; - -namespace JKMP.Plugin.Multiplayer.Networking -{ - /// - /// A reusable task completion source - /// - internal class ReusableTCS : INotifyCompletion - { - private bool isCompleted; - private T? result; - - public bool IsCompleted => isCompleted; - - private Action? onCompleted; - - public void OnCompleted(Action continuation) - { - if (onCompleted != null) - throw new NotSupportedException("Multiple awaiters is not supported"); - - onCompleted = continuation; - } - - public void Reset() - { - isCompleted = false; - result = default; - onCompleted = null; - } - - public async Task SetResult(T? result) - { - if (isCompleted) - throw new InvalidOperationException("Result is already set. Make sure to call Reset before calling SetResult again."); - - this.result = result; - isCompleted = true; - - if (onCompleted != null) - await Task.Run(onCompleted).ConfigureAwait(false); - } - - public ReusableTCS GetAwaiter() => this; - - public T? GetResult() => result; - } -} \ No newline at end of file