Permalink
Browse files

Implemented Alchemy client and added integration tests between client…

… and server.
  • Loading branch information...
1 parent 16cc497 commit 8ce624b10d82fef6d01b806052d783072b143ba4 @DorianGray DorianGray committed Dec 19, 2011
View
@@ -15,6 +15,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Alchemy", "Alchemy", "{DEF8
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Alchemy", "test\Unit\Alchemy\Alchemy.csproj", "{D62E2F92-A930-44D9-90FB-864CAF837BAE}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Alchemy", "Alchemy", "{D629207E-B540-40F6-B2B4-5BCDD033EAD6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Alchemy", "test\Integration\Alchemy\Alchemy.csproj", "{D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +55,18 @@ Global
{D62E2F92-A930-44D9-90FB-864CAF837BAE}.Release|Mixed Platforms.Build.0 = Release|x64
{D62E2F92-A930-44D9-90FB-864CAF837BAE}.Release|x64.ActiveCfg = Release|Any CPU
{D62E2F92-A930-44D9-90FB-864CAF837BAE}.Release|x86.ActiveCfg = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|x64.ActiveCfg = Release|Any CPU
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -59,8 +75,10 @@ Global
{45486CDE-86A3-4769-952F-E0821BF79493} = {8C9C334C-588E-41A1-85FC-9DC035821D27}
{24B00C6C-88BE-4F83-B2E1-8CC8F145BFB9} = {32470B4C-0665-44B9-9A55-AF9C671FDAA5}
{A8BCA98B-12E7-4E13-99FE-09DDCA10BB26} = {32470B4C-0665-44B9-9A55-AF9C671FDAA5}
+ {D629207E-B540-40F6-B2B4-5BCDD033EAD6} = {24B00C6C-88BE-4F83-B2E1-8CC8F145BFB9}
{DEF8E4AE-D1A2-4C33-A4EC-A51BDF6BD09F} = {A8BCA98B-12E7-4E13-99FE-09DDCA10BB26}
{D62E2F92-A930-44D9-90FB-864CAF837BAE} = {DEF8E4AE-D1A2-4C33-A4EC-A51BDF6BD09F}
+ {D7B6AB15-5986-4FDC-ADA8-9EF14DF8F26D} = {D629207E-B540-40F6-B2B4-5BCDD033EAD6}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Server.csproj
@@ -10,7 +10,7 @@ namespace Alchemy
/// It manages sending the XML cross domain policy to flash socket clients over port 843.
/// See http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html for details.
/// </summary>
- public class AccessPolicyServer : TcpServer, IDisposable
+ internal class AccessPolicyServer : TcpServer, IDisposable
{
/// <summary>
/// The pre-formatted XML response.
@@ -86,6 +86,7 @@
<Compile Include="Handlers\WebSocket\IWebSocketAuthentication.cs" />
<Compile Include="Handlers\WebSocket\WebSocketHandler.cs" />
<Compile Include="TcpServer.cs" />
+ <Compile Include="WebSocketClient.cs" />
<Compile Include="WebSocketServer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -24,7 +24,7 @@ public class Context : IDisposable
/// <summary>
/// The max frame that we will accept from the client
/// </summary>
- public UInt64 MaxFrameSize;
+ public UInt64 MaxFrameSize = Int64.MaxValue;
/// <summary>
/// Whether or not the TCPClient is still connected.
@@ -24,7 +24,7 @@ public class Header
/// Regular expression to parse http header
/// </summary>
public static string Pattern =
- @"^(?<connect>[^\s]+)\s(?<path>[^\s]+)\sHTTP\/1\.1\r\n" + // HTTP Request
+ @"^(?<connect>[^\s]+)?\s?(?<path>[^\s]+)?\s?HTTP\/1\.1(.*?)?\r\n" + // HTTP Request
@"((?<field_name>[^:\r\n]+):(?<field_value>[^\r\n]+)\r\n)+";
// HTTP Header Fields (<Field_Name>: <Field_Value> CR LF)
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
@@ -116,13 +117,15 @@ public void Send(DataFrame dataFrame, Context context, bool raw = false, bool cl
context.SendReady.Wait();
try
{
- context.Connection.Client.BeginSend(raw ? dataFrame.AsRaw() : dataFrame.AsFrame(), SocketFlags.None,
+ List<ArraySegment<byte>> list = raw ? dataFrame.AsRaw() : dataFrame.AsFrame();
+ context.Connection.Client.BeginSend(list, SocketFlags.None,
callback,
context);
}
- catch
+ catch(Exception e)
{
context.SendReady.Release();
+ Console.WriteLine(e);
@ShyRed

ShyRed Dec 20, 2011

Is Console.WriteLine(e) some debugging code you forgot to remove?

@DorianGray

DorianGray Dec 20, 2011

Owner

It is indeed. I'll put some time into cleaning up tonight. The client also, if you haven't noticed, still needs some love.

@ShyRed

ShyRed Dec 20, 2011

Just wanted to point stuff out that I notice while looking through the commits. :-)

@DorianGray

DorianGray Dec 21, 2011

Owner

Haha, thanks! it prompted me to rip out all the debug stuff lying around and do some more cleanup.

}
}
@@ -31,6 +31,9 @@ public class ClientHandshake
public string Origin = String.Empty;
public string ResourcePath = String.Empty;
+ public ClientHandshake()
+ {}
+
/// <summary>
/// Initializes a new instance of the <see cref="ClientHandshake"/> class.
/// </summary>
@@ -51,7 +51,7 @@ protected override bool CheckAuthentication(Context context)
}
}
// Generate response handshake for the client
- ServerHandshake serverShake = GenerateResponseHandshake(handshake, context);
+ ServerHandshake serverShake = GenerateResponseHandshake(handshake);
serverShake.SubProtocol = handshake.SubProtocol;
// Send the response handshake
SendServerHandshake(serverShake, context);
@@ -61,9 +61,9 @@ protected override bool CheckAuthentication(Context context)
return false;
}
- private static ServerHandshake GenerateResponseHandshake(ClientHandshake handshake, Context context)
+ private static ServerHandshake GenerateResponseHandshake(ClientHandshake handshake)
{
- var responseHandshake = new ServerHandshake {Accept = GenerateAccept(handshake.Key, context)};
+ var responseHandshake = new ServerHandshake {Accept = GenerateAccept(handshake.Key)};
return responseHandshake;
}
@@ -75,13 +75,20 @@ private static void SendServerHandshake(ServerHandshake handshake, Context conte
context.UserContext.Send(handshakeBytes, true);
}
- private static string GenerateAccept(string key, Context context)
+ public static string GenerateAccept(string key)
{
- string rawAnswer = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+ if (!String.IsNullOrEmpty(key))
+ {
+ string rawAnswer = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- // Create a hash of the rawAnswer and return it
- SHA1 hasher = SHA1.Create();
- return Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(rawAnswer)));
+ // Create a hash of the rawAnswer and return it
+ SHA1 hasher = SHA1.Create();
+ return Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(rawAnswer)));
+ }
+ else
+ {
+ return String.Empty;
+ }
}
}
}
@@ -18,10 +18,10 @@ public class ClientHandshake
private const String Handshake =
"GET {0} HTTP/1.1\r\n" +
"Host: {2}\r\n" +
+ "Origin: {1}\r\n" +
"Upgrade: websocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Key: {4}\r\n" +
- "Sec-WebSocket-Origin: {1}\r\n" +
"Sec-WebSocket-Protocol: {3}\r\n" +
"Sec-WebSocket-Version: 8\r\n" +
"{5}";
@@ -31,6 +31,9 @@ public class ClientHandshake
public string Origin = String.Empty;
public string ResourcePath = String.Empty;
+ public ClientHandshake()
+ { }
+
/// <summary>
/// Initializes a new instance of the <see cref="ClientHandshake"/> class.
/// </summary>
@@ -118,6 +121,20 @@ public class ServerHandshake
public Dictionary<string, string> AdditionalFields { get; set; }
+ public ServerHandshake()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServerHandshake"/> class.
+ /// </summary>
+ /// <param name="header">The header.</param>
+ public ServerHandshake(Header header)
+ {
+ Accept = header["Sec-WebSocket-Accept"];
+ SubProtocol = header["Sec-WebSocket-Protocol"];
+ }
+
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
Oops, something went wrong.

0 comments on commit 8ce624b

Please sign in to comment.