Skip to content

Commit c4c4c65

Browse files
bajasoftjan-bajer
authored andcommitted
Add missing handshake messages when upgrading to WebSocket, fixes #380
1 parent a20f828 commit c4c4c65

File tree

5 files changed

+77
-6
lines changed

5 files changed

+77
-6
lines changed

src/SocketIO.Serializer.Core/ISerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Collections.Generic;
32
using SocketIO.Core;
43

@@ -19,6 +18,7 @@ public interface ISerializer
1918
SerializedItem SerializeConnectedMessage(EngineIO eio, string ns, object auth, IEnumerable<KeyValuePair<string, string>> queries);
2019

2120
SerializedItem SerializePingMessage();
21+
SerializedItem SerializePingProbeMessage();
2222
SerializedItem SerializePongMessage();
2323
SerializedItem SerializeUpgradeMessage();
2424
}

src/SocketIO.Serializer.MessagePack/SocketIOMessagePackSerializer.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ public SerializedItem SerializePingMessage()
257257
};
258258
}
259259

260+
public SerializedItem SerializePingProbeMessage()
261+
{
262+
return new SerializedItem
263+
{
264+
Text = "2probe"
265+
};
266+
}
267+
260268
public SerializedItem SerializePongMessage()
261269
{
262270
return new SerializedItem

src/SocketIO.Serializer.NewtonsoftJson/NewtonsoftJsonSerializer.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ public SerializedItem SerializePingMessage()
220220
};
221221
}
222222

223+
public SerializedItem SerializePingProbeMessage()
224+
{
225+
return new SerializedItem
226+
{
227+
Text = "2probe"
228+
};
229+
}
230+
223231
public SerializedItem SerializePongMessage()
224232
{
225233
return new SerializedItem
@@ -309,6 +317,7 @@ private static void ReadMessage(IMessage message, EngineIO eio, string text)
309317
case MessageType.Ping:
310318
break;
311319
case MessageType.Pong:
320+
ReadPongMessage(message, text);
312321
break;
313322
case MessageType.Connected:
314323
ReadConnectedMessage(message, text, eio);
@@ -336,6 +345,11 @@ private static void ReadMessage(IMessage message, EngineIO eio, string text)
336345
}
337346
}
338347

348+
private static void ReadPongMessage(IMessage message, string text)
349+
{
350+
message.ReceivedText = text;
351+
}
352+
339353
private static void ReadOpenedMessage(IMessage message, string text)
340354
{
341355
JsonConvert.PopulateObject(text, message, new JsonSerializerSettings

src/SocketIO.Serializer.SystemTextJson/SystemTextJsonSerializer.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ public SerializedItem SerializePingMessage()
220220
};
221221
}
222222

223+
public SerializedItem SerializePingProbeMessage()
224+
{
225+
return new SerializedItem
226+
{
227+
Text = "2probe"
228+
};
229+
}
230+
223231
public SerializedItem SerializeUpgradeMessage()
224232
{
225233
return new SerializedItem
@@ -316,6 +324,7 @@ private static void ReadMessage(IMessage message, EngineIO eio, string text)
316324
case MessageType.Ping:
317325
break;
318326
case MessageType.Pong:
327+
ReadPongMessage(message, text);
319328
break;
320329
case MessageType.Connected:
321330
ReadConnectedMessage(message, text, eio);
@@ -343,6 +352,11 @@ private static void ReadMessage(IMessage message, EngineIO eio, string text)
343352
}
344353
}
345354

355+
private static void ReadPongMessage(IMessage message, string text)
356+
{
357+
message.ReceivedText = text;
358+
}
359+
346360
private static void ReadOpenedMessage(IMessage message, string text)
347361
{
348362
// TODO: Should deserializing to existing object

src/SocketIOClient/SocketIO.cs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,16 +320,51 @@ private async Task UpgradeToWebSocket(IMessage openedMessage)
320320
{
321321
var options = NewTransportOptions();
322322
options.OpenedMessage = openedMessage;
323+
323324
for (var i = 0; i < 3; i++)
324325
{
325-
var transport = (WebSocketTransport)NewTransport(TransportProtocol.WebSocket, options);
326-
using var cts = new CancellationTokenSource(Options.ConnectionTimeout);
326+
WebSocketTransport transport = (WebSocketTransport)NewTransport(TransportProtocol.WebSocket, options);
327+
328+
TaskCompletionSource<bool> pongProbeTcs = new();
329+
using CancellationTokenSource connectionTimeoutCts = new(Options.ConnectionTimeout);
330+
CancellationToken connectionTimeoutToken = connectionTimeoutCts.Token;
331+
332+
connectionTimeoutToken.Register(() =>
333+
{
334+
pongProbeTcs.TrySetException(new TimeoutException("The upgrade operation has timed out!"));
335+
});
336+
327337
try
328338
{
329-
await transport.ConnectAsync(cts.Token).ConfigureAwait(false);
330-
var message = Serializer.SerializeUpgradeMessage();
339+
await transport.ConnectAsync(connectionTimeoutToken).ConfigureAwait(false);
340+
341+
void pongProbeHandler(IMessage msg)
342+
{
343+
if (msg.Type == MessageType.Pong && msg.ReceivedText == "probe")
344+
{
345+
pongProbeTcs.SetResult(true);
346+
}
347+
else
348+
{
349+
pongProbeTcs.SetException(new Exception($"Unexpected handshake response: '{msg.Type}'"));
350+
}
351+
}
352+
353+
transport.OnReceived += pongProbeHandler;
354+
355+
SerializedItem message = Serializer.SerializePingProbeMessage();
356+
357+
await transport
358+
.SendAsync(new List<SerializedItem> { message }, connectionTimeoutToken)
359+
.ConfigureAwait(false);
360+
361+
await pongProbeTcs.Task;
362+
363+
transport.OnReceived -= pongProbeHandler;
364+
365+
message = Serializer.SerializeUpgradeMessage();
331366
await transport
332-
.SendAsync(new List<SerializedItem> { message }, cts.Token)
367+
.SendAsync(new List<SerializedItem> { message }, connectionTimeoutToken)
333368
.ConfigureAwait(false);
334369

335370
Transport.Dispose();

0 commit comments

Comments
 (0)