websocket-server – Rev 1
?pathlinks?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Diagnostics;
namespace WebSockets.Common
{
// see http://tools.ietf.org/html/rfc6455 for specification
public class WebSocketFrameReader
{
private byte[] _buffer;
public WebSocketFrameReader()
{
_buffer = new byte[1024*64];
}
public WebSocketFrame Read(Stream stream, Socket socket)
{
byte byte1;
try
{
byte1 = (byte) stream.ReadByte();
}
catch (IOException)
{
if (socket.Connected)
{
throw;
}
else
{
return null;
}
}
// process first byte
byte finBitFlag = 0x80;
byte opCodeFlag = 0x0F;
bool isFinBitSet = (byte1 & finBitFlag) == finBitFlag;
WebSocketOpCode opCode = (WebSocketOpCode) (byte1 & opCodeFlag);
// read and process second byte
byte byte2 = (byte) stream.ReadByte();
byte maskFlag = 0x80;
bool isMaskBitSet = (byte2 & maskFlag) == maskFlag;
uint len = ReadLength(byte2, stream);
byte[] decodedPayload;
// use the masking key to decode the data if needed
if (isMaskBitSet)
{
const int maskKeyLen = 4;
byte[] maskKey = BinaryReaderWriter.ReadExactly(maskKeyLen, stream);
byte[] encodedPayload = BinaryReaderWriter.ReadExactly((int) len, stream);
decodedPayload = new byte[len];
// apply the mask key
for (int i = 0; i < encodedPayload.Length; i++)
{
decodedPayload[i] = (Byte) (encodedPayload[i] ^ maskKey[i%maskKeyLen]);
}
}
else
{
decodedPayload = BinaryReaderWriter.ReadExactly((int) len, stream);
}
WebSocketFrame frame = new WebSocketFrame(isFinBitSet, opCode, decodedPayload, true);
return frame;
}
private static uint ReadLength(byte byte2, Stream stream)
{
byte payloadLenFlag = 0x7F;
uint len = (uint) (byte2 & payloadLenFlag);
// read a short length or a long length depending on the value of len
if (len == 126)
{
len = BinaryReaderWriter.ReadUShortExactly(stream, false);
}
else if (len == 127)
{
len = (uint) BinaryReaderWriter.ReadULongExactly(stream, false);
const uint maxLen = 2147483648; // 2GB
// protect ourselves against bad data
if (len > maxLen || len < 0)
{
throw new ArgumentOutOfRangeException(string.Format("Payload length out of range. Min 0 max 2GB. Actual {0:#,##0} bytes.", len));
}
}
return len;
}
}
}