fix Ext.cs, WebSocket.cs for implementation of Sec-WebSocket-Key*.
This commit is contained in:
parent
3f5215844f
commit
b683db43fc
@ -1,8 +1,8 @@
|
||||
<Properties>
|
||||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Release_Ubuntu" ctype="Workspace" />
|
||||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug_Ubuntu" ctype="Workspace" />
|
||||
<MonoDevelop.Ide.Workbench ActiveDocument="websocket-sharp/WebSocket.cs" ctype="Workbench">
|
||||
<Files>
|
||||
<File FileName="websocket-sharp/WebSocket.cs" Line="1" Column="1" />
|
||||
<File FileName="websocket-sharp/WebSocket.cs" Line="264" Column="15" />
|
||||
</Files>
|
||||
</MonoDevelop.Ide.Workbench>
|
||||
<MonoDevelop.Ide.DebuggingService.Breakpoints>
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
@ -40,11 +41,91 @@ namespace WebSocketSharp
|
||||
return b == Convert.ToByte(c);
|
||||
}
|
||||
|
||||
public static void NotEqualsDo(this string a, string b, Action<string> action)
|
||||
public static uint GenerateKey(this Random rand, int space)
|
||||
{
|
||||
uint max = (uint)(0xffffffff / space);
|
||||
|
||||
int upper16 = (int)((max & 0xffff0000) >> 16);
|
||||
int lower16 = (int)(max & 0x0000ffff);
|
||||
|
||||
return ((uint)rand.Next(upper16 + 1) << 16) + (uint)rand.Next(lower16 + 1);
|
||||
}
|
||||
|
||||
public static string GenerateSecKey(this Random rand, out uint key)
|
||||
{
|
||||
int space = rand.Next(1, 13);
|
||||
int ascii = rand.Next(1, 13);
|
||||
|
||||
key = rand.GenerateKey(space);
|
||||
|
||||
long mKey = key * space;
|
||||
char[] mKeyChars = mKey.ToString().ToCharArray();
|
||||
int mKeyCharsLen = mKeyChars.Length;
|
||||
|
||||
int secKeyCharsLen = mKeyCharsLen + space + ascii;
|
||||
char[] secKeyChars = new char[secKeyCharsLen].InitializeWith(' ');
|
||||
|
||||
secKeyChars[0] = mKeyChars[0];
|
||||
secKeyChars[secKeyCharsLen - 1] = mKeyChars[mKeyCharsLen - 1];
|
||||
|
||||
int i = 0;
|
||||
for (int j = 1; j < mKeyCharsLen - 1; j++)
|
||||
{
|
||||
i = rand.Next(i + 1, secKeyCharsLen - mKeyCharsLen + j + 1);
|
||||
secKeyChars[i] = mKeyChars[j];
|
||||
}
|
||||
|
||||
var convToAscii = secKeyChars
|
||||
.IndexOf(' ')
|
||||
.OrderBy( x => Guid.NewGuid() )
|
||||
.Where( (x, idx) => idx < ascii );
|
||||
|
||||
int k;
|
||||
foreach (int index in convToAscii)
|
||||
{
|
||||
k = rand.Next(2) == 0 ? rand.Next(33, 48) : rand.Next(58, 127);
|
||||
secKeyChars[index] = Convert.ToChar(k);
|
||||
}
|
||||
|
||||
return new String(secKeyChars);
|
||||
}
|
||||
|
||||
public static IEnumerable<int> IndexOf<T>(this T[] array, T val)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i].Equals(val))
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static T[] InitializeWith<T>(this T[] array, T val)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = val;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static Byte[] InitializeWithASCII(this Byte[] bytes, Random rand)
|
||||
{
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
bytes[i] = (byte)rand.Next(32, 127);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static void NotEqualsDo(this string a, string b, Action<string, string> action)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
action(a);
|
||||
action(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
@ -256,17 +258,39 @@ namespace WebSocketSharp
|
||||
host += ":" + port;
|
||||
}
|
||||
|
||||
string subprotocol = protocol != String.Empty
|
||||
string subProtocol = protocol != String.Empty
|
||||
? String.Format("Sec-WebSocket-Protocol: {0}\r\n", protocol)
|
||||
: protocol;
|
||||
#if !CHALLENGE
|
||||
string secKeys = String.Empty;
|
||||
string key3AsASCII = String.Empty;
|
||||
#else
|
||||
Random rand = new Random();
|
||||
|
||||
uint key1, key2;
|
||||
string secKey1 = rand.GenerateSecKey(out key1);
|
||||
string secKey2 = rand.GenerateSecKey(out key2);
|
||||
|
||||
byte[] key3 = new byte[8].InitializeWithASCII(rand);
|
||||
|
||||
string secKeys = "Sec-WebSocket-Key1: {0}\r\n" +
|
||||
"Sec-WebSocket-Key2: {1}\r\n";
|
||||
secKeys = String.Format(secKeys, secKey1, secKey2);
|
||||
|
||||
string key3AsASCII = Encoding.ASCII.GetString(key3);
|
||||
|
||||
byte[] expectedRes = createExpectedRes(key1, key2, key3);
|
||||
byte[] actualRes = new byte[16];
|
||||
#endif
|
||||
string request = "GET " + path + " HTTP/1.1\r\n" +
|
||||
"Upgrade: WebSocket\r\n" +
|
||||
"Connection: Upgrade\r\n" +
|
||||
subprotocol +
|
||||
subProtocol +
|
||||
"Host: " + host + "\r\n" +
|
||||
"Origin: " + origin + "\r\n" +
|
||||
"\r\n";
|
||||
secKeys +
|
||||
"\r\n" +
|
||||
key3AsASCII;
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info @doHandshake: Handshake from client: \n{0}", request);
|
||||
#endif
|
||||
@ -283,6 +307,10 @@ namespace WebSocketSharp
|
||||
wsStream.ReadByte().EqualsWithSaveTo('\r', rawdata) &&
|
||||
wsStream.ReadByte().EqualsWithSaveTo('\n', rawdata))
|
||||
{
|
||||
#if CHALLENGE
|
||||
wsStream.Read(actualRes, 0, actualRes.Length);
|
||||
rawdata.AddRange(actualRes);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -297,15 +325,25 @@ namespace WebSocketSharp
|
||||
Console.WriteLine("{0}", s);
|
||||
}
|
||||
#endif
|
||||
Action<string> action = s => { throw new IOException("Invalid handshake response: " + s); };
|
||||
Action<string, string> action = (a, b) =>
|
||||
{
|
||||
throw new IOException("Invalid handshake response: " + a);
|
||||
};
|
||||
#if !CHALLENGE
|
||||
response[0].NotEqualsDo("HTTP/1.1 101 Web Socket Protocol Handshake", action);
|
||||
#else
|
||||
response[0].NotEqualsDo("HTTP/1.1 101 WebSocket Protocol Handshake", action);
|
||||
#endif
|
||||
response[1].NotEqualsDo("Upgrade: WebSocket", action);
|
||||
response[2].NotEqualsDo("Connection: Upgrade", action);
|
||||
|
||||
for (int i = 3; i < response.Length; i++)
|
||||
{
|
||||
#if !CHALLENGE
|
||||
if (response[i].Contains("WebSocket-Protocol:"))
|
||||
// if (response[i].Contains("Sec-WebSocket-Protocol:"))
|
||||
#else
|
||||
if (response[i].Contains("Sec-WebSocket-Protocol:"))
|
||||
#endif
|
||||
{
|
||||
int j = response[i].IndexOf(":");
|
||||
protocol = response[i].Substring(j + 1).Trim();
|
||||
@ -315,10 +353,39 @@ namespace WebSocketSharp
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info @doHandshake: Sub protocol: {0}", protocol);
|
||||
#endif
|
||||
#if CHALLENGE
|
||||
string expectedResHexStr = BitConverter.ToString(expectedRes);
|
||||
string actualResHexStr = BitConverter.ToString(actualRes);
|
||||
|
||||
actualResHexStr.NotEqualsDo(expectedResHexStr, (a, b) =>
|
||||
{
|
||||
Console.WriteLine("WS: Error @doHandshake: Invalid challenge response.");
|
||||
Console.WriteLine("\texpected: {0}", b);
|
||||
Console.WriteLine("\tactual : {0}", a);
|
||||
throw new IOException("Invalid challenge response: " + a);
|
||||
}
|
||||
);
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info @doHandshake: challenge response: {0}", actualResHexStr);
|
||||
#endif
|
||||
#endif
|
||||
ReadyState = WsState.OPEN;
|
||||
}
|
||||
|
||||
private byte[] createExpectedRes(uint key1, uint key2, byte[] key3)
|
||||
{
|
||||
byte[] key1Bytes = BitConverter.GetBytes(key1);
|
||||
byte[] key2Bytes = BitConverter.GetBytes(key2);
|
||||
|
||||
Array.Reverse(key1Bytes);
|
||||
Array.Reverse(key2Bytes);
|
||||
|
||||
byte[] concatKeys = key1Bytes.Concat(key2Bytes).Concat(key3).ToArray();
|
||||
|
||||
MD5 md5 = MD5.Create();
|
||||
return md5.ComputeHash(concatKeys);
|
||||
}
|
||||
|
||||
private void message()
|
||||
{
|
||||
#if DEBUG
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,7 +16,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<DefineConstants>DEBUG,CHALLENGE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
@ -34,7 +34,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug_Ubuntu</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<DefineConstants>DEBUG,CHALLENGE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user