diff --git a/server/CircleScape.csproj b/server/CircleScape.csproj
index 8ce6bfa..d5d8c08 100644
--- a/server/CircleScape.csproj
+++ b/server/CircleScape.csproj
@@ -101,7 +101,6 @@
-
@@ -125,12 +124,6 @@
-
-
- {347353f6-cecd-4895-8717-2b5394ac71cc}
- Kneesocks
-
-
@@ -150,6 +143,16 @@
App.config
+
+
+ {347353f6-cecd-4895-8717-2b5394ac71cc}
+ Kneesocks
+
+
+ {054f172e-9683-40bc-8bdd-7671340ec193}
+ Square
+
+
diff --git a/server/CircleScape.sln b/server/CircleScape.sln
index c633273..3efd8d2 100644
--- a/server/CircleScape.sln
+++ b/server/CircleScape.sln
@@ -5,7 +5,9 @@ VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CircleScape", "CircleScape.csproj", "{438DBAC1-BA37-40BB-9CCE-0FE1F23C6DC5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kneesocks", "Kneesocks\Kneesocks.csproj", "{347353F6-CECD-4895-8717-2B5394AC71CC}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kneesocks", "Libraries\Kneesocks\Kneesocks.csproj", "{347353F6-CECD-4895-8717-2B5394AC71CC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Square", "Libraries\Square\Square.csproj", "{054F172E-9683-40BC-8BDD-7671340EC193}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{347353F6-CECD-4895-8717-2B5394AC71CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {054F172E-9683-40BC-8BDD-7671340EC193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {054F172E-9683-40BC-8BDD-7671340EC193}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {054F172E-9683-40BC-8BDD-7671340EC193}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {054F172E-9683-40BC-8BDD-7671340EC193}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/server/Kneesocks/Utilities.cs b/server/Kneesocks/Utilities.cs
deleted file mode 100644
index 9958031..0000000
--- a/server/Kneesocks/Utilities.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Kneesocks {
- public static class StringExtensions {
- public enum kHashReturnType {
- RAW, HEX, BASE64
- }
-
- public static byte[] GetBytes(this string str, bool isUtf8 = true) {
- return isUtf8 ? Encoding.UTF8.GetBytes(str)
- : Encoding.ASCII.GetBytes(str);
- }
-
- public static int ByteLength(this string str, bool isUtf8 = true) {
- return isUtf8 ? Encoding.UTF8.GetByteCount(str)
- : Encoding.ASCII.GetByteCount(str);
- }
-
- public static string Base64Encode(this string str, bool isUtf8 = true) {
- var raw =
- isUtf8 ? Encoding.UTF8.GetBytes(str)
- : Encoding.ASCII.GetBytes(str);
- return Convert.ToBase64String(raw);
- }
-
- public static string Base64Decode(this string str, bool isUtf8 = true) {
- var raw = Convert.FromBase64String(str);
- return isUtf8 ? Encoding.UTF8.GetString(raw)
- : Encoding.ASCII.GetString(raw);
- }
-
- public static string SHA1(this string str, kHashReturnType type = kHashReturnType.RAW) {
- using(var hasher = System.Security.Cryptography.SHA1.Create()) {
- return ParseRawHash(
- hasher.ComputeHash(str.GetBytes(false)),
- type
- );
- }
- }
-
- public static string MD5(this string str, kHashReturnType type = kHashReturnType.RAW) {
- using(var hasher = System.Security.Cryptography.MD5.Create()) {
- return ParseRawHash(
- hasher.ComputeHash(str.GetBytes(false)),
- type
- );
- }
- }
-
- private static string ParseRawHash(byte[] hash, kHashReturnType type) {
- var raw = Encoding.ASCII.GetString(hash);
-
- switch(type) {
- case kHashReturnType.BASE64:
- return Base64Encode(raw, false);
- case kHashReturnType.HEX:
- return BitConverter.ToString(hash).Replace("-", "");
- case kHashReturnType.RAW:
- default:
- return raw;
- }
- }
- }
-
- public static class NumericExtensions {
- /*public static T Unpack(this byte[] bytes, int offset = 0) {
- return 0;
- }*/
- }
-}
diff --git a/server/Kneesocks/Connection.cs b/server/Libraries/Kneesocks/Connection.cs
similarity index 71%
rename from server/Kneesocks/Connection.cs
rename to server/Libraries/Kneesocks/Connection.cs
index 81a56e0..afd1aa6 100644
--- a/server/Kneesocks/Connection.cs
+++ b/server/Libraries/Kneesocks/Connection.cs
@@ -32,9 +32,7 @@ namespace Kneesocks {
public string DisconnectReason { get; private set; } = null;
public bool Handshaked { get; private set; } = false;
- private string RawClientHandshake = "";
- private Dictionary Headers =
- new Dictionary(StringComparer.OrdinalIgnoreCase);
+ public Handshake ClientHandshake { get; private set; } = null;
public Connection(TcpClient sock) {
Socket = sock;
@@ -62,30 +60,51 @@ namespace Kneesocks {
DisconnectReason = conn.DisconnectReason;
Handshaked = conn.Handshaked;
- RawClientHandshake = conn.RawClientHandshake;
- Headers = conn.Headers;
- }
-
- private void StartRead(ulong length) {
-
+ ClientHandshake = conn.ClientHandshake;
}
public byte[] Parse() {
byte[] readBuffer = null;
if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead();
- if(readBuffer == null)
+ if(readBuffer == null) {
+ if(Buffer.ElapsedReadTime.Seconds > 30)
+ Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response");
+
return null;
+ }
}
if(!Handshaked) {
- if(Stream.)
-
- return null;
- } else {
+ if(!Buffer.IsReading) {
+ readBuffer = Buffer.AttemptRead("\r\n\r\n");
+ if(readBuffer == null)
+ return null;
+ }
- OnParse();
+ try {
+ Handshake request = new Handshake(Encoding.ASCII.GetString(readBuffer));
+ var response = Handshake.AcceptRequest(request).ToBytes();
+ Stream.Write(response, 0, response.Length);
+ ClientHandshake = request;
+ Handshaked = true;
+ } catch(Exception e) {
+ Disconnect(Frame.kClosingReason.ProtocolError, e.Message);
+ return null;
+ }
+
+ OnOpen();
+ return null;
}
+
+ /*if(!Buffer.IsReading) {
+ readBuffer = Buffer.AttemptRead("\r\n\r\n");
+ if(readBuffer == null)
+ return null;
+ }*/
+
+ OnParse();
+ return null;
}
public void Disconnect(string reason = null) {
diff --git a/server/Kneesocks/Frame.cs b/server/Libraries/Kneesocks/Frame.cs
similarity index 100%
rename from server/Kneesocks/Frame.cs
rename to server/Libraries/Kneesocks/Frame.cs
diff --git a/server/Kneesocks/Handshake.cs b/server/Libraries/Kneesocks/Handshake.cs
similarity index 90%
rename from server/Kneesocks/Handshake.cs
rename to server/Libraries/Kneesocks/Handshake.cs
index e057427..b6cb636 100644
--- a/server/Kneesocks/Handshake.cs
+++ b/server/Libraries/Kneesocks/Handshake.cs
@@ -27,7 +27,7 @@ namespace Kneesocks {
Service_Unavailable = 503,
Gateway_Timeout = 504
}
-
+
public kStatusCode StatusCode { get; private set; } = kStatusCode.Switching_Protocols;
protected string StatusCodeText {
get {
@@ -44,25 +44,23 @@ namespace Kneesocks {
throw new FormatException("Header delimeter not found in raw data");
var header = rawData.Substring(0, headerLength);
- if(!header.StartsWith("HTTP/"))
+ if(!header.StartsWith("GET ") || !header.Contains("HTTP/"))
throw new FormatException("Protocol defined in status line not understood");
var lines = header.Split('\n');
foreach(var line in lines) {
string[] parts;
- if(line.StartsWith("HTTP/")) {
+ if(line.StartsWith("GET ")) {
parts = line.Trim().Split(' ');
- if(parts.Length < 2)
+ if(parts.Length < 3)
throw new FormatException("Status line in header malformed");
- int code;
+ /*int code;
if(!int.TryParse(parts[1], out code))
- throw new FormatException("Status code sent is not a number");
+ throw new FormatException("Status code sent is not a number");*/
- if(!Enum.IsDefined(typeof(kStatusCode), code))
- throw new NotSupportedException("Status code not supported");
-
- StatusCode = (kStatusCode)code;
+ /*if(!Enum.IsDefined(typeof(kStatusCode), code))
+ throw new NotSupportedException("Status code not supported");*/
} else {
parts = line.Trim().Split(new char[] {':'}, 2);
if(parts.Length == 2)
@@ -88,6 +86,8 @@ namespace Kneesocks {
var key = request.GetHeader("Sec-WebSocket-Key");
var connectionHash = (key + nonce).SHA1().Base64Encode(false);
+ var test = ("dGhlIHNhbXBsZSBub25jZQ==" + nonce).SHA1().Base64Encode(false);
+
var shake = new Handshake(kStatusCode.Switching_Protocols);
shake.SetHeader("Upgrade", "websocket")
.SetHeader("Connection", "Upgrade")
@@ -99,6 +99,10 @@ namespace Kneesocks {
return new Handshake(statusCode, message);
}
+ public byte[] ToBytes() {
+ return Encoding.ASCII.GetBytes(ToString());
+ }
+
public override string ToString() {
if(Content != null) {
SetHeader("Content-Length", Content.ByteLength().ToString());
diff --git a/server/Kneesocks/Kneesocks.csproj b/server/Libraries/Kneesocks/Kneesocks.csproj
similarity index 92%
rename from server/Kneesocks/Kneesocks.csproj
rename to server/Libraries/Kneesocks/Kneesocks.csproj
index ffa0fec..d37edf7 100644
--- a/server/Kneesocks/Kneesocks.csproj
+++ b/server/Libraries/Kneesocks/Kneesocks.csproj
@@ -50,6 +50,12 @@
+
+
+ {054f172e-9683-40bc-8bdd-7671340ec193}
+ Square
+
+
+
\ No newline at end of file
diff --git a/server/Libraries/Square/StringExtensions.cs b/server/Libraries/Square/StringExtensions.cs
new file mode 100644
index 0000000..7609144
--- /dev/null
+++ b/server/Libraries/Square/StringExtensions.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Square {
+ public static class StringExtensions {
+ public static byte[] GetBytes(this string str, bool isUtf8 = true) {
+ return isUtf8 ? Encoding.UTF8.GetBytes(str)
+ : Encoding.ASCII.GetBytes(str);
+ }
+
+ public static int ByteLength(this string str, bool isUtf8 = true) {
+ return isUtf8 ? Encoding.UTF8.GetByteCount(str)
+ : Encoding.ASCII.GetByteCount(str);
+ }
+
+ public static string Base64Encode(this string str, bool isUtf8 = true) {
+ var raw =
+ isUtf8 ? Encoding.UTF8.GetBytes(str)
+ : Encoding.ASCII.GetBytes(str);
+ return Convert.ToBase64String(raw);
+ }
+
+ public static string Base64Decode(this string str, bool isUtf8 = true) {
+ var raw = Convert.FromBase64String(str);
+ return isUtf8 ? Encoding.UTF8.GetString(raw)
+ : Encoding.ASCII.GetString(raw);
+ }
+
+ public static byte[] Base64DecodeRaw(this string str) {
+ return Convert.FromBase64String(str);
+ }
+ }
+}
diff --git a/server/Utilities.cs b/server/Utilities.cs
deleted file mode 100644
index 1d6e2cf..0000000
--- a/server/Utilities.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace CircleScape {
- public static class StringExtensions {
- public enum kHashReturnType {
- RAW, HEX, BASE64
- }
-
- public static string Base64Encode(this string str, bool isUtf8 = true) {
- var raw =
- isUtf8 ? Encoding.UTF8.GetBytes(str)
- : Encoding.ASCII.GetBytes(str);
- return Convert.ToBase64String(raw);
- }
-
- public static string Base64Decode(this string str, bool isUtf8 = true) {
- var raw = Convert.FromBase64String(str);
- return isUtf8 ? Encoding.UTF8.GetString(raw)
- : Encoding.ASCII.GetString(raw);
- }
-
- public static string SHA1(this string str, kHashReturnType type = kHashReturnType.RAW) {
- using(var hasher = System.Security.Cryptography.SHA1.Create()) {
- return ParseRawHash(
- hasher.ComputeHash(Encoding.ASCII.GetBytes(str)),
- type
- );
- }
- }
-
- public static string MD5(this string str, kHashReturnType type = kHashReturnType.RAW) {
- using(var hasher = System.Security.Cryptography.MD5.Create()) {
- return ParseRawHash(
- hasher.ComputeHash(Encoding.ASCII.GetBytes(str)),
- type
- );
- }
- }
-
- private static string ParseRawHash(byte[] hash, kHashReturnType type) {
- var raw = Encoding.ASCII.GetString(hash);
-
- switch(type) {
- case kHashReturnType.BASE64:
- return Base64Encode(raw, false);
- case kHashReturnType.HEX:
- return BitConverter.ToString(hash).Replace("-", "");
- case kHashReturnType.RAW:
- default:
- return raw;
- }
- }
- }
-
- public static class NumericExtensions {
-
- }
-}