the squid in second platoon

f
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-09-08 16:06:55 -05:00
parent b49acd08d4
commit 331c050540
10 changed files with 145 additions and 51 deletions

View file

@ -271,16 +271,31 @@ Communication between the master server and clients will be done over a WebSocke
<th>#</th>
<th>Region</th>
<th>Type</th>
<th>if</th>
</thead>
<tr>
<td class="center">1</td>
<td>Succeeded</td>
<td>Boolean</td>
<td></td>
</tr>
<tr>
<tr style="border-bottom: 2px solid;">
<td class="center">2</td>
<td>Message</td>
<td>String</td>
<td>R<sub>1</sub></td>
</tr>
<tr>
<td class="center">2</td>
<td>Session Id</td>
<td>Packed Unsigned Long</td>
<td>&not;R<sub>1</sub></td>
</tr>
<tr>
<td class="center">3</td>
<td>Secret</td>
<td>Bytes (16)</td>
<td>&not;R<sub>1</sub></td>
</tr>
</table>
@ -430,8 +445,12 @@ Communication between the master server and clients will be done over a WebSocke
<th colspan="100" class="center">
ID 4: Server List Request<br />
[Encrypted] Requester<br />
<i>Bodyless Packet</i>
</th>
<thead>
<th colspan="100" class="center">
<i>Bodyless Packet</i>
</th>
</thead>
</thead>
</table>

View file

@ -51,7 +51,7 @@ namespace SockScape.Encryption {
try {
var ms = new MemoryStream(data);
var cs = new CryptoStream(ms,
new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
byte[] ret = new byte[data.Length];

View file

@ -48,8 +48,10 @@ namespace SockScape {
serverHandle.Start();
}
//var server = new Server<PlayerConnection>(6770, PoolManager.Pending);
//server.Start();
if(Configuration.General["Run Master"])
MasterIntraServer.Initialize();
MasterIntraClient.Initialize();
/*while(true) {
var send = Console.ReadLine();
@ -60,7 +62,9 @@ namespace SockScape {
Console.ReadLine();
//server.Stop();
MasterIntraClient.Close();
if(Configuration.General["Run Master"])
MasterIntraServer.Close();
}
}
}

View file

@ -21,6 +21,9 @@ namespace Glove.INI {
public double Dbl
=> this;
public bool Bool
=> this;
public static implicit operator string(Value value)
=> value.Raw;

View file

@ -2,29 +2,39 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.Remoting;
using System.Text;
using System.Threading.Tasks;
using Glove;
namespace SockScape {
static class MasterServerList {
public static Dictionary<UInt16, Server> Servers { get; }
private static Dictionary<UInt16, Server> _Servers
= new Dictionary<UInt16, Server>();
public static Dictionary<UInt16, Server> Servers {
get {
lock(_Servers) {
return _Servers.ToDictionary(x => x.Key,
x => x.Value);
}
}
}
public static void Write(Server server) {
lock(Servers) {
if(HasId(server.Id) && !Servers[server.Id].Address.Equals(server.Address))
lock(_Servers) {
if(HasId(server.Id) && !_Servers[server.Id].Address.Equals(server.Address))
Console.WriteLine($"{DateTime.Now.ToShortTimeString()} - Server {server.Id} has changed IP addresses.");
Servers[server.Id] = server;
_Servers[server.Id] = server;
}
}
public static Packet ReportPacket {
get {
lock(Servers) {
var packet = new Packet(kInterMasterId.ServerListing, ((ushort)Servers.Count).Pack());
foreach(var server in Servers)
lock(_Servers) {
var packet = new Packet(kInterMasterId.ServerListing, ((ushort)_Servers.Count).Pack());
foreach(var server in _Servers)
// TODO change this to support IPv6
packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack(),
server.Value.Address.MapToIPv4().ToString(), server.Value.Port.Pack());
@ -34,11 +44,24 @@ namespace SockScape {
}
}
public static bool HasId(UInt16 id)
=> Servers.ContainsKey(id);
public static void RemoveServersByOwners(IEnumerable<MasterIntraServer.Client> owners) {
lock(_Servers) {
_Servers = _Servers.Where(x => !owners.Contains(x.Value.Owner))
.ToDictionary(x => x.Key, x => x.Value);
}
}
public static void Clear()
=> Servers.Clear();
public static bool HasId(UInt16 id) {
lock(_Servers) {
return _Servers.ContainsKey(id);
}
}
public static void Clear() {
lock(_Servers) {
_Servers.Clear();
}
}
}
class Server {
@ -46,5 +69,6 @@ namespace SockScape {
public ushort UserCount { get; set; }
public IPAddress Address { get; set; }
public ushort Port { get; set; }
public MasterIntraServer.Client Owner { get; set; }
}
}

View file

@ -51,7 +51,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>

View file

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Kneesocks;
using Glove;
using SockScape.DAL;
using SockScape.Encryption;
namespace SockScape {
@ -18,7 +20,7 @@ namespace SockScape {
}
protected override void OnParse() {
}
protected override void OnReceive(byte[] data) {
@ -31,6 +33,11 @@ namespace SockScape {
return;
}
if(packet.Id != (int)kInterMasterId.KeyExchange && Encryptor == null) {
Disconnect(Frame.kClosingReason.ProtocolError, "You must exchange keys before performing any other operations.");
return;
}
switch((kInterMasterId)packet.Id) {
case kInterMasterId.KeyExchange:
Key.ParseResponsePacket(packet);
@ -42,10 +49,17 @@ namespace SockScape {
Encryptor = new StreamCipher(Key.PrivateKey);
break;
case kInterMasterId.LoginAttempt:
if(packet.RegionCount != 2)
break;
using(var db = new ScapeDb()) {
if(db.Users.)
}
break;
case kInterMasterId.RegistrationAttempt:
using(var db = new ScapeDb()) {
}
break;
default:
Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time.");

View file

@ -12,6 +12,7 @@ using SockScape.Encryption;
namespace SockScape {
static class MasterIntraClient {
private static Key Key;
private static BlockCipher Encryptor;
private static UdpClient Sock;
private static Thread ListeningThread;
@ -32,6 +33,12 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master Port"];
Sock = new UdpClient(Configuration.General["Master Addr"], port);
// TODO figure out what this has to do with ICMP (in server too)
uint IOC_IN = 0x80000000,
IOC_VENDOR = 0x18000000,
SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
Sock.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] {0}, null);
Key = new Key();
Encryptor = null;
@ -42,19 +49,22 @@ namespace SockScape {
public static void Listener() {
while(IsOpen) {
var endPoint = new IPEndPoint(0, 0);
var endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint);
LastMessageIn = DateTime.Now;
bool readRaw = Encryptor == null
|| data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
Packet packet =
Encryptor == null ? Packet.FromBytes(data)
: Packet.FromBytes(Encryptor.Parse(data));
readRaw ? Packet.FromBytes(data)
: Packet.FromBytes(Encryptor.Decrypt(data));
switch((kIntraMasterId)packet.Id) {
case kIntraMasterId.KeyExchange:
var responsePacket = Key.ParseRequestPacket(packet);
Encryptor = new StreamCipher(Key.PrivateKey);
Encryptor = new BlockCipher(Key.PrivateKey);
if(responsePacket != null)
Send(responsePacket);
else
@ -62,16 +72,14 @@ namespace SockScape {
break;
case kIntraMasterId.PositiveAck:
Console.WriteLine($"Packet type {packet[0]} accepted by master");
Console.WriteLine($"Packet type {packet[0].Raw[0]} accepted by master");
break;
case kIntraMasterId.NegativeAck:
Console.WriteLine($"Packet type {packet[0]} declined by master for reason {packet[1]}");
Console.WriteLine($"Packet type {packet[0].Raw[0]} declined by master for reason {packet[1].Str}");
break;
case kIntraMasterId.EncryptionError:
NextSendId = NextRecvId = 0;
Buffer.Clear();
Key = new Key();
Encryptor = null;
LastMessageIn = new DateTime(0);
@ -79,12 +87,12 @@ namespace SockScape {
}
}
if(LastMessageIn.Ticks != 0) {
if(Encryptor != null) {
if(DeltaLastOut.TotalSeconds > 2)
Send(Encryptor.Parse(ServerContext.StatusUpdatePacket.GetBytes()));
SendEncrypted(ServerContext.StatusUpdatePacket);
} else
if(DeltaLastOut.TotalSeconds > 10)
Send(new Packet(kIntraSlaveId.InitiationAttempt, Configuration.General["Master Secret"]));
Send(new Packet(kIntraSlaveId.InitiationAttempt, Configuration.General["Master Secret"].Str));
Thread.Sleep(1);
}
@ -94,11 +102,13 @@ namespace SockScape {
Send(packet.GetBytes());
}
public static void SendEncrypted(Packet packet) {
Send(Encryptor.Encrypt(packet.GetBytes()));
}
public static void Send(byte[] bytes) {
Sock.Send(bytes, bytes.Length);
LastMessageOut = DateTime.Now;
Buffer.Add(NextSendId, bytes);
++NextSendId;
}
public static void Close() {

View file

@ -12,7 +12,7 @@ using SockScape.DAL;
using SockScape.Encryption;
namespace SockScape {
static class MasterUdpServer {
static class MasterIntraServer {
private static Dictionary<string, Client> Prospects;
private static Dictionary<string, Client> Clients;
@ -30,7 +30,13 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master Port"];
Sock = new UdpClient(new IPEndPoint(IPAddress.Any, port));
// TODO figure out what this has to do with ICMP (in client too)
/*uint IOC_IN = 0x80000000,
IOC_VENDOR = 0x18000000,
SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
Sock.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] {0}, null);*/
IsOpen = true;
ListeningThread = new Thread(Listener);
ListeningThread.Start();
@ -38,7 +44,7 @@ namespace SockScape {
public static void Listener() {
while(IsOpen) {
IPEndPoint endPoint = new IPEndPoint(0, 0);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint);
var client = endPoint.ToString();
@ -48,7 +54,7 @@ namespace SockScape {
Packet packet =
encryptor == null ? Packet.FromBytes(data)
: Packet.FromBytes(encryptor.Parse(data));
: Packet.FromBytes(encryptor.Decrypt(data));
if(packet == null) {
if(encryptor != null)
@ -56,7 +62,11 @@ namespace SockScape {
continue;
}
Clients[client].LastReceive = DateTime.Now;
if(IsProspectConnected(client) && encryptor == null)
Prospects[client].LastReceive = DateTime.Now;
else if(IsClientConnected(client) && encryptor != null)
Clients[client].LastReceive = DateTime.Now;
switch((kIntraSlaveId)packet.Id) {
case kIntraSlaveId.InitiationAttempt:
if(packet.RegionCount != 1 || IsProspectConnected(client))
@ -81,7 +91,7 @@ namespace SockScape {
var privateKey = Prospects[client].Key.ParseResponsePacket(packet);
if(privateKey != -1) {
Prospects[client].LastReceive = DateTime.Now;
Prospects[client].Encryptor = new StreamCipher(privateKey);
Prospects[client].Encryptor = new BlockCipher(privateKey);
Clients[client] = Prospects[client];
Prospects.Remove(client);
} else
@ -92,7 +102,7 @@ namespace SockScape {
if(!IsClientConnected(client) || packet.RegionCount < 1)
break;
if(packet.CheckRegions(0, 1)) {
if(!packet.CheckRegions(0, 1)) {
NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed.");
break;
}
@ -104,14 +114,15 @@ namespace SockScape {
}
for(byte i = 0; i < serverCount; ++i) {
if(!packet.CheckRegions(2 + 3 * i, 2, 2, 2))
if(!packet.CheckRegions(1 + 3 * i, 2, 2, 2))
continue;
MasterServerList.Write(new Server {
Id = packet[2 + 3 * i].Raw.UnpackUInt16(),
UserCount = packet[3 + 3 * i].Raw.UnpackUInt16(),
Id = packet[1 + 3 * i].Raw.UnpackUInt16(),
UserCount = packet[2 + 3 * i].Raw.UnpackUInt16(),
Address = endPoint.Address,
Port = packet[4 + 3 * i].Raw.UnpackUInt16()
Port = packet[3 + 3 * i].Raw.UnpackUInt16(),
Owner = Clients[client]
});
}
@ -120,7 +131,12 @@ namespace SockScape {
}
}
Prospects = Prospects.Where(x => x.Value.ReceiveDelta.Seconds < 10)
.ToDictionary(x => x.Key, x => x.Value);
var expiredClients = Clients.Where(x => x.Value.ReceiveDelta.Seconds > 60).Select(x => x.Value).ToList();
if(expiredClients.Count > 0)
MasterServerList.RemoveServersByOwners(expiredClients);
Thread.Sleep(1);
}
@ -149,23 +165,23 @@ namespace SockScape {
return Clients.ContainsKey(client);
}
private static void PositiveAck(IPEndPoint endPoint, StreamCipher cipher, kIntraSlaveId id) {
Send(cipher.Parse(new Packet(kIntraMasterId.PositiveAck, id).GetBytes()), endPoint);
private static void PositiveAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id) {
Send(cipher.Encrypt(new Packet(kIntraMasterId.PositiveAck, (byte)id).GetBytes()), endPoint);
}
private static void NegativeAck(IPEndPoint endPoint, StreamCipher cipher, kIntraSlaveId id, string message = "An error occurred while parsing a packet.") {
Send(cipher.Parse(new Packet(kIntraMasterId.NegativeAck, id, message).GetBytes()), endPoint);
private static void NegativeAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id, string message = "An error occurred while parsing a packet.") {
Send(cipher.Encrypt(new Packet(kIntraMasterId.NegativeAck, (byte)id, message).GetBytes()), endPoint);
}
private static void EncryptionError(IPEndPoint endPoint, string message = "A general encryption error has occurred. Renegotiation required.") {
Send(new Packet(kIntraMasterId.EncryptionError, message), endPoint);
}
class Client {
public class Client {
public IPEndPoint Address { get; set; }
public DateTime LastReceive { get; set; }
public TimeSpan ReceiveDelta => DateTime.Now - LastReceive;
public StreamCipher Encryptor { get; set; }
public BlockCipher Encryptor { get; set; }
public Key Key { get; set; }
}
}

View file

@ -88,6 +88,10 @@ namespace SockScape {
Regions.Add((byte[])region);
else if(region.GetType() == typeof(string))
Regions.Add(((string)region).GetBytes());
else if(region.GetType() == typeof(byte))
Regions.Add(new[] { (byte)region });
else
Console.WriteLine($"Could not add region {region} of type {region.GetType()}.");
return this;
}
@ -104,7 +108,7 @@ namespace SockScape {
return false;
for(int i = 0; i < lengths.Length; ++i) {
if(this[startIndex + i].Raw.Length == lengths[i])
if(this[startIndex + i].Raw.Length != lengths[i])
return false;
}