Skip to content

Commit

Permalink
Verify opcodes + RSV bits. fixes #33
Browse files Browse the repository at this point in the history
  • Loading branch information
statianzo committed Jan 24, 2012
1 parent 0924214 commit 535e51b
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
21 changes: 20 additions & 1 deletion src/Fleck.Tests/Hybi13HandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Text;
using Fleck.Handlers;
using NUnit.Framework;
using System.Linq;

namespace Fleck.Tests
{
Expand Down Expand Up @@ -200,13 +201,14 @@ public void ShouldCloseOnCloseFromValidStatusCode()
[Test]
public void ShouldCloseOnCloseFromText()
{
var payload = 1000.ToBigEndianBytes<ushort>().Concat(Encoding.UTF8.GetBytes("Reason")).ToArray();
var frame = new Hybi14DataFrame
{
FrameType = FrameType.Close,
IsFinal = true,
IsMasked = true,
MaskKey = 5232,
Payload = Encoding.UTF8.GetBytes("Just right")
Payload = payload
};

var hit = false;
Expand Down Expand Up @@ -247,6 +249,23 @@ public void ShouldThrowOnCloseFrameTooLong()
var ex = Assert.Throws<WebSocketException>(() => _handler.Receive(frame.ToBytes()));
Assert.AreEqual(WebSocketStatusCodes.ProtocolError, ex.StatusCode);
}

[Test]
public void ShouldThrowOnInvalidFrameType()
{
var frame = new Hybi14DataFrame
{
FrameType = (FrameType)11,
IsFinal = true,
IsMasked = true,
MaskKey = 5232,
Payload = 1000.ToBigEndianBytes<ushort>()
};

var ex = Assert.Throws<WebSocketException>(() => _handler.Receive(frame.ToBytes()));
Assert.AreEqual(WebSocketStatusCodes.ProtocolError, ex.StatusCode);
}


[Test]
public void ShouldCallOnMessageWhenRecievingTextFrameOver125Bytes()
Expand Down
41 changes: 25 additions & 16 deletions src/Fleck/Handlers/Hybi13Handler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ public static void ReceiveData(List<byte> data, ReadState readState, Action<Fram
while (data.Count >= 2)
{
var isFinal = (data[0] & 128) != 0;
var reservedBits = (data[0] & 112);
var frameType = (FrameType)(data[0] & 15);
var isMasked = (data[1] & 128) != 0;
var length = (data[1] & 127);

if (!isMasked)
throw new WebSocketException(WebSocketStatusCodes.ProtocolError);

if (frameType == FrameType.Continuation && !readState.FrameType.HasValue)

if (!isMasked
|| !Enum.IsDefined(typeof(FrameType), frameType)
|| reservedBits != 0 //Must be zero per spec 5.2
|| (frameType == FrameType.Continuation && !readState.FrameType.HasValue))
throw new WebSocketException(WebSocketStatusCodes.ProtocolError);

var index = 2;
Expand Down Expand Up @@ -126,29 +128,23 @@ public static void ProcessFrame(FrameType frameType, byte[] data, Action<string>
if (data.Length == 1 || data.Length>125)
throw new WebSocketException(WebSocketStatusCodes.ProtocolError);

if (data.Length == 2)
if (data.Length >= 2)
{
var closeCode = (ushort)data.Take(2).ToArray().ToLittleEndianInt();
if (!WebSocketStatusCodes.ValidCloseCodes.Contains(closeCode) && (closeCode < 3000 || closeCode > 4999))
throw new WebSocketException(WebSocketStatusCodes.ProtocolError);

}

if (data.Length > 2)
ReadUTF8PayloadData(data.Skip(2).ToArray());

onClose();
break;
case FrameType.Binary:
onBinary(data);
break;
case FrameType.Text:
var encoding = new UTF8Encoding(false, true);
try
{
var message = encoding.GetString(data);
onMessage(message);
}
catch(ArgumentException)
{
throw new WebSocketException(WebSocketStatusCodes.InvalidFramePayloadData);
}
onMessage(ReadUTF8PayloadData(data));
break;
default:
FleckLog.Debug("Received unhandled " + frameType);
Expand Down Expand Up @@ -184,6 +180,19 @@ public static string CreateResponseKey(string requestKey)

return Convert.ToBase64String(bytes);
}

private static string ReadUTF8PayloadData(byte[] bytes)
{
var encoding = new UTF8Encoding(false, true);
try
{
return encoding.GetString(bytes);
}
catch(ArgumentException)
{
throw new WebSocketException(WebSocketStatusCodes.InvalidFramePayloadData);
}
}
}

}

0 comments on commit 535e51b

Please sign in to comment.