thigh highs

running out of sock names
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-05-05 16:05:52 -05:00
parent 2393f94339
commit 583182e81b
5 changed files with 202 additions and 40 deletions

View file

@ -23,7 +23,9 @@ namespace Kneesocks {
private TcpClient Socket;
private NetworkStream Stream;
private string RawBuffer = "";
ReadBuffer Buffer;
private Frame PartialFrame = null;
private List<Frame> FrameBuffer = new List<Frame>();
public bool Disconnected { get; private set; } = false;
@ -38,16 +40,23 @@ namespace Kneesocks {
Socket = sock;
Socket.ReceiveTimeout = 1;
Stream = sock.GetStream();
Buffer = new ReadBuffer(Stream);
}
public Connection(UInt64 id, TcpClient sock) : this(sock) {
Id = id;
}
public Connection(Connection conn) {
Id = conn.Id;
public Connection(Connection conn, bool preserveId = true) {
if(preserveId)
_Id = conn._Id;
Socket = conn.Socket;
Stream = Socket.GetStream();
Stream = conn.Stream;
Buffer = conn.Buffer;
PartialFrame = conn.PartialFrame;
FrameBuffer = conn.FrameBuffer;
Disconnected = conn.Disconnected;
DisconnectReason = conn.DisconnectReason;
@ -57,11 +66,25 @@ namespace Kneesocks {
Headers = conn.Headers;
}
private void StartRead(ulong length) {
}
public byte[] Parse() {
byte[] readBuffer = null;
if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead();
if(readBuffer == null)
return null;
}
if(!Handshaked) {
if(Stream.)
return null;
} else {
OnParse();
}
}
@ -85,16 +108,16 @@ namespace Kneesocks {
}
// called after the client successfully handshakes
public virtual void OnOpen() { }
protected virtual void OnOpen() { }
// called when the thread manager iterates through
// the thread list and stops on this thread
public virtual void OnParse() { }
protected virtual void OnParse() { }
// called when data has been received
public virtual void OnReceive(byte[] data) { }
protected virtual void OnReceive(byte[] data) { }
// called when the connection is disconnected
public virtual void OnClose() { }
protected virtual void OnClose() { }
}
}

View file

@ -32,7 +32,29 @@ namespace Kneesocks {
public byte[] Mask { get; set; } = new byte[] { 0, 0, 0, 0 };
public byte Reserved { get; set; } = 0;
public byte[] Content { get; set; }
private int _HeaderLength = 0;
public int HeaderLength {
get {
if(_HeaderLength != 0)
return _HeaderLength;
int length = 2
+ (BodyLength >= 0x7E && BodyLength <= 0xFFFF ? 2 : 0)
+ (BodyLength > 0xFFFF ? 4 : 0)
+ (IsMasked ? 4 : 0);
return (_HeaderLength = length);
}
}
private int _BodyLength = 0;
public int BodyLength {
get {
return Content == null ? _BodyLength : Content.Length;
}
}
public byte[] Content { get; set; } = null;
public byte[] MaskedContent {
get {
long counter = 0;
@ -41,8 +63,8 @@ namespace Kneesocks {
}
public byte[] GetBytes() {
var headerSize = 2L;
var bodySize = Content.LongLength;
var headerSize = 2;
var bodySize = (UInt64)Content.LongLength;
var headerLengthFirstByte = (byte)Content.Length;
if(bodySize >= 0x7E && bodySize <= 0xFFFF) {
headerSize += 2;
@ -55,7 +77,7 @@ namespace Kneesocks {
if(IsMasked)
headerSize += 4;
var returnValue = new byte[headerSize + bodySize];
var returnValue = new byte[(UInt64)headerSize + bodySize];
returnValue[0] = (byte)(((byte)Opcode % 0x10)
| ((Reserved % 8) << 4)
| (IsFinal ? 0x80 : 0x0));
@ -76,44 +98,65 @@ namespace Kneesocks {
return returnValue;
}
public static Frame FromBytes(byte[] raw) {
public static int HeaderSizeFromBytes(byte[] raw) {
if(raw.Length < 2)
throw new FormatException("Need first two bytes to analyze");
var lengthByte = raw[1] & 0x7F;
return 2
+ ((raw[1] & 0x80) != 0 ? 4: 0)
+ (lengthByte == 0x7E ? 2 : 0)
+ (lengthByte == 0x7F ? 4 : 0);
}
public static Frame HeaderFromBytes(byte[] raw) {
if(raw.Length < 2)
throw new FormatException("Websocket frame cannot be less than two bytes long");
var rawOpcode = raw[0] & 0x0F;
if(!Enum.IsDefined(typeof(kOpcode), rawOpcode))
throw new FormatException("Opcode '0x"+ rawOpcode.ToString("X") +"' not understood");
throw new ArgumentException("Opcode '0x" + rawOpcode.ToString("X") + "' not understood");
var returnFrame = new Frame {
IsFinal = (raw[0] & 0x80) != 0,
Opcode = (kOpcode)rawOpcode,
IsFinal = (raw[0] & 0x80) != 0,
Opcode = (kOpcode)rawOpcode,
IsMasked = (raw[1] & 0x80) != 0,
Reserved = (byte)((raw[0] & 0x70) >> 4)
};
ulong bodyLength = raw[1] & 0x7Ful;
int headerOffset =
bodyLength < 0x7E
? 1
int headerOffset =
bodyLength < 0x7E
? 1
: (bodyLength == 0x7E ? 3 : 9);
if(raw.Length < headerOffset + 1)
throw new FormatException("Websocket frame is smaller than expected header size");
bodyLength = bodyLength < 0x7E ? 0 : bodyLength;
for(var i = headerOffset - 1; i > 0; --i)
bodyLength |= (ulong)raw[2 + i] << (8*(headerOffset - 1 - i));
bodyLength |= (ulong)raw[2 + i] << (8 * (headerOffset - 1 - i));
if(returnFrame.IsMasked) {
if(bodyLength > Int32.MaxValue)
throw new FormatException("Frame is too large to interpret");
returnFrame._BodyLength = (int)bodyLength;
if(returnFrame.IsMasked)
Array.Copy(raw, headerOffset + 1, returnFrame.Mask, 0, 4);
headerOffset += 4;
}
ulong expectedFrameLength = bodyLength + (uint)headerOffset + 1;
if(expectedFrameLength < (ulong)raw.LongLength)
throw new FormatException("Raw frame length ("+ (ulong)raw.LongLength + ") is less than described size ("+ expectedFrameLength + ")");
Array.Copy(raw, headerOffset + 1, returnFrame.Content, 0L, (long)bodyLength);
return returnFrame;
}
public static Frame FromBytes(byte[] raw) {
var returnFrame = HeaderFromBytes(raw);
uint expectedFrameLength = (uint)returnFrame.BodyLength + (uint)returnFrame.HeaderLength;
if(expectedFrameLength < (uint)raw.Length)
throw new FormatException("Raw frame length ("+ (uint)raw.Length + ") is less than described size ("+ expectedFrameLength + ")");
returnFrame.Content = new byte[returnFrame.BodyLength];
Array.Copy(raw, returnFrame.HeaderLength, returnFrame.Content, 0L, (long)returnFrame.BodyLength);
if(returnFrame.IsMasked)
returnFrame.Content = returnFrame.MaskedContent;

View file

@ -45,6 +45,7 @@
<Compile Include="Handshake.cs" />
<Compile Include="Pool.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReadBuffer.cs" />
<Compile Include="Server.cs" />
<Compile Include="Stack.cs" />
<Compile Include="Utilities.cs" />

View file

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Kneesocks {
class ReadBuffer {
private List<byte> Buffer;
private int ExpectedLength;
private string ExpectedString;
private NetworkStream Source;
private DateTime StartTime;
public bool IsReading { get; private set; } = false;
public ReadBuffer(NetworkStream source) {
Source = source;
}
public TimeSpan ElapsedReadTime {
get {
return DateTime.Now - StartTime;
}
}
private byte[] CheckBuffer() {
byte[] returnValue = null;
if(ExpectedString != null) {
var location = Encoding.ASCII.GetString(Buffer.ToArray()).IndexOf(ExpectedString);
if(location != -1) {
var fullJump = location + ExpectedString.Length;
returnValue = Buffer.Take(fullJump).ToArray();
Buffer = Buffer.Skip(fullJump).ToList();
IsReading = false;
}
} else {
if(Buffer.Count >= ExpectedLength) {
returnValue = Buffer.Take(ExpectedLength).ToArray();
Buffer = Buffer.Skip(ExpectedLength).ToList();
IsReading = false;
}
}
return returnValue;
}
public byte[] AttemptRead() {
if(!IsReading)
return null;
byte[] returnValue;
if((returnValue = CheckBuffer()) != null)
return returnValue;
var buffer = new byte[1024];
while(Source.DataAvailable) {
var readAmount = ExpectedString == null
? Math.Min(1024, ExpectedLength - Buffer.Count)
: 1024;
var bytesRead = Source.Read(buffer, 0, readAmount);
if(bytesRead == readAmount)
Buffer.AddRange(buffer);
else
Buffer.AddRange(buffer.Take(readAmount));
if((returnValue = CheckBuffer()) != null)
return returnValue;
}
return null;
}
public byte[] AttemptRead(int length) {
if(IsReading)
return null;
IsReading = true;
ExpectedLength = length;
ExpectedString = null;
StartTime = DateTime.Now;
return AttemptRead();
}
public byte[] AttemptRead(string terminator) {
if(IsReading)
return null;
IsReading = true;
ExpectedString = terminator;
StartTime = DateTime.Now;
return AttemptRead();
}
}
}

View file

@ -9,7 +9,6 @@ namespace Kneesocks {
public class Stack<T> where T : Connection {
private Pool<T> PoolRef = null;
private List<Connection> Clients = new List<Connection>();
private Mutex ClientsMutex = new Mutex();
private bool RunWithNoClients = false;
private bool Running = true;
private bool _finished = false;
@ -26,14 +25,10 @@ namespace Kneesocks {
RunWithNoClients = runWithNoClients;
}
public bool AddClient(Connection client) {
if(!ClientsMutex.WaitOne(5000))
return false;
Clients.Add(client);
ClientsMutex.ReleaseMutex();
return true;
public void AddClient(Connection client) {
lock(Clients) {
Clients.Add(client);
}
}
public int Count {