VACUUM DOT MATRIX MONTHLY
note on my desk
This commit is contained in:
parent
4b1adda2a6
commit
978977282d
8 changed files with 91 additions and 36 deletions
37
protocol.md
37
protocol.md
|
@ -283,19 +283,31 @@ Communication between the master server and clients will be done over a WebSocke
|
|||
<td class="center">2</td>
|
||||
<td>Message</td>
|
||||
<td>String</td>
|
||||
<td>R<sub>1</sub></td>
|
||||
<td>¬R<sub>1</sub></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="center">2</td>
|
||||
<td>Session Id</td>
|
||||
<td>Packed Unsigned Long</td>
|
||||
<td>¬R<sub>1</sub></td>
|
||||
<td>R<sub>1</sub></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="center">3</td>
|
||||
<td>Secret</td>
|
||||
<td>Bytes (16)</td>
|
||||
<td>¬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>
|
||||
</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 ≤ <i>i</i> ≤ <i>n - 1</i>)</td>
|
||||
</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>Packed Unsigned Short</td>
|
||||
</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>Packed Unsigned Short</td>
|
||||
</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>
|
||||
|
||||
#### Client to Master
|
||||
|
@ -409,6 +411,11 @@ Communication between the master server and clients will be done over a WebSocke
|
|||
<td>Password</td>
|
||||
<td>String</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="center">3</td>
|
||||
<td>Server Id</td>
|
||||
<td>Packed Unsigned Short</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table style="margin-right: 8px; margin-bottom: 8px;">
|
||||
|
|
|
@ -17,6 +17,13 @@ namespace SockScape.DAL {
|
|||
[Required, Index(IsUnique = true)]
|
||||
public byte[] Secret { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime LastPing { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public TimeSpan DeltaLastPing
|
||||
=> DateTime.UtcNow - LastPing;
|
||||
|
||||
[Required]
|
||||
public int ServerId { get; set; }
|
||||
}
|
||||
|
|
|
@ -171,9 +171,9 @@ namespace Kneesocks {
|
|||
internal void Parse() {
|
||||
if(Handshaked) {
|
||||
if(!Buffer.IsReading) {
|
||||
if(TimeSinceLastPing.Seconds > TimeoutInterval) {
|
||||
if(TimeSinceLastPing.TotalSeconds > TimeoutInterval) {
|
||||
Disconnect(Frame.kClosingReason.Normal, "Ping response timed out.");
|
||||
} else if(TimeSinceLastPing.Seconds > PingInterval && !AwaitingPingResponse) {
|
||||
} else if(TimeSinceLastPing.TotalSeconds > PingInterval && !AwaitingPingResponse) {
|
||||
var frameBytes = new Frame {
|
||||
IsFinal = true,
|
||||
IsMasked = false,
|
||||
|
@ -204,7 +204,7 @@ namespace Kneesocks {
|
|||
if(Buffer.IsReading) {
|
||||
readBuffer = Buffer.AttemptRead();
|
||||
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");
|
||||
|
||||
return;
|
||||
|
|
|
@ -36,8 +36,7 @@ namespace SockScape {
|
|||
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());
|
||||
packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack());
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
@ -47,7 +46,7 @@ namespace SockScape {
|
|||
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);
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
@ -16,7 +17,7 @@ namespace SockScape {
|
|||
|
||||
protected override void OnOpen() {
|
||||
Key = new Key();
|
||||
Send(Key.GenerateRequestPacket().GetBytes());
|
||||
Send(Key.GenerateRequestPacket());
|
||||
}
|
||||
|
||||
protected override void OnParse() {
|
||||
|
@ -49,11 +50,44 @@ namespace SockScape {
|
|||
Encryptor = new StreamCipher(Key.PrivateKey);
|
||||
break;
|
||||
case kInterMasterId.LoginAttempt:
|
||||
if(packet.RegionCount != 2)
|
||||
if(packet.RegionCount != 3 || !packet.CheckRegions(2, 2))
|
||||
break;
|
||||
|
||||
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;
|
||||
case kInterMasterId.RegistrationAttempt:
|
||||
|
@ -68,5 +102,13 @@ namespace SockScape {
|
|||
|
||||
Console.WriteLine($"{Id} says {data.GetString()}");
|
||||
}
|
||||
|
||||
private void Send(Packet packet) {
|
||||
Send(packet.GetBytes());
|
||||
}
|
||||
|
||||
private void SendEncrypted(Packet packet) {
|
||||
Send(Encryptor.Parse(packet.GetBytes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,11 +20,11 @@ namespace SockScape {
|
|||
|
||||
private static DateTime LastMessageOut = new DateTime(0);
|
||||
private static TimeSpan DeltaLastOut
|
||||
=> DateTime.Now - LastMessageOut;
|
||||
=> DateTime.UtcNow - LastMessageOut;
|
||||
|
||||
private static DateTime LastMessageIn = new DateTime(0);
|
||||
private static TimeSpan DeltaLastIn
|
||||
=> DateTime.Now - LastMessageIn;
|
||||
=> DateTime.UtcNow - LastMessageIn;
|
||||
|
||||
public static void Initialize() {
|
||||
if(IsOpen || ListeningThread != null)
|
||||
|
@ -52,7 +52,7 @@ namespace SockScape {
|
|||
var endPoint = new IPEndPoint(IPAddress.Any, 0);
|
||||
while(Sock.Available > 0) {
|
||||
var data = Sock.Receive(ref endPoint);
|
||||
LastMessageIn = DateTime.Now;
|
||||
LastMessageIn = DateTime.UtcNow;
|
||||
|
||||
bool readRaw = Encryptor == null
|
||||
|| data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
|
||||
|
@ -108,7 +108,7 @@ namespace SockScape {
|
|||
|
||||
public static void Send(byte[] bytes) {
|
||||
Sock.Send(bytes, bytes.Length);
|
||||
LastMessageOut = DateTime.Now;
|
||||
LastMessageOut = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public static void Close() {
|
||||
|
|
|
@ -63,9 +63,9 @@ namespace SockScape {
|
|||
}
|
||||
|
||||
if(IsProspectConnected(client) && encryptor == null)
|
||||
Prospects[client].LastReceive = DateTime.Now;
|
||||
Prospects[client].LastReceive = DateTime.UtcNow;
|
||||
else if(IsClientConnected(client) && encryptor != null)
|
||||
Clients[client].LastReceive = DateTime.Now;
|
||||
Clients[client].LastReceive = DateTime.UtcNow;
|
||||
|
||||
switch((kIntraSlaveId)packet.Id) {
|
||||
case kIntraSlaveId.InitiationAttempt:
|
||||
|
@ -75,7 +75,7 @@ namespace SockScape {
|
|||
if(packet[0] == Configuration.General["Master Secret"]) {
|
||||
var key = new Key();
|
||||
Prospects[client] = new Client {
|
||||
LastReceive = DateTime.Now,
|
||||
LastReceive = DateTime.UtcNow,
|
||||
Address = endPoint,
|
||||
Key = key
|
||||
};
|
||||
|
@ -90,7 +90,7 @@ namespace SockScape {
|
|||
|
||||
var privateKey = Prospects[client].Key.ParseResponsePacket(packet);
|
||||
if(privateKey != -1) {
|
||||
Prospects[client].LastReceive = DateTime.Now;
|
||||
Prospects[client].LastReceive = DateTime.UtcNow;
|
||||
Prospects[client].Encryptor = new BlockCipher(privateKey);
|
||||
Clients[client] = Prospects[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);
|
||||
|
||||
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)
|
||||
MasterServerList.RemoveServersByOwners(expiredClients);
|
||||
|
||||
|
@ -180,7 +180,7 @@ namespace SockScape {
|
|||
public class Client {
|
||||
public IPEndPoint Address { 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 Key Key { get; set; }
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace SockScape {
|
|||
}
|
||||
|
||||
protected override void OnParse() {
|
||||
if((DateTime.UtcNow - ConnectionOpened).Seconds > 60) {
|
||||
if((DateTime.UtcNow - ConnectionOpened).TotalSeconds > 60) {
|
||||
Disconnect(Frame.kClosingReason.ProtocolError, "Logon request timed out.");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue