VACUUM DOT MATRIX MONTHLY

note on my desk
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-09-12 15:59:55 -05:00
parent 4b1adda2a6
commit 978977282d
8 changed files with 91 additions and 36 deletions

View file

@ -283,19 +283,31 @@ Communication between the master server and clients will be done over a WebSocke
<td class="center">2</td> <td class="center">2</td>
<td>Message</td> <td>Message</td>
<td>String</td> <td>String</td>
<td>R<sub>1</sub></td> <td>&not;R<sub>1</sub></td>
</tr> </tr>
<tr> <tr>
<td class="center">2</td> <td class="center">2</td>
<td>Session Id</td> <td>Session Id</td>
<td>Packed Unsigned Long</td> <td>Packed Unsigned Long</td>
<td>&not;R<sub>1</sub></td> <td>R<sub>1</sub></td>
</tr> </tr>
<tr> <tr>
<td class="center">3</td> <td class="center">3</td>
<td>Secret</td> <td>Secret</td>
<td>Bytes (16)</td> <td>Bytes (16)</td>
<td>&not;R<sub>1</sub></td> <td>R<sub>1</sub></td>
</tr>
<tr>
<td class="center">4</td>
<td>Server Address</td>
<td>IPv4 String</td>
<td>R<sub>1</sub></td>
</tr>
<tr>
<td class="center">5</td>
<td>Server Port</td>
<td>Packed Unsigned Short</td>
<td>R<sub>1</sub></td>
</tr> </tr>
</table> </table>
@ -345,25 +357,15 @@ Communication between the master server and clients will be done over a WebSocke
<td colspan="2">Iterated over <i>n</i> (0 &leq; <i>i</i> &leq; <i>n - 1</i>)</td> <td colspan="2">Iterated over <i>n</i> (0 &leq; <i>i</i> &leq; <i>n - 1</i>)</td>
</tr> </tr>
<tr> <tr>
<td class="center">2 + 4<i>i</i></td> <td class="center">2 + 2<i>i</i></td>
<td>Server Id</td> <td>Server Id</td>
<td>Packed Unsigned Short</td> <td>Packed Unsigned Short</td>
</tr> </tr>
<tr> <tr>
<td class="center">3 + 4<i>i</i></td> <td class="center">3 + 2<i>i</i></td>
<td>User Count</td> <td>User Count</td>
<td>Packed Unsigned Short</td> <td>Packed Unsigned Short</td>
</tr> </tr>
<tr>
<td class="center">4 + 4<i>i</i></td>
<td>IP Address</td>
<td>IPv4 String</td>
</tr>
<tr>
<td class="center">5 + 4<i>i</i></td>
<td>Port</td>
<td>Packed Unsigned Short</td>
</tr>
</table> </table>
#### Client to Master #### Client to Master
@ -409,6 +411,11 @@ Communication between the master server and clients will be done over a WebSocke
<td>Password</td> <td>Password</td>
<td>String</td> <td>String</td>
</tr> </tr>
<tr>
<td class="center">3</td>
<td>Server Id</td>
<td>Packed Unsigned Short</td>
</tr>
</table> </table>
<table style="margin-right: 8px; margin-bottom: 8px;"> <table style="margin-right: 8px; margin-bottom: 8px;">

View file

@ -17,6 +17,13 @@ namespace SockScape.DAL {
[Required, Index(IsUnique = true)] [Required, Index(IsUnique = true)]
public byte[] Secret { get; set; } public byte[] Secret { get; set; }
[Required]
public DateTime LastPing { get; set; }
[NotMapped]
public TimeSpan DeltaLastPing
=> DateTime.UtcNow - LastPing;
[Required] [Required]
public int ServerId { get; set; } public int ServerId { get; set; }
} }

View file

@ -171,9 +171,9 @@ namespace Kneesocks {
internal void Parse() { internal void Parse() {
if(Handshaked) { if(Handshaked) {
if(!Buffer.IsReading) { if(!Buffer.IsReading) {
if(TimeSinceLastPing.Seconds > TimeoutInterval) { if(TimeSinceLastPing.TotalSeconds > TimeoutInterval) {
Disconnect(Frame.kClosingReason.Normal, "Ping response timed out."); Disconnect(Frame.kClosingReason.Normal, "Ping response timed out.");
} else if(TimeSinceLastPing.Seconds > PingInterval && !AwaitingPingResponse) { } else if(TimeSinceLastPing.TotalSeconds > PingInterval && !AwaitingPingResponse) {
var frameBytes = new Frame { var frameBytes = new Frame {
IsFinal = true, IsFinal = true,
IsMasked = false, IsMasked = false,
@ -204,7 +204,7 @@ namespace Kneesocks {
if(Buffer.IsReading) { if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead(); readBuffer = Buffer.AttemptRead();
if(readBuffer == null) { if(readBuffer == null) {
if((!Handshaked || (Handshaked && FirstTwoBytes != null)) && Buffer.ElapsedReadTime.Seconds > (Handshaked ? 300 : 30)) if((!Handshaked || (Handshaked && FirstTwoBytes != null)) && Buffer.ElapsedReadTime.TotalSeconds > (Handshaked ? 300 : 30))
Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response"); Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response");
return; return;

View file

@ -36,8 +36,7 @@ namespace SockScape {
var packet = new Packet(kInterMasterId.ServerListing, ((ushort)_Servers.Count).Pack()); var packet = new Packet(kInterMasterId.ServerListing, ((ushort)_Servers.Count).Pack());
foreach(var server in _Servers) foreach(var server in _Servers)
// TODO change this to support IPv6 // TODO change this to support IPv6
packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack(), packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack());
server.Value.Address.MapToIPv4().ToString(), server.Value.Port.Pack());
return packet; return packet;
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
@ -16,7 +17,7 @@ namespace SockScape {
protected override void OnOpen() { protected override void OnOpen() {
Key = new Key(); Key = new Key();
Send(Key.GenerateRequestPacket().GetBytes()); Send(Key.GenerateRequestPacket());
} }
protected override void OnParse() { protected override void OnParse() {
@ -49,11 +50,44 @@ namespace SockScape {
Encryptor = new StreamCipher(Key.PrivateKey); Encryptor = new StreamCipher(Key.PrivateKey);
break; break;
case kInterMasterId.LoginAttempt: case kInterMasterId.LoginAttempt:
if(packet.RegionCount != 2) if(packet.RegionCount != 3 || !packet.CheckRegions(2, 2))
break; break;
using(var db = new ScapeDb()) { using(var db = new ScapeDb()) {
if(db.Users.) User user;
if((user = db.Users.FirstOrDefault(x => x.Username == packet[0])) == null) {
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "User does not exist."));
break;
}
if(!packet[1].Str.CheckPassword(user.Password)) {
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "Password is incorrect."));
break;
}
if(user.Session?.DeltaLastPing.TotalMinutes < 3) {
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "You are already logged in. Log out or try again shortly."));
break;
}
ushort server = packet[2].Raw.UnpackUInt16();
if(!MasterServerList.HasId(server)) {
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "The world you have specified is offline."));
break;
}
if(user.Session?.DeltaLastPing.TotalMinutes >= 3) {
db.Entry(user.Session).State = EntityState.Deleted;
db.SaveChanges();
}
db.Sessions.Add(new Session {
Id = user.Id,
Secret = RNG.NextBytes(16),
ServerId = server,
LastPing = DateTime.UtcNow
});
db.SaveChanges();
} }
break; break;
case kInterMasterId.RegistrationAttempt: case kInterMasterId.RegistrationAttempt:
@ -68,5 +102,13 @@ namespace SockScape {
Console.WriteLine($"{Id} says {data.GetString()}"); Console.WriteLine($"{Id} says {data.GetString()}");
} }
private void Send(Packet packet) {
Send(packet.GetBytes());
}
private void SendEncrypted(Packet packet) {
Send(Encryptor.Parse(packet.GetBytes()));
}
} }
} }

View file

@ -20,11 +20,11 @@ namespace SockScape {
private static DateTime LastMessageOut = new DateTime(0); private static DateTime LastMessageOut = new DateTime(0);
private static TimeSpan DeltaLastOut private static TimeSpan DeltaLastOut
=> DateTime.Now - LastMessageOut; => DateTime.UtcNow - LastMessageOut;
private static DateTime LastMessageIn = new DateTime(0); private static DateTime LastMessageIn = new DateTime(0);
private static TimeSpan DeltaLastIn private static TimeSpan DeltaLastIn
=> DateTime.Now - LastMessageIn; => DateTime.UtcNow - LastMessageIn;
public static void Initialize() { public static void Initialize() {
if(IsOpen || ListeningThread != null) if(IsOpen || ListeningThread != null)
@ -52,7 +52,7 @@ namespace SockScape {
var endPoint = new IPEndPoint(IPAddress.Any, 0); var endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) { while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint); var data = Sock.Receive(ref endPoint);
LastMessageIn = DateTime.Now; LastMessageIn = DateTime.UtcNow;
bool readRaw = Encryptor == null bool readRaw = Encryptor == null
|| data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber); || data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
@ -108,7 +108,7 @@ namespace SockScape {
public static void Send(byte[] bytes) { public static void Send(byte[] bytes) {
Sock.Send(bytes, bytes.Length); Sock.Send(bytes, bytes.Length);
LastMessageOut = DateTime.Now; LastMessageOut = DateTime.UtcNow;
} }
public static void Close() { public static void Close() {

View file

@ -63,9 +63,9 @@ namespace SockScape {
} }
if(IsProspectConnected(client) && encryptor == null) if(IsProspectConnected(client) && encryptor == null)
Prospects[client].LastReceive = DateTime.Now; Prospects[client].LastReceive = DateTime.UtcNow;
else if(IsClientConnected(client) && encryptor != null) else if(IsClientConnected(client) && encryptor != null)
Clients[client].LastReceive = DateTime.Now; Clients[client].LastReceive = DateTime.UtcNow;
switch((kIntraSlaveId)packet.Id) { switch((kIntraSlaveId)packet.Id) {
case kIntraSlaveId.InitiationAttempt: case kIntraSlaveId.InitiationAttempt:
@ -75,7 +75,7 @@ namespace SockScape {
if(packet[0] == Configuration.General["Master Secret"]) { if(packet[0] == Configuration.General["Master Secret"]) {
var key = new Key(); var key = new Key();
Prospects[client] = new Client { Prospects[client] = new Client {
LastReceive = DateTime.Now, LastReceive = DateTime.UtcNow,
Address = endPoint, Address = endPoint,
Key = key Key = key
}; };
@ -90,7 +90,7 @@ namespace SockScape {
var privateKey = Prospects[client].Key.ParseResponsePacket(packet); var privateKey = Prospects[client].Key.ParseResponsePacket(packet);
if(privateKey != -1) { if(privateKey != -1) {
Prospects[client].LastReceive = DateTime.Now; Prospects[client].LastReceive = DateTime.UtcNow;
Prospects[client].Encryptor = new BlockCipher(privateKey); Prospects[client].Encryptor = new BlockCipher(privateKey);
Clients[client] = Prospects[client]; Clients[client] = Prospects[client];
Prospects.Remove(client); Prospects.Remove(client);
@ -131,10 +131,10 @@ namespace SockScape {
} }
} }
Prospects = Prospects.Where(x => x.Value.ReceiveDelta.Seconds < 10) Prospects = Prospects.Where(x => x.Value.ReceiveDelta.TotalSeconds < 10)
.ToDictionary(x => x.Key, x => x.Value); .ToDictionary(x => x.Key, x => x.Value);
var expiredClients = Clients.Where(x => x.Value.ReceiveDelta.Seconds > 60).Select(x => x.Value).ToList(); var expiredClients = Clients.Where(x => x.Value.ReceiveDelta.TotalSeconds > 60).Select(x => x.Value).ToList();
if(expiredClients.Count > 0) if(expiredClients.Count > 0)
MasterServerList.RemoveServersByOwners(expiredClients); MasterServerList.RemoveServersByOwners(expiredClients);
@ -180,7 +180,7 @@ namespace SockScape {
public class Client { public class Client {
public IPEndPoint Address { get; set; } public IPEndPoint Address { get; set; }
public DateTime LastReceive { get; set; } public DateTime LastReceive { get; set; }
public TimeSpan ReceiveDelta => DateTime.Now - LastReceive; public TimeSpan ReceiveDelta => DateTime.UtcNow - LastReceive;
public BlockCipher Encryptor { get; set; } public BlockCipher Encryptor { get; set; }
public Key Key { get; set; } public Key Key { get; set; }
} }

View file

@ -17,7 +17,7 @@ namespace SockScape {
} }
protected override void OnParse() { protected override void OnParse() {
if((DateTime.UtcNow - ConnectionOpened).Seconds > 60) { if((DateTime.UtcNow - ConnectionOpened).TotalSeconds > 60) {
Disconnect(Frame.kClosingReason.ProtocolError, "Logon request timed out."); Disconnect(Frame.kClosingReason.ProtocolError, "Logon request timed out.");
} }
} }