sockscape/server/Socks/MasterIntraClient.cs

121 lines
4.3 KiB
C#
Raw Normal View History

2017-06-16 21:00:01 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
2017-06-16 21:00:01 +00:00
using System.Text;
2017-08-29 20:14:44 +00:00
using System.Threading;
2017-06-16 21:00:01 +00:00
using System.Threading.Tasks;
2017-08-30 21:02:51 +00:00
using Glove;
using SockScape.Encryption;
2017-06-16 21:00:01 +00:00
2017-08-29 20:14:44 +00:00
namespace SockScape {
static class MasterIntraClient {
2017-08-30 21:02:51 +00:00
private static Key Key;
2017-09-08 21:06:55 +00:00
private static BlockCipher Encryptor;
2017-08-30 21:02:51 +00:00
private static UdpClient Sock;
2017-08-29 20:14:44 +00:00
private static Thread ListeningThread;
private static bool IsOpen;
2017-09-06 20:59:38 +00:00
private static DateTime LastMessageOut = new DateTime(0);
private static TimeSpan DeltaLastOut
=> DateTime.UtcNow - LastMessageOut;
private static DateTime LastMessageIn = new DateTime(0);
private static TimeSpan DeltaLastIn
=> DateTime.UtcNow - LastMessageIn;
2017-06-16 21:00:01 +00:00
public static void Initialize() {
2017-08-30 21:02:51 +00:00
if(IsOpen || ListeningThread != null)
return;
ushort port = (ushort)Configuration.General["Master Port"];
2017-08-29 20:14:44 +00:00
Sock = new UdpClient(Configuration.General["Master Addr"], port);
2017-09-08 21:06:55 +00:00
// TODO figure out what this has to do with ICMP (in server too)
uint IOC_IN = 0x80000000,
IOC_VENDOR = 0x18000000,
2017-09-15 20:55:02 +00:00
SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 0xC;
2017-09-08 21:06:55 +00:00
Sock.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] {0}, null);
2017-08-30 21:02:51 +00:00
Key = new Key();
Encryptor = null;
2017-08-30 21:02:51 +00:00
IsOpen = true;
2017-08-30 21:02:51 +00:00
ListeningThread = new Thread(Listener);
ListeningThread.Start();
}
2017-08-29 20:14:44 +00:00
public static void Listener() {
2017-08-30 21:02:51 +00:00
while(IsOpen) {
2017-09-08 21:06:55 +00:00
var endPoint = new IPEndPoint(IPAddress.Any, 0);
2017-08-30 21:02:51 +00:00
while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint);
LastMessageIn = DateTime.UtcNow;
2017-09-08 21:06:55 +00:00
bool readRaw = Encryptor == null
|| data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
Packet packet =
2017-09-08 21:06:55 +00:00
readRaw ? Packet.FromBytes(data)
: Packet.FromBytes(Encryptor.Decrypt(data));
switch((kIntraMasterId)packet.Id) {
case kIntraMasterId.KeyExchange:
var responsePacket = Key.ParseRequestPacket(packet);
2017-09-08 21:06:55 +00:00
Encryptor = new BlockCipher(Key.PrivateKey);
if(responsePacket != null)
Send(responsePacket);
else
LastMessageIn = new DateTime(0);
break;
2017-09-05 21:02:14 +00:00
case kIntraMasterId.PositiveAck:
2017-09-08 21:06:55 +00:00
Console.WriteLine($"Packet type {packet[0].Raw[0]} accepted by master");
2017-09-05 21:02:14 +00:00
break;
case kIntraMasterId.NegativeAck:
2017-09-08 21:06:55 +00:00
Console.WriteLine($"Packet type {packet[0].Raw[0]} declined by master for reason {packet[1].Str}");
2017-09-05 21:02:14 +00:00
break;
case kIntraMasterId.EncryptionError:
Key = new Key();
Encryptor = null;
LastMessageIn = new DateTime(0);
break;
}
2017-08-30 21:02:51 +00:00
}
2017-09-08 21:06:55 +00:00
if(Encryptor != null) {
2017-09-07 04:26:58 +00:00
if(DeltaLastOut.TotalSeconds > 2)
2017-09-08 21:06:55 +00:00
SendEncrypted(ServerContext.StatusUpdatePacket);
2017-09-07 04:26:58 +00:00
} else
if(DeltaLastOut.TotalSeconds > 10)
2017-09-08 21:06:55 +00:00
Send(new Packet(kIntraSlaveId.InitiationAttempt, Configuration.General["Master Secret"].Str));
2017-09-06 20:59:38 +00:00
2017-08-30 21:02:51 +00:00
Thread.Sleep(1);
}
2017-08-29 20:14:44 +00:00
}
public static void Send(Packet packet) {
Send(packet.GetBytes());
}
2017-09-08 21:06:55 +00:00
public static void SendEncrypted(Packet packet) {
Send(Encryptor.Encrypt(packet.GetBytes()));
}
public static void Send(byte[] bytes) {
Sock.Send(bytes, bytes.Length);
LastMessageOut = DateTime.UtcNow;
}
2017-08-29 20:14:44 +00:00
public static void Close() {
IsOpen = false;
ListeningThread.Join();
ListeningThread = null;
}
2017-06-16 21:00:01 +00:00
}
}