Created
February 10, 2012 07:33
-
-
Save dearing/1787430 to your computer and use it in GitHub Desktop.
RFC6455: simple echo test with websocket after handshake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* http://tools.ietf.org/html/rfc6455#section-5.2 | |
0 1 2 3 | |
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
+-+-+-+-+-------+-+-------------+-------------------------------+ | |
|F|R|R|R| opcode|M| Payload len | Extended payload length | | |
|I|S|S|S| (4) |A| (7) | (16/64) | | |
|N|V|V|V| |S| | (if payload len==126/127) | | |
| |1|2|3| |K| | | | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | |
| Extended payload length continued, if payload len == 127 | | |
+ - - - - - - - - - - - - - - - +-------------------------------+ | |
| |Masking-key, if MASK set to 1 | | |
+-------------------------------+-------------------------------+ | |
| Masking-key (continued) | Payload Data | | |
+-------------------------------- - - - - - - - - - - - - - - - + | |
: Payload Data continued ... : | |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | |
| Payload Data continued ... | | |
+---------------------------------------------------------------+ | |
*/ | |
namespace websockets | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using System.IO; | |
using System.Net.Sockets; | |
public class WebSocketFrame : IDisposable | |
{ | |
public enum Opcodes : byte | |
{ | |
Continue = 0x0, // =frrr-0000 : non-control = continuation of fragment sequence | |
Text = 0x1, // =frrr-0001 : non-control = data to be handled as utf-8 | |
Binary = 0x2, // =frrr-0010 : non-control = data to be handled as binary | |
Close = 0x8, // =frrr-1000 : control = close connection | |
Ping = 0x9, // =frrr-1001 : control = ping request | |
Pong = 0xA // =frrr-1010 : control = pong responce | |
} | |
public enum PayloadTypes : byte | |
{ | |
Tall = 0x00, // =m000-0000 : frame[2] = payload length; 0..125 bytes | |
Grande = 0x7E, // =m111-1110 : frame[3,4] = payload length; 16-bit as unsigned integer (uShort) | |
Venti = 0x7D // =m111-1111 : frame[3..11] = payload length; 64-bit as unsigned integer (uLong) | |
} | |
public List<byte> echo{get;set;} | |
public UInt64 PayloadLength { get; set; } | |
public Opcodes Opcode { get; set; } | |
public Byte[] Mask { get; set; } | |
public Boolean isFinal { get; set; } | |
public Boolean isMasked { get; set; } | |
public void ProcessHeader(NetworkStream stream) | |
{ | |
byte[] header = new byte[2]; | |
byte[] mask = new byte[4]; | |
echo = new List<byte>(); | |
stream.Read(header, 0, 2); | |
echo.AddRange(header); | |
this.isFinal = (header[0] & 0x80) == 0x80; | |
this.Opcode = (Opcodes)(header[0] & 0x7F); | |
this.isMasked = (header[1] & 0x80) == 0x80; | |
this.PayloadLength = (ulong)(header[1] & 0x7F); | |
if (PayloadLength == 126) | |
{ | |
byte[] len = new byte[2]; | |
stream.Read(len, 0, 2); | |
Array.Reverse(len); | |
this.PayloadLength = (ulong)BitConverter.ToUInt16(len, 0); | |
} | |
else if (PayloadLength == 127) | |
{ | |
byte[] len = new byte[8]; | |
stream.Read(len, 0, 8); | |
Array.Reverse(len); | |
this.PayloadLength = (ulong)BitConverter.ToUInt64(len, 0); | |
} | |
byte[] data = new byte[PayloadLength]; | |
stream.Read(mask, 0, 4); | |
echo.AddRange(mask); | |
stream.Read(data, 0, data.Length); | |
echo.AddRange(data); | |
if(isMasked) | |
for (int i = 0; i < data.Length; i++) | |
data[i] ^= mask[i % 4]; | |
Console.WriteLine("{0}: isFinal?{1}: Length:{2}", this.Opcode,this.isFinal,this.PayloadLength); | |
if(Opcode == Opcodes.Text) | |
Console.WriteLine(Encoding.UTF8.GetString(data)); | |
stream.Write(echo.ToArray(), 0, echo.Count); | |
stream.Flush(); | |
} | |
public void Dispose() | |
{ | |
Console.WriteLine("Echo complete."); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
those looking may find this snippet helpful when reading http://tools.ietf.org/html/rfc6455#section-5 and drinking some coffee