udplease go away

woomy
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-08-16 16:01:08 -05:00
parent b11b9957ac
commit 8867c3051a
7 changed files with 222 additions and 241 deletions

View file

@ -5,6 +5,8 @@ const enum kPacketId {
}
class Packet {
private static magicNumber: Uint8Array = new Uint8Array([0xF0, 0x9F, 0xA6, 0x91]);
private _id: kPacketId;
public get id(): kPacketId {
return this._id;
@ -47,10 +49,14 @@ class Packet {
public static fromBytes(bytes: Uint8Array): Packet {
var packet = new Packet;
packet._id = bytes[0];
var regionCount = bytes[1];
if(!bytes.subarray(0, 4).every((v, i) => v === Packet.magicNumber[i]))
return null;
packet._id = bytes[4];
var regionCount = bytes[5];
var regionLengths = [];
var ptr = 2;
var ptr = 6;
for(var i = 0; i < regionCount; ++i) {
if(bytes[ptr] < 0xFE)
regionLengths.push(bytes[ptr]);
@ -74,7 +80,7 @@ class Packet {
}
public getBytes(): Uint8Array {
var headerSize = 2, bodySize = 0;
var headerSize = 6, bodySize = 0;
this._regions.forEach(region => {
bodySize += region.byteLength;
@ -86,9 +92,10 @@ class Packet {
});
var buffer = new Uint8Array(headerSize + bodySize);
var headerPtr = 2, bodyPtr = headerSize;
buffer[0] = this._id % 256;
buffer[1] = this._regions.length;
var headerPtr = 6, bodyPtr = headerSize;
buffer.set(Packet.magicNumber, 0);
buffer[4] = this._id % 256;
buffer[5] = this._regions.length;
this._regions.forEach(region => {
var regionLength = region.byteLength;
if(regionLength < 0xFE)

View file

@ -10,9 +10,10 @@ All references to the 'byte' in this document refers to individual 8-bit octets,
Because the body of the packet is a sequence of many different regions of byte data that is not delimited, it is necessary for the header of the packet to determine boundaries for the regions of data.
* The first byte is the packet id, the meanings of which are defined in the [_Packet IDs_](#packet-ids) section.
* The second byte is the number of byte regions in the packet.
* The bytes following the second byte are a list of binary length segments, each of which correspond to the number of bytes in its respective region. They each follow this format:
* The first four bytes will always be 0xF0, 0x9F, 0xA6, 0x91. If this is not set properly, the endpoint must close the connection.
* The fifth byte is the packet id, the meanings of which are defined in the [_Packet IDs_](#packet-ids) section.
* The sixth byte is the number of byte regions in the packet.
* The bytes following the sixth byte are a list of binary length segments, each of which correspond to the number of bytes in its respective region. They each follow this format:
* If length is less than 254, the length of the region is stored in a single byte.
* If length is greater than or equal to 254 but less than 65,536, the first byte of the lenght segment should be 254 and the following two bytes is the length of the region.
* If length is greater than or equal to 65,536, the first byte of the length segment should be 255 and the following four bytes is the length of the region.
@ -37,46 +38,24 @@ A packet ID may have a specific "direction" of communication, in that an endpoin
#### Server to Client
<div style="display: flex; flex-wrap: wrap;">
<!--
<table class="float">
<thead>
<th colspan="100" class="center">
ID 0: Key Exchange<br />
Requester
</th>
</thead>
<thead>
<th colspan="2" class="right">#</th>
<th>Region</th>
<th>Type</th>
</thead>
<tr>
<td><i>s &isin; [0, 2]</i></td>
<td class="right">1</td>
<td>Step</td>
<td>Uint8</td>
</tr>
<tr>
<td><i>s = 0</i></td>
<td class="right">2</td>
<td>Generator</td>
<td>Big Int</td>
</tr>
<tr>
<td><i>s = 0</i></td>
<td class="right">3</td>
<td>Modulus</td>
<td>Big Int</td>
</tr>
<tr>
<td><i>s = 1</i></td>
<td class="right">2</td>
<td>Server Key</td>
<td>Big Int</td>
</tr>
</table>
-->
TODO: populate
#### Client to Server
TODO: populate
## Master/Slave Servers
To keep track of the status of multiple servers from a centralized point that the client may query, each server must be able to communicate with a "master" server that will record and dispense information regarding all servers to clients. All servers that report to the master server will hereby be refered to as "slave" servers.
Communication between master and slave servers will be done over a UDP connection on a port that is defined by the master server's configuration. The protocol used for this communication is identical to the protocol defined for standard client/server communication; however, the [_Packet IDs_](#TODO) are defined differently.
Communication between the master server and clients will be done over a WebSocket connection on a port that is defined by the master server's configuration. The protocol used for this communication is identical to the protocol defined for standard client/server communication; however, the [_Packet IDs_](#TODO) are defined differently.
### Master/Slave Packet IDs
#### Master to Slave
<table style="margin-right: 8px; margin-bottom: 8px;">
<thead>
<th colspan="100" class="center">
@ -120,16 +99,11 @@ A packet ID may have a specific "direction" of communication, in that an endpoin
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Succeeded</td>
<td>Boolean</td>
</tr>
<tr>
<td class="center">3</td>
<td class="center">2</td>
<td>Message</td>
<td>String</td>
</tr>
@ -149,25 +123,18 @@ A packet ID may have a specific "direction" of communication, in that an endpoin
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Succeeded</td>
<td>Boolean</td>
</tr>
<tr>
<td class="center">3</td>
<td class="center">2</td>
<td>Message</td>
<td>String</td>
</tr>
</table>
</div>
#### Client to Server
#### Slave to Master
<div style="display: flex; flex-wrap: wrap;">
<table style="margin-right: 8px; margin-bottom: 8px;">
<thead>
<th colspan="100" class="center">
@ -201,16 +168,11 @@ A packet ID may have a specific "direction" of communication, in that an endpoin
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Username</td>
<td>String</td>
</tr>
<tr>
<td class="center">3</td>
<td class="center">2</td>
<td>Password</td>
<td>String</td>
</tr>
@ -230,26 +192,26 @@ A packet ID may have a specific "direction" of communication, in that an endpoin
</thead>
<tr>
<td class="center">1</td>
<td>Check Const</td>
<td>String</td>
</tr>
<tr>
<td class="center">2</td>
<td>Username</td>
<td>String</td>
</tr>
<tr>
<td class="center">3</td>
<td class="center">2</td>
<td>Password</td>
<td>String</td>
</tr>
<tr>
<td class="center">4</td>
<td class="center">3</td>
<td>Email</td>
<td>String</td>
</tr>
</table>
</div>
### Master/Client Packet IDs
#### Master to Client
#### Client to Master
## Sockstamps

View file

@ -23,7 +23,8 @@ namespace SockScape {
InitialCount = 3,
InitialSize = 3,
SizeGrowth = 3,
MaxSize = 100
MaxSize = 100,
MaxTotal = server["Max Users"] ?? Configuration.General["Max Users"]
};
pools.Add(server["Id"], pool);

View file

@ -20,6 +20,9 @@ namespace Kneesocks {
// maximum number of threads that will be spawned
// 0 means no limit
public int MaxCount { get; set; } = 0;
// maximum amount of total connections in the pool
// 0 means no limit
public int MaxTotal { get; set; } = 0;
// maximum number of connections in a thread that exceeds the calculated
// amount for the pool's thread count before the connection redistribution
// function is called
@ -81,6 +84,9 @@ namespace Kneesocks {
if(Disposed)
return false;
if(MaxTotal != 0 && Connections.Count >= MaxTotal)
return false;
lock(Threads) {
foreach(var thread in Threads) {
if(thread.Stack.Count < FullThreadSize) {

View file

@ -49,7 +49,9 @@ namespace Kneesocks {
Server = this
};
templatedConnection.Initialize(Socket.AcceptTcpClient());
ConnectionPool.AddConnection(templatedConnection);
if(!ConnectionPool.AddConnection(templatedConnection))
templatedConnection.Disconnect("Connection pooler rejected connection.");
}
Thread.Sleep(100);

View file

@ -7,27 +7,29 @@ using Glove;
namespace SockScape {
class Packet {
private static readonly byte[] MagicNumber = { 0xF0, 0x9F, 0xA6, 0x91 };
public enum kId {
KeyExchange = 0,
LoginAttempt,
RegistrationAttempt
}
private static Packet ErrorPacket {
get => new Packet { IsLegal = false };
}
public static Packet FromBytes(byte[] raw) {
if(raw.Length < 3)
return ErrorPacket;
if(raw.Length < 7)
return null;
Packet packet = new Packet();
if(!Enum.IsDefined(typeof(kId), (int)raw[0]))
return ErrorPacket;
packet.Id = (kId)raw[0];
var regionCount = raw[1];
if(!Enum.IsDefined(typeof(kId), (int)raw[4]))
return null;
if(!raw.Subset(0, 4).SequenceEqual(MagicNumber))
return null;
packet.Id = (kId)raw[4];
var regionCount = raw[5];
var regionLengths = new List<uint>();
var headerPtr = 2;
var headerPtr = 6;
for(var i = 0; i < regionCount; ++i) {
regionLengths.Add(0);
var first = raw[headerPtr];
@ -36,22 +38,22 @@ namespace SockScape {
++headerPtr;
} else if(first == 254) {
if(headerPtr + 3 < raw.Length)
return ErrorPacket;
return null;
regionLengths[i] = raw.Subset(headerPtr + 1, 2).UnpackUInt16();
headerPtr += 3;
} else {
if(headerPtr + 5 < raw.Length)
return ErrorPacket;
return null;
regionLengths[i] = raw.Subset(headerPtr + 1, 4).UnpackUInt32();
headerPtr += 5;
}
if(headerPtr > raw.Length)
return ErrorPacket;
return null;
}
if(headerPtr + regionLengths.Sum(x => x) > raw.Length)
return ErrorPacket;
return null;
long bodyPtr = headerPtr;
foreach(var regionLength in regionLengths) {
@ -96,10 +98,11 @@ namespace SockScape {
if(!IsLegal)
return null;
var header = new List<byte> {
(byte)Id,
(byte)RegionCount
};
var header = new List<byte>();
header.AddRange(MagicNumber);
header.Add((byte)Id);
header.Add((byte)RegionCount);
IEnumerable<byte> body = new byte[0];
foreach(var region in Regions) {
if(region.Length < 0xFE)

View file

@ -32,7 +32,7 @@ namespace SockScape {
Encryptor == null ? Packet.FromBytes(data)
: Packet.FromBytes(Encryptor.Parse(data));
if(!packet.IsLegal) {
if(packet == null) {
Disconnect(Frame.kClosingReason.ProtocolError, "Packet received was not legal.");
return;
}