Skip to content

Commit 6824ee2

Browse files
committed
Extended payload length bug. #229
1 parent 9fe246c commit 6824ee2

9 files changed

+74
-53
lines changed

source/NetCoreServer/IWebSocket.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ void OnWsReceived(byte[] buffer, long offset, long size) {}
5353
/// <param name="buffer">Received buffer</param>
5454
/// <param name="offset">Received buffer offset</param>
5555
/// <param name="size">Received buffer size</param>
56-
void OnWsClose(byte[] buffer, long offset, long size) {}
56+
/// <param name="status">WebSocket close status (default is 1000)</param>
57+
void OnWsClose(byte[] buffer, long offset, long size, int status = 1000) {}
5758

5859
/// <summary>
5960
/// Handle WebSocket ping notification

source/NetCoreServer/NetCoreServer.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>6.6.0.0</Version>
5+
<Version>6.7.0.0</Version>
66
<Authors>Ivan Shynkarenka</Authors>
77
<Copyright>Copyright (c) 2019-2022 Ivan Shynkarenka</Copyright>
88
<RepositoryUrl>https://github.com/chronoxor/NetCoreServer</RepositoryUrl>

source/NetCoreServer/UdpClient.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ public virtual long Send(EndPoint endpoint, ReadOnlySpan<byte> buffer)
457457
try
458458
{
459459
// Sent datagram to the server
460-
int sent = Socket.SendTo(buffer, SocketFlags.None, endpoint);
460+
long sent = Socket.SendTo(buffer, SocketFlags.None, endpoint);
461461
if (sent > 0)
462462
{
463463
// Update statistic
@@ -632,7 +632,7 @@ public virtual long Receive(ref EndPoint endpoint, byte[] buffer, long offset, l
632632
try
633633
{
634634
// Receive datagram from the server
635-
int received = Socket.ReceiveFrom(buffer, (int)offset, (int)size, SocketFlags.None, ref endpoint);
635+
long received = Socket.ReceiveFrom(buffer, (int)offset, (int)size, SocketFlags.None, ref endpoint);
636636

637637
// Update statistic
638638
DatagramsReceived++;

source/NetCoreServer/UdpServer.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ public virtual long Send(EndPoint endpoint, ReadOnlySpan<byte> buffer)
473473
try
474474
{
475475
// Sent datagram to the client
476-
int sent = Socket.SendTo(buffer, SocketFlags.None, endpoint);
476+
long sent = Socket.SendTo(buffer, SocketFlags.None, endpoint);
477477
if (sent > 0)
478478
{
479479
// Update statistic
@@ -610,7 +610,7 @@ public virtual long Receive(ref EndPoint endpoint, byte[] buffer, long offset, l
610610
try
611611
{
612612
// Receive datagram from the client
613-
int received = Socket.ReceiveFrom(buffer, (int)offset, (int)size, SocketFlags.None, ref endpoint);
613+
long received = Socket.ReceiveFrom(buffer, (int)offset, (int)size, SocketFlags.None, ref endpoint);
614614

615615
// Update statistic
616616
DatagramsReceived++;

source/NetCoreServer/WebSocket.cs

+47-27
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ public bool PerformServerUpgrade(HttpRequest request, HttpResponse response)
253253
/// <param name="status">WebSocket status (default is 0)</param>
254254
public void PrepareSendFrame(byte opcode, bool mask, ReadOnlySpan<byte> buffer, int status = 0)
255255
{
256-
int size = buffer.Length;
256+
long size = (((opcode & WS_CLOSE) == WS_CLOSE) && (buffer.Length > 0)) ? (buffer.Length + 2) : buffer.Length;
257257

258258
// Clear the previous WebSocket send buffer
259259
WsSendBuffer.Clear();
@@ -263,7 +263,7 @@ public void PrepareSendFrame(byte opcode, bool mask, ReadOnlySpan<byte> buffer,
263263

264264
// Append WebSocket frame size
265265
if (size <= 125)
266-
WsSendBuffer.Append((byte)((size & 0xFF) | (mask ? 0x80 : 0)));
266+
WsSendBuffer.Append((byte)(((int)size & 0xFF) | (mask ? 0x80 : 0)));
267267
else if (size <= 65535)
268268
{
269269
WsSendBuffer.Append((byte)(126 | (mask ? 0x80 : 0)));
@@ -284,11 +284,21 @@ public void PrepareSendFrame(byte opcode, bool mask, ReadOnlySpan<byte> buffer,
284284
}
285285

286286
// Resize WebSocket frame buffer
287-
int offset = (int)WsSendBuffer.Size;
287+
long offset = WsSendBuffer.Size;
288288
WsSendBuffer.Resize(WsSendBuffer.Size + size);
289289

290+
int index = 0;
291+
292+
// Append WebSocket close status
293+
if (((opcode & WS_CLOSE) == WS_CLOSE) && (buffer.Length > 0))
294+
{
295+
index += 2;
296+
WsSendBuffer.Append((byte)((status >> 8) & 0xFF));
297+
WsSendBuffer.Append((byte)(status & 0xFF));
298+
}
299+
290300
// Mask WebSocket frame content
291-
for (int i = 0; i < size; i++)
301+
for (int i = index; i < size; i++)
292302
WsSendBuffer.Data[offset + i] = (byte)(buffer[i] ^ WsSendMask[i % 4]);
293303
}
294304

@@ -302,7 +312,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
302312
{
303313
lock (WsReceiveLock)
304314
{
305-
var index = 0;
315+
int index = 0;
306316

307317
// Clear received data after WebSocket frame was processed
308318
if (WsFrameReceived)
@@ -339,7 +349,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
339349
// Prepare WebSocket frame opcode and mask flag
340350
if (WsReceiveFrameBuffer.Size < 2)
341351
{
342-
for (int i = 0; i < 2; i++, index++, size--)
352+
for (long i = 0; i < 2; i++, index++, size--)
343353
{
344354
if (size == 0)
345355
return;
@@ -350,7 +360,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
350360
byte opcode = (byte)(WsReceiveFrameBuffer[0] & 0x0F);
351361
bool fin = ((WsReceiveFrameBuffer[0] >> 7) & 0x01) != 0;
352362
bool mask = ((WsReceiveFrameBuffer[1] >> 7) & 0x01) != 0;
353-
int payload = WsReceiveFrameBuffer[1] & (~0x80);
363+
long payload = WsReceiveFrameBuffer[1] & (~0x80);
354364

355365
// Prepare WebSocket opcode
356366
WsOpcode = (opcode != 0) ? opcode : WsOpcode;
@@ -365,7 +375,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
365375
{
366376
if (WsReceiveFrameBuffer.Size < 4)
367377
{
368-
for (int i = 0; i < 2; i++, index++, size--)
378+
for (long i = 0; i < 2; i++, index++, size--)
369379
{
370380
if (size == 0)
371381
return;
@@ -381,7 +391,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
381391
{
382392
if (WsReceiveFrameBuffer.Size < 10)
383393
{
384-
for (int i = 0; i < 8; i++, index++, size--)
394+
for (long i = 0; i < 8; i++, index++, size--)
385395
{
386396
if (size == 0)
387397
return;
@@ -399,7 +409,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
399409
{
400410
if (WsReceiveFrameBuffer.Size < WsHeaderSize)
401411
{
402-
for (int i = 0; i < 4; i++, index++, size--)
412+
for (long i = 0; i < 4; i++, index++, size--)
403413
{
404414
if (size == 0)
405415
return;
@@ -409,12 +419,12 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
409419
}
410420
}
411421

412-
int total = WsHeaderSize + WsPayloadSize;
413-
int length = Math.Min(total - (int)WsReceiveFrameBuffer.Size, (int)size);
422+
long total = WsHeaderSize + WsPayloadSize;
423+
long length = Math.Min(total - WsReceiveFrameBuffer.Size, size);
414424

415425
// Prepare WebSocket frame payload
416-
WsReceiveFrameBuffer.Append(buffer[((int)offset + index)..((int)offset + index + length)]);
417-
index += length;
426+
WsReceiveFrameBuffer.Append(buffer[((int)offset + index)..((int)offset + index + (int)length)]);
427+
index += (int)length;
418428
size -= length;
419429

420430
// Process WebSocket frame
@@ -423,11 +433,11 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
423433
// Unmask WebSocket frame content
424434
if (mask)
425435
{
426-
for (int i = 0; i < WsPayloadSize; i++)
436+
for (long i = 0; i < WsPayloadSize; i++)
427437
WsReceiveFinalBuffer.Append((byte)(WsReceiveFrameBuffer[WsHeaderSize + i] ^ WsReceiveMask[i % 4]));
428438
}
429439
else
430-
WsReceiveFinalBuffer.Append(WsReceiveFrameBuffer.AsSpan().Slice(WsHeaderSize, WsPayloadSize));
440+
WsReceiveFinalBuffer.Append(WsReceiveFrameBuffer.AsSpan().Slice((int)WsHeaderSize, (int)WsPayloadSize));
431441

432442
WsFrameReceived = true;
433443

@@ -452,8 +462,18 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
452462
}
453463
case WS_CLOSE:
454464
{
465+
int sindex = 0;
466+
int status = 1000;
467+
468+
// Read WebSocket close status
469+
if (WsReceiveFinalBuffer.Size > 2)
470+
{
471+
sindex += 2;
472+
status = ((WsReceiveFinalBuffer[0] << 8) | (WsReceiveFinalBuffer[1] << 0));
473+
}
474+
455475
// Call the WebSocket close handler
456-
_wsHandler.OnWsClose(WsReceiveFinalBuffer.Data, 0, WsReceiveFinalBuffer.Size);
476+
_wsHandler.OnWsClose(WsReceiveFinalBuffer.Data, sindex, WsReceiveFinalBuffer.Size - sindex, status);
457477
break;
458478
}
459479
case WS_BINARY:
@@ -473,7 +493,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
473493
/// <summary>
474494
/// Required WebSocket receive frame size
475495
/// </summary>
476-
public int RequiredReceiveFrameSize()
496+
public long RequiredReceiveFrameSize()
477497
{
478498
lock (WsReceiveLock)
479499
{
@@ -482,23 +502,23 @@ public int RequiredReceiveFrameSize()
482502

483503
// Required WebSocket frame opcode and mask flag
484504
if (WsReceiveFrameBuffer.Size < 2)
485-
return 2 - (int)WsReceiveFrameBuffer.Size;
505+
return 2 - WsReceiveFrameBuffer.Size;
486506

487507
bool mask = ((WsReceiveFrameBuffer[1] >> 7) & 0x01) != 0;
488-
int payload = WsReceiveFrameBuffer[1] & (~0x80);
508+
long payload = WsReceiveFrameBuffer[1] & (~0x80);
489509

490510
// Required WebSocket frame size
491511
if ((payload == 126) && (WsReceiveFrameBuffer.Size < 4))
492-
return 4 - (int)WsReceiveFrameBuffer.Size;
512+
return 4 - WsReceiveFrameBuffer.Size;
493513
if ((payload == 127) && (WsReceiveFrameBuffer.Size < 10))
494-
return 10 - (int)WsReceiveFrameBuffer.Size;
514+
return 10 - WsReceiveFrameBuffer.Size;
495515

496516
// Required WebSocket frame mask
497517
if ((mask) && (WsReceiveFrameBuffer.Size < WsHeaderSize))
498-
return WsHeaderSize - (int)WsReceiveFrameBuffer.Size;
518+
return WsHeaderSize - WsReceiveFrameBuffer.Size;
499519

500520
// Required WebSocket frame payload
501-
return WsHeaderSize + WsPayloadSize - (int)WsReceiveFrameBuffer.Size;
521+
return WsHeaderSize + WsPayloadSize - WsReceiveFrameBuffer.Size;
502522
}
503523
}
504524

@@ -561,15 +581,15 @@ public void ClearWsBuffers()
561581
/// <summary>
562582
/// Received frame opcode
563583
/// </summary>
564-
internal int WsOpcode;
584+
internal byte WsOpcode;
565585
/// <summary>
566586
/// Received frame header size
567587
/// </summary>
568-
internal int WsHeaderSize;
588+
internal long WsHeaderSize;
569589
/// <summary>
570590
/// Received frame payload size
571591
/// </summary>
572-
internal int WsPayloadSize;
592+
internal long WsPayloadSize;
573593

574594
/// <summary>
575595
/// Receive buffer lock

source/NetCoreServer/WsClient.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ public string ReceiveText()
220220
{
221221
while (!WebSocket.WsFrameReceived)
222222
{
223-
int required = WebSocket.RequiredReceiveFrameSize();
223+
long required = WebSocket.RequiredReceiveFrameSize();
224224
cache.Resize(required);
225-
int received = (int)base.Receive(cache.Data, 0, required);
225+
long received = base.Receive(cache.Data, 0, required);
226226
if (received != required)
227227
return result.ExtractString(0, result.Data.Length);
228228
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -251,9 +251,9 @@ public Buffer ReceiveBinary()
251251
{
252252
while (!WebSocket.WsFrameReceived)
253253
{
254-
int required = WebSocket.RequiredReceiveFrameSize();
254+
long required = WebSocket.RequiredReceiveFrameSize();
255255
cache.Resize(required);
256-
int received = (int)base.Receive(cache.Data, 0, required);
256+
long received = base.Receive(cache.Data, 0, required);
257257
if (received != required)
258258
return result;
259259
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -378,7 +378,7 @@ public virtual void OnWsConnected(HttpRequest request) {}
378378
public virtual void OnWsDisconnecting() {}
379379
public virtual void OnWsDisconnected() {}
380380
public virtual void OnWsReceived(byte[] buffer, long offset, long size) {}
381-
public virtual void OnWsClose(byte[] buffer, long offset, long size) { CloseAsync(1000); }
381+
public virtual void OnWsClose(byte[] buffer, long offset, long size, int status = 1000) { CloseAsync(status); }
382382
public virtual void OnWsPing(byte[] buffer, long offset, long size) { SendPongAsync(buffer, offset, size); }
383383
public virtual void OnWsPong(byte[] buffer, long offset, long size) {}
384384
public virtual void OnWsError(string error) { OnError(SocketError.SocketError); }

source/NetCoreServer/WsSession.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ public string ReceiveText()
187187
{
188188
while (!WebSocket.WsFrameReceived)
189189
{
190-
int required = WebSocket.RequiredReceiveFrameSize();
190+
long required = WebSocket.RequiredReceiveFrameSize();
191191
cache.Resize(required);
192-
int received = (int)base.Receive(cache.Data, 0, required);
192+
long received = base.Receive(cache.Data, 0, required);
193193
if (received != required)
194194
return result.ExtractString(0, result.Data.Length);
195195
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -218,9 +218,9 @@ public Buffer ReceiveBinary()
218218
{
219219
while (!WebSocket.WsFrameReceived)
220220
{
221-
int required = WebSocket.RequiredReceiveFrameSize();
221+
long required = WebSocket.RequiredReceiveFrameSize();
222222
cache.Resize(required);
223-
int received = (int)base.Receive(cache.Data, 0, required);
223+
long received = base.Receive(cache.Data, 0, required);
224224
if (received != required)
225225
return result;
226226
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -330,7 +330,7 @@ public virtual void OnWsConnected(HttpRequest request) {}
330330
public virtual void OnWsDisconnecting() {}
331331
public virtual void OnWsDisconnected() {}
332332
public virtual void OnWsReceived(byte[] buffer, long offset, long size) {}
333-
public virtual void OnWsClose(byte[] buffer, long offset, long size) { Close(1000); }
333+
public virtual void OnWsClose(byte[] buffer, long offset, long size, int status = 1000) { Close(status); }
334334
public virtual void OnWsPing(byte[] buffer, long offset, long size) { SendPongAsync(buffer, offset, size); }
335335
public virtual void OnWsPong(byte[] buffer, long offset, long size) {}
336336
public virtual void OnWsError(string error) { OnError(SocketError.SocketError); }

source/NetCoreServer/WssClient.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ public string ReceiveText()
224224
{
225225
while (!WebSocket.WsFrameReceived)
226226
{
227-
int required = WebSocket.RequiredReceiveFrameSize();
227+
long required = WebSocket.RequiredReceiveFrameSize();
228228
cache.Resize(required);
229-
int received = (int)base.Receive(cache.Data, 0, required);
229+
long received = (int)base.Receive(cache.Data, 0, required);
230230
if (received != required)
231231
return result.ExtractString(0, result.Data.Length);
232232
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -255,9 +255,9 @@ public Buffer ReceiveBinary()
255255
{
256256
while (!WebSocket.WsFrameReceived)
257257
{
258-
int required = WebSocket.RequiredReceiveFrameSize();
258+
long required = WebSocket.RequiredReceiveFrameSize();
259259
cache.Resize(required);
260-
int received = (int)base.Receive(cache.Data, 0, required);
260+
long received = (int)base.Receive(cache.Data, 0, required);
261261
if (received != required)
262262
return result;
263263
WebSocket.PrepareReceiveFrame(cache.Data, 0, received);
@@ -382,7 +382,7 @@ public virtual void OnWsConnected(HttpRequest request) {}
382382
public virtual void OnWsDisconnecting() {}
383383
public virtual void OnWsDisconnected() {}
384384
public virtual void OnWsReceived(byte[] buffer, long offset, long size) {}
385-
public virtual void OnWsClose(byte[] buffer, long offset, long size) { CloseAsync(1000); }
385+
public virtual void OnWsClose(byte[] buffer, long offset, long size, int status = 1000) { CloseAsync(status); }
386386
public virtual void OnWsPing(byte[] buffer, long offset, long size) { SendPongAsync(buffer, offset, size); }
387387
public virtual void OnWsPong(byte[] buffer, long offset, long size) {}
388388
public virtual void OnWsError(string error) { OnError(SocketError.SocketError); }

0 commit comments

Comments
 (0)