once as a kid i cried over a mario flash animation

my mom looked very disappointed
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-09-14 14:14:07 -05:00
parent 07e50a3301
commit 4d281dac5a
7 changed files with 105 additions and 37 deletions

View file

@ -287,24 +287,18 @@ Communication between the master server and clients will be done over a WebSocke
</tr> </tr>
<tr> <tr>
<td class="center">2</td> <td class="center">2</td>
<td>Session Id</td>
<td>Packed Unsigned Long</td>
<td>R<sub>1</sub></td>
</tr>
<tr>
<td class="center">3</td>
<td>Secret</td> <td>Secret</td>
<td>Bytes (16)</td> <td>Bytes (16)</td>
<td>R<sub>1</sub></td> <td>R<sub>1</sub></td>
</tr> </tr>
<tr> <tr>
<td class="center">4</td> <td class="center">3</td>
<td>Server Address</td> <td>Server Address</td>
<td>IPv4 String</td> <td>IPv4 String</td>
<td>R<sub>1</sub></td> <td>R<sub>1</sub></td>
</tr> </tr>
<tr> <tr>
<td class="center">5</td> <td class="center">4</td>
<td>Server Port</td> <td>Server Port</td>
<td>Packed Unsigned Short</td> <td>Packed Unsigned Short</td>
<td>R<sub>1</sub></td> <td>R<sub>1</sub></td>

View file

@ -26,6 +26,16 @@ namespace SockScape {
} }
}, },
new SectionRules {
Name = "Mail",
Required = true,
RequiredFields = new[] {
"Host",
"UseTLS",
"Auth"
}
},
new SectionRules { new SectionRules {
Name = "Database", Name = "Database",
Required = true, Required = true,

View file

@ -8,7 +8,6 @@ using System.Security.Cryptography;
namespace Glove { namespace Glove {
public static class RNG { public static class RNG {
// TODO add cryptographically secure rng
private static readonly Random RandCtx = new Random(); private static readonly Random RandCtx = new Random();
private static readonly RNGCryptoServiceProvider CsRandCtx private static readonly RNGCryptoServiceProvider CsRandCtx
= new RNGCryptoServiceProvider(); = new RNGCryptoServiceProvider();

View file

@ -21,6 +21,12 @@ namespace SockScape {
} }
} }
public static Server Get(ushort id) {
lock(_Servers) {
return _Servers[id];
}
}
public static void Write(Server server) { public static void Write(Server server) {
lock(_Servers) { lock(_Servers) {
if(HasId(server.Id) && !_Servers[server.Id].Address.Equals(server.Address)) if(HasId(server.Id) && !_Servers[server.Id].Address.Equals(server.Address))

View file

@ -13,8 +13,8 @@ using SockScape.Encryption;
namespace SockScape { namespace SockScape {
class MasterConnection : Connection { class MasterConnection : Connection {
private Regex UsernameRegex = new Regex("[A-Z0-9_]", RegexOptions.IgnoreCase); private readonly Regex UsernameRegex = new Regex("[A-Z0-9_]", RegexOptions.IgnoreCase);
private Regex EmailRegex = new Regex("\\B[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\B", RegexOptions.IgnoreCase); private readonly Regex EmailRegex = new Regex(@"\B[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\B", RegexOptions.IgnoreCase);
private Key Key; private Key Key;
public StreamCipher Encryptor { get; private set; } public StreamCipher Encryptor { get; private set; }
@ -55,9 +55,10 @@ namespace SockScape {
Encryptor = new StreamCipher(Key.PrivateKey); Encryptor = new StreamCipher(Key.PrivateKey);
break; break;
case kInterMasterId.LoginAttempt: case kInterMasterId.LoginAttempt:
if(packet.RegionCount != 3 || !packet.CheckRegions(2, 2)) if(packet.RegionCount != 3 || !packet.CheckRegionsMaxLength(0, 16, 255) || !packet.CheckRegionLengths(2, 2))
break; break;
Session session;
using(var db = new ScapeDb()) { using(var db = new ScapeDb()) {
User user; User user;
if((user = db.Users.FirstOrDefault(x => x.Username == packet[0])) == null) { if((user = db.Users.FirstOrDefault(x => x.Username == packet[0])) == null) {
@ -75,8 +76,8 @@ namespace SockScape {
break; break;
} }
ushort server = packet[2].Raw.UnpackUInt16(); ushort serverId = packet[2].Raw.UnpackUInt16();
if(!MasterServerList.HasId(server)) { if(!MasterServerList.HasId(serverId)) {
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "The world you have specified is offline.")); SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(false), "The world you have specified is offline."));
break; break;
} }
@ -86,32 +87,65 @@ namespace SockScape {
db.SaveChanges(); db.SaveChanges();
} }
db.Sessions.Add(new Session { db.Sessions.Add(session = new Session {
Id = user.Id, Id = user.Id,
Secret = RNG.NextBytes(16), Secret = RNG.NextBytes(16),
ServerId = server, ServerId = serverId,
LastPing = DateTime.UtcNow LastPing = DateTime.UtcNow
}); });
db.SaveChanges(); db.SaveChanges();
} }
var server = MasterServerList.Get((ushort)session.ServerId);
SendEncrypted(new Packet(kInterMasterId.LoginAttempt, Convert.ToByte(true), session.Secret, server.Address.ToString(), server.Port.Pack()));
break; break;
case kInterMasterId.RegistrationAttempt: case kInterMasterId.RegistrationAttempt:
if(packet.RegionCount != 3) if(packet.RegionCount != 3 || !packet.CheckAllMaxLength(0xFF))
break; break;
using(var db = new ScapeDb()) { if(!packet[0].Raw.IsAsciiString()) {
if(!packet[0].Raw.IsAsciiString()) { SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "Your username cannot contain unicode characters."));
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "Your username cannot contain unicode characters.")); break;
break;
}
if(packet[0].Raw.Length > 16 || !UsernameRegex.IsMatch(packet[0].Str)) {
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "The username is max 16 characters and can only be letters, numbers, and underscores."));
break;
}
} }
string username = packet[0].Str.Trim(),
password = packet[1].Str.Trim(),
email = packet[2].Str.Trim();
if(username.Length > 16 || !UsernameRegex.IsMatch(username)) {
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "The username is max 16 characters and can only be letters, numbers, and underscores."));
break;
}
if(!EmailRegex.IsMatch(email)) {
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "The email address is malformed."));
break;
}
using(var db = new ScapeDb()) {
if(db.Users.FirstOrDefault(x => x.Username == username) != null) {
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "This username is already in use."));
break;
}
if(db.Users.FirstOrDefault(x => x.Email == email) != null) {
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(false), "This email address is already in use."));
break;
}
// TODO email activation
db.Users.Add(new User {
Username = username,
Password = password.HashPassword(),
Email = email,
Joined = DateTime.UtcNow
});
db.SaveChanges();
}
SendEncrypted(new Packet(kInterMasterId.RegistrationAttempt, Convert.ToByte(true), "Registration was successful."));
break; break;
case kInterMasterId.ServerListing: case kInterMasterId.ServerListing:
SendEncrypted(MasterServerList.ReportPacket); SendEncrypted(MasterServerList.ReportPacket);

View file

@ -102,7 +102,7 @@ namespace SockScape {
if(!IsClientConnected(client) || packet.RegionCount < 1) if(!IsClientConnected(client) || packet.RegionCount < 1)
break; break;
if(!packet.CheckRegions(0, 1)) { if(!packet.CheckRegionLengths(0, 1)) {
NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed."); NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed.");
break; break;
} }
@ -114,7 +114,7 @@ namespace SockScape {
} }
for(byte i = 0; i < serverCount; ++i) { for(byte i = 0; i < serverCount; ++i) {
if(!packet.CheckRegions(1 + 3 * i, 2, 2, 2)) if(!packet.CheckRegionLengths(1 + 3 * i, 2, 2, 2))
continue; continue;
MasterServerList.Write(new Server { MasterServerList.Write(new Server {
@ -132,7 +132,7 @@ namespace SockScape {
} }
Prospects = Prospects.Where(x => x.Value.ReceiveDelta.TotalSeconds < 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.TotalSeconds > 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)

View file

@ -50,7 +50,7 @@ namespace SockScape {
long bodyPtr = headerPtr; long bodyPtr = headerPtr;
foreach(var regionLength in regionLengths) { foreach(var regionLength in regionLengths) {
// FLAG this could fail if one region exceeds 2^31-1 in size, check later // FLAG TODO this could fail if one region exceeds 2^31-1 in size, check later
packet.Regions.Add(raw.Subset((int)bodyPtr, (int)regionLength)); packet.Regions.Add(raw.Subset((int)bodyPtr, (int)regionLength));
bodyPtr += regionLength; bodyPtr += regionLength;
} }
@ -103,7 +103,7 @@ namespace SockScape {
return this; return this;
} }
public bool CheckRegions(int startIndex, params int[] lengths) { public bool CheckRegionLengths(int startIndex, params int[] lengths) {
if(startIndex + lengths.Length > RegionCount) if(startIndex + lengths.Length > RegionCount)
return false; return false;
@ -115,6 +115,30 @@ namespace SockScape {
return true; return true;
} }
public bool CheckRegionsMaxLength(int startIndex, params int[] lengths) {
if(startIndex + lengths.Length > RegionCount)
return false;
for(int i = 0; i < lengths.Length; ++i) {
if(this[startIndex + i].Raw.Length > lengths[i])
return false;
}
return true;
}
public bool CheckAllMaxLength(int length, int startIndex = 0) {
if(startIndex > RegionCount)
return false;
for(int i = startIndex; i < RegionCount; ++i) {
if(this[i].Raw.Length > length)
return false;
}
return true;
}
public byte[] GetBytes() { public byte[] GetBytes() {
var header = new List<byte>(); var header = new List<byte>();
header.AddRange(MagicNumber); header.AddRange(MagicNumber);
@ -162,8 +186,9 @@ namespace SockScape {
} }
} }
// FLAG TODO determine if you still need this thing, probably not
public class PacketBuffer { public class PacketBuffer {
private short MaxSize; private readonly short MaxSize;
private Dictionary<uint, byte[]> Buffer private Dictionary<uint, byte[]> Buffer
= new Dictionary<uint, byte[]>(); = new Dictionary<uint, byte[]>();
@ -174,9 +199,9 @@ namespace SockScape {
public void Add(uint id, byte[] packet) { public void Add(uint id, byte[] packet) {
Buffer[id] = packet; Buffer[id] = packet;
if(Buffer.Count > 10) if(Buffer.Count > MaxSize)
Buffer = Buffer =
Buffer.Where(x => x.Key >= id - 10) Buffer.Where(x => x.Key >= id - MaxSize)
.ToDictionary(x => x.Key, x => x.Value); .ToDictionary(x => x.Key, x => x.Value);
} }