Skip to content

Commit

Permalink
fixed bugs about empty package encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
kerryjiang committed Aug 30, 2024
1 parent 1d399c1 commit 3343067
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 22 deletions.
45 changes: 24 additions & 21 deletions src/SuperSocket.WebSocket/WebSocketEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ protected virtual Span<byte> WriteHead(IBufferWriter<byte> writer, long length,
if (length < _size0)
{
headLen = 2;

var head = writer.GetSpan(headLen);
head[1] = (byte)length;

Expand Down Expand Up @@ -229,43 +230,45 @@ protected virtual int GetFragmentTotalLength(int headLen, int bodyLen)
private int EncodeFinalFragment(IBufferWriter<byte> writer, byte opCode, ReadOnlySpan<char> text, Encoder encoder, ArraySegment<byte> unwrittenBytes)
{
byte[] buffer = default;
Span<byte> bufferSpan = default;

object encodingContext = default;

try
{
// writer should not be touched for now, because head has not been written yet.
encodingContext = CreateDataEncodingContext(null);

var totalWritten = 0;

Span<byte> bufferSpan = default;
if (encoder != null)
{
// writer should not be touched for now, because head has not been written yet.
encodingContext = CreateDataEncodingContext(null);

var fragementSize = (text.Length > 0 ? encoder.GetByteCount(text, true) : 0) + unwrittenBytes.Count;
var fragementSize = (text.Length > 0 ? encoder.GetByteCount(text, true) : 0) + unwrittenBytes.Count;

if (fragementSize == 0)
fragementSize = _minEncodeBufferSize;
if (fragementSize == 0)
fragementSize = _minEncodeBufferSize;

buffer = _bufferPool.Rent(fragementSize);
buffer = _bufferPool.Rent(fragementSize);

bufferSpan = buffer.AsSpan();
bufferSpan = buffer.AsSpan();

if (unwrittenBytes.Count > 0)
{
unwrittenBytes.AsSpan().CopyTo(bufferSpan);
totalWritten += unwrittenBytes.Count;
OnDataEncoded(bufferSpan.Slice(0, unwrittenBytes.Count), encodingContext, 0);
}
if (unwrittenBytes.Count > 0)
{
unwrittenBytes.AsSpan().CopyTo(bufferSpan);
totalWritten += unwrittenBytes.Count;
OnDataEncoded(bufferSpan.Slice(0, unwrittenBytes.Count), encodingContext, 0);
}

encoder.Convert(text, totalWritten == 0 ? bufferSpan : bufferSpan.Slice(totalWritten), true, out var charsUsed, out var bytesUsed, out bool completed);
encoder.Convert(text, totalWritten == 0 ? bufferSpan : bufferSpan.Slice(totalWritten), true, out var charsUsed, out var bytesUsed, out bool completed);

OnDataEncoded(bufferSpan.Slice(totalWritten, bytesUsed), encodingContext, totalWritten);
OnDataEncoded(bufferSpan.Slice(totalWritten, bytesUsed), encodingContext, totalWritten);

totalWritten += bytesUsed;
totalWritten += bytesUsed;

if (!completed || text.Length != charsUsed)
{
throw new ProtocolException("Unexpected encoding behavior: the text encoding didn't complete with enough buffer.");
if (!completed || text.Length != charsUsed)
{
throw new ProtocolException("Unexpected encoding behavior: the text encoding didn't complete with enough buffer.");
}
}

opCode = (byte)(opCode | 0x80);
Expand Down
9 changes: 8 additions & 1 deletion src/SuperSocket.WebSocket/WebSocketMaskedEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,21 @@ protected override object CreateDataEncodingContext(IBufferWriter<byte> writer)
protected override Span<byte> WriteHead(IBufferWriter<byte> writer, long length, out int headLen)
{
var head = base.WriteHead(writer, length, out headLen);
head[1] = (byte)(head[1] | 0x80);

// We don't mask data for empty package
if (length > 0)
head[1] = (byte)(head[1] | 0x80);

return head;
}

protected override void OnHeadEncoded(IBufferWriter<byte> writer, object encodingContext)
{
var maskingContext = encodingContext as MaskingContext;

if (maskingContext == null)
return;

// Means mask buffer was allocated from writter
if (maskingContext.MaskBuffer == null)
{
Expand Down
1 change: 1 addition & 0 deletions test/SuperSocket.Tests/WebSocket/WebSocketBasicTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ private string GetTestMessage(int messageSize, bool nonAsciiText)
[InlineData(10, true, 8)]
[InlineData(16, true, 8)]
[InlineData(17, true, 8)]
[InlineData(0, false, 8)]
public void TestWebSocketMaskEncoder(int messageLength, bool nonAsciiText, int fragmentSize)
{
var websocketEncoder = new WebSocketMaskedEncoder(ArrayPool<byte>.Shared, new int[] { fragmentSize });
Expand Down

0 comments on commit 3343067

Please sign in to comment.