Skip to content

Commit 6a91a01

Browse files
committed
fixed a bug about handling close handshake when PackageHandler is in use
1 parent 70c38a0 commit 6a91a01

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

src/WebSocket4Net/WebSocket.cs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ public class WebSocket : EasyClient<WebSocketPackage>, IWebSocket
2424
private static readonly Encoding _utf8Encoding = new UTF8Encoding(false);
2525
private const string _magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
2626

27+
private TaskCompletionSource<WebSocketPackage> _closePackageReceivedTaskSource;
28+
29+
private bool _packageHandlerMode = false;
30+
2731
public Uri Uri { get; private set; }
2832

2933
public bool AutoPingEnabled { get; set; }
@@ -220,7 +224,11 @@ private void WriteHandshakeRequest(PipeWriter writer, string secKey)
220224
writer.Write("\r\n", _asciiEncoding);
221225
}
222226

223-
public new void StartReceive() => base.StartReceive();
227+
public new void StartReceive()
228+
{
229+
base.StartReceive();
230+
_packageHandlerMode = true;
231+
}
224232

225233
public new async ValueTask<WebSocketPackage> ReceiveAsync()
226234
=> await ReceiveAsync(
@@ -229,6 +237,11 @@ private void WriteHandshakeRequest(PipeWriter writer, string secKey)
229237

230238
internal async ValueTask<WebSocketPackage> ReceiveAsync(bool handleControlPackage, bool returnControlPackage)
231239
{
240+
if (_packageHandlerMode)
241+
{
242+
throw new InvalidOperationException($"You cannot call the method {nameof(ReceiveAsync)} if you already setup the client to process packages by PackageHandler.");
243+
}
244+
232245
var package = await base.ReceiveAsync();
233246

234247
if (package == null)
@@ -254,6 +267,15 @@ protected override async ValueTask OnPackageReceived(WebSocketPackage package)
254267
{
255268
if (package.OpCode != OpCode.Binary && package.OpCode != OpCode.Text)
256269
{
270+
if (package.OpCode == OpCode.Close && _closePackageReceivedTaskSource is TaskCompletionSource<WebSocketPackage> closePackageReceivedTaskSource)
271+
{
272+
if (Interlocked.CompareExchange(ref _closePackageReceivedTaskSource, null, closePackageReceivedTaskSource) == closePackageReceivedTaskSource)
273+
{
274+
closePackageReceivedTaskSource.SetResult(package);
275+
return;
276+
}
277+
}
278+
257279
await HandleControlPackage(package);
258280
return;
259281
}
@@ -349,14 +371,21 @@ public async ValueTask CloseAsync(CloseReason closeReason, string message = null
349371
Reason = closeReason,
350372
ReasonText = message
351373
};
374+
375+
var closePackageReceivedTaskSource = default(TaskCompletionSource<WebSocketPackage>);
376+
377+
if (_packageHandlerMode)
378+
{
379+
closePackageReceivedTaskSource = _closePackageReceivedTaskSource = new ();
380+
}
352381

353382
await SendAsync(_packageEncoder, package);
354383

355384
State = WebSocketState.CloseSent;
356385

357-
var closeHandshakeResponse = await ReceiveAsync(
358-
handleControlPackage: false,
359-
returnControlPackage: true);
386+
var closeHandshakeResponse = closePackageReceivedTaskSource != null
387+
? await closePackageReceivedTaskSource.Task
388+
: await ReceiveAsync(handleControlPackage: false, returnControlPackage: true);
360389

361390
if (closeHandshakeResponse.OpCode != OpCode.Close)
362391
{

0 commit comments

Comments
 (0)