thigh highs
running out of sock names
This commit is contained in:
parent
2393f94339
commit
583182e81b
5 changed files with 202 additions and 40 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
public byte[] Parse() {
|
||||
if(!Handshaked) {
|
||||
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() { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,13 +98,24 @@ 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,
|
||||
|
@ -102,18 +135,28 @@ namespace Kneesocks {
|
|||
|
||||
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;
|
||||
|
||||
return returnFrame;
|
||||
}
|
||||
|
||||
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 + ")");
|
||||
public static Frame FromBytes(byte[] raw) {
|
||||
var returnFrame = HeaderFromBytes(raw);
|
||||
|
||||
Array.Copy(raw, headerOffset + 1, returnFrame.Content, 0L, (long)bodyLength);
|
||||
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;
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
100
server/Kneesocks/ReadBuffer.cs
Normal file
100
server/Kneesocks/ReadBuffer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
public void AddClient(Connection client) {
|
||||
lock(Clients) {
|
||||
Clients.Add(client);
|
||||
|
||||
ClientsMutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count {
|
||||
|
|
Loading…
Reference in a new issue