diff --git a/server/Libraries/Kneesocks/Connection.cs b/server/Libraries/Kneesocks/Connection.cs
index 11e7baf..dab49b4 100644
--- a/server/Libraries/Kneesocks/Connection.cs
+++ b/server/Libraries/Kneesocks/Connection.cs
@@ -26,7 +26,9 @@ namespace Kneesocks {
private NetworkStream Stream;
ReadBuffer Buffer;
- private Frame PartialFrame = null;
+ private byte[] FirstTwoBytes = null;
+ private int ExtraHeaderSize = 2;
+ private byte[] FrameHeader = null;
private List FrameBuffer = new List();
public bool Disconnected { get; private set; } = false;
@@ -54,7 +56,9 @@ namespace Kneesocks {
Stream = conn.Stream;
Buffer = conn.Buffer;
- PartialFrame = conn.PartialFrame;
+ FirstTwoBytes = conn.FirstTwoBytes;
+ ExtraHeaderSize = conn.ExtraHeaderSize;
+ FrameHeader = conn.FrameHeader;
FrameBuffer = conn.FrameBuffer;
Disconnected = conn.Disconnected;
@@ -63,13 +67,13 @@ namespace Kneesocks {
Handshaked = conn.Handshaked;
ClientHandshake = conn.ClientHandshake;
}
-
+
public byte[] Parse() {
byte[] readBuffer = null;
if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead();
if(readBuffer == null) {
- if(Buffer.ElapsedReadTime.Seconds > 30)
+ if(Buffer.ElapsedReadTime.Seconds > (Handshaked ? 300 : 30))
Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response");
return null;
@@ -77,7 +81,7 @@ namespace Kneesocks {
}
if(!Handshaked) {
- if(!Buffer.IsReading) {
+ if(readBuffer == null) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
if(readBuffer == null)
return null;
@@ -98,13 +102,48 @@ namespace Kneesocks {
return null;
}
+ OnParse();
+
+ if(FirstTwoBytes == null) {
+ if(readBuffer == null) {
+ readBuffer = Buffer.AttemptRead(2);
+ if(readBuffer == null)
+ return null;
+ }
+
+ FirstTwoBytes = readBuffer;
+ ExtraHeaderSize = Frame.HeaderSizeFromBytes(FirstTwoBytes) - 2;
+ readBuffer = null;
+ }
+
+ if(FrameHeader == null) {
+ if(ExtraHeaderSize == 0)
+ FrameHeader = FirstTwoBytes;
+ else {
+ if(readBuffer == null) {
+ readBuffer = Buffer.AttemptRead(ExtraHeaderSize);
+ if(readBuffer == null)
+ return null;
+ }
+
+ FrameHeader = FirstTwoBytes.Concat(readBuffer).ToArray();
+ }
+
+ readBuffer = null;
+ }
+
+ if(FrameHeader != null) {
+ var check = Frame.HeaderFromBytes()
+
+ if()
+ }
+
/*if(!Buffer.IsReading) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
if(readBuffer == null)
return null;
}*/
- OnParse();
return null;
}
diff --git a/server/Libraries/Kneesocks/Handshake.cs b/server/Libraries/Kneesocks/Handshake.cs
index 35871ba..0efd5a9 100644
--- a/server/Libraries/Kneesocks/Handshake.cs
+++ b/server/Libraries/Kneesocks/Handshake.cs
@@ -8,6 +8,7 @@ using Square;
namespace Kneesocks {
public class Handshake {
private const string HttpVersion = "1.1";
+ public bool IsRequest = false;
public enum kStatusCode {
Switching_Protocols = 101,
@@ -28,18 +29,20 @@ namespace Kneesocks {
Service_Unavailable = 503,
Gateway_Timeout = 504
}
-
- public kStatusCode StatusCode { get; private set; } = kStatusCode.Switching_Protocols;
+ public kStatusCode? StatusCode { get; private set; } = null;
protected string StatusCodeText {
get {
return Enum.GetName(typeof(kStatusCode), StatusCode).Replace('_', ' ');
}
}
+
private Dictionary Headers =
new Dictionary(StringComparer.OrdinalIgnoreCase);
public string Content { get; set; } = null;
public Handshake(string rawData) {
+ IsRequest = true;
+
var headerLength = rawData.IndexOf("\r\n\r\n");
if(headerLength == -1)
throw new FormatException("Header delimeter not found in raw data");
@@ -55,13 +58,6 @@ namespace Kneesocks {
parts = line.Trim().Split(' ');
if(parts.Length < 3)
throw new FormatException("Status line in header malformed");
-
- /*int code;
- if(!int.TryParse(parts[1], out code))
- throw new FormatException("Status code sent is not a number");*/
-
- /*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)
@@ -99,10 +95,13 @@ namespace Kneesocks {
}
public byte[] ToBytes() {
- return Encoding.ASCII.GetBytes(ToString());
+ return ToString().GetBytes();
}
public override string ToString() {
+ if(IsRequest)
+ throw new NotSupportedException("Cannot create a request string.");
+
if(Content != null) {
SetHeader("Content-Length", Content.ByteLength().ToString());
if(GetHeader("Content-Type") == null)
@@ -115,6 +114,10 @@ namespace Kneesocks {
return raw += "\r\n";
}
+ public bool HasHeader(string name) {
+ return Headers.ContainsKey(name);
+ }
+
public string GetHeader(string name) {
if(Headers.ContainsKey(name))
return Headers[name];
diff --git a/server/Libraries/Square/ArrayExtensions.cs b/server/Libraries/Square/ArrayExtensions.cs
new file mode 100644
index 0000000..c6687fc
--- /dev/null
+++ b/server/Libraries/Square/ArrayExtensions.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Square {
+ public static class ArrayExtensions {
+ public static T[] Subset(this T[] arr, int offset, int count = -1) {
+ if(count < 0)
+ return arr.Skip(offset).ToArray();
+ else
+ return arr.Skip(offset).Take(count).ToArray();
+ }
+
+ public static T[] Range(this T[] arr, int start, int end) {
+ return arr.Subset(start, end - start);
+ }
+ }
+
+ public static class ByteArrayExtensions {
+ public static string Base64Encode(this byte[] bytes) {
+ return Convert.ToBase64String(bytes);
+ }
+
+ public static string ToHexString(this byte[] bytes) {
+ return BitConverter.ToString(bytes).Replace("-", "");
+ }
+
+ public static string ToString(this byte[] bytes, bool isUtf8 = true) {
+ return isUtf8 ? Encoding.UTF8.GetString(bytes)
+ : Encoding.ASCII.GetString(bytes);
+ }
+
+ public static byte[] HostToNetworkOrder(this byte[] bytes) {
+ if(BitConverter.IsLittleEndian)
+ return bytes.Reverse().ToArray();
+ else
+ return bytes;
+ }
+
+ public static byte[] NetworkToHostOrder(this byte[] bytes) {
+ if(BitConverter.IsLittleEndian)
+ return bytes.Reverse().ToArray();
+ else
+ return bytes;
+ }
+
+ public static Single UnpackFloat(this byte[] bytes) {
+ return BitConverter.ToSingle(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static Double UnpackDouble(this byte[] bytes) {
+ return BitConverter.ToDouble(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static Int16 UnpackInt16(this byte[] bytes) {
+ return BitConverter.ToInt16(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static UInt16 UnpackUInt16(this byte[] bytes) {
+ return BitConverter.ToUInt16(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static Int32 UnpackInt32(this byte[] bytes) {
+ return BitConverter.ToInt32(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static UInt32 UnpackUInt32(this byte[] bytes) {
+ return BitConverter.ToUInt32(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static Int64 UnpackInt64(this byte[] bytes) {
+ return BitConverter.ToInt64(bytes.NetworkToHostOrder(), 0);
+ }
+
+ public static UInt64 UnpackUInt64(this byte[] bytes) {
+ return BitConverter.ToUInt64(bytes.NetworkToHostOrder(), 0);
+ }
+ }
+}
diff --git a/server/Libraries/Square/ByteArrayExtensions.cs b/server/Libraries/Square/ByteArrayExtensions.cs
deleted file mode 100644
index 91b0afc..0000000
--- a/server/Libraries/Square/ByteArrayExtensions.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Square {
- public static class ByteArrayExtensions {
- public static string Base64Encode(this byte[] bytes) {
- return Convert.ToBase64String(bytes);
- }
-
- public static string ToHexString(this byte[] bytes) {
- return BitConverter.ToString(bytes).Replace("-", "");
- }
- }
-}
diff --git a/server/Libraries/Square/CryptoExtensions.cs b/server/Libraries/Square/CryptoExtensions.cs
index c149d1d..38617fd 100644
--- a/server/Libraries/Square/CryptoExtensions.cs
+++ b/server/Libraries/Square/CryptoExtensions.cs
@@ -26,17 +26,5 @@ namespace Square {
return hasher.ComputeHash(bytes);
}
}
-
- /*private static string ParseRawHash(byte[] hash, kHashReturnType type) {
- switch(type) {
- case kHashReturnType.BASE64:
- return hash.Base64Encode();
- case kHashReturnType.HEX:
- return BitConverter.ToString(hash).Replace("-", "");
- case kHashReturnType.RAW:
- default:
- return hash;
- }
- }*/
}
}
diff --git a/server/Libraries/Square/NumericExtensions.cs b/server/Libraries/Square/NumericExtensions.cs
index 10e2957..9b18f73 100644
--- a/server/Libraries/Square/NumericExtensions.cs
+++ b/server/Libraries/Square/NumericExtensions.cs
@@ -6,6 +6,36 @@ using System.Threading.Tasks;
namespace Square {
public static class NumericExtensions {
+ public static byte[] Pack(this Single value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+ public static byte[] Pack(this Double value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this Int16 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this UInt16 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this Int32 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this UInt32 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this Int64 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
+
+ public static byte[] Pack(this UInt64 value) {
+ return BitConverter.GetBytes(value).HostToNetworkOrder();
+ }
}
}
diff --git a/server/Libraries/Square/Square.csproj b/server/Libraries/Square/Square.csproj
index 3a322fc..a8c16a9 100644
--- a/server/Libraries/Square/Square.csproj
+++ b/server/Libraries/Square/Square.csproj
@@ -40,7 +40,7 @@
-
+