mirror of
https://github.com/AlexMacocian/MTSC.git
synced 2026-07-15 14:59:33 +00:00
Implemented a unified message sending method.
Implemented broadcasting handlers to test encrypted communication.
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RootNamespace>MTSC_TestClient</RootNamespace>
|
||||
<StartupObject>MTSC_TestClient.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using MTSC.Client;
|
||||
using MTSC.Client.Handlers;
|
||||
using MTSC.Logging;
|
||||
using System;
|
||||
|
||||
namespace MTSC_TestClient
|
||||
{
|
||||
@@ -6,7 +9,20 @@ namespace MTSC_TestClient
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello World!");
|
||||
Client client = new Client();
|
||||
BroadcastHandler broadcastHandler = new BroadcastHandler(client);
|
||||
client
|
||||
.SetServerAddress("127.0.0.1")
|
||||
.SetPort(555)
|
||||
.AddHandler(new EncryptionHandler(client))
|
||||
.AddHandler(broadcastHandler)
|
||||
.AddLogger(new ConsoleLogger())
|
||||
.Connect();
|
||||
while (true)
|
||||
{
|
||||
string line = Console.ReadLine();
|
||||
broadcastHandler.Broadcast(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -13,7 +13,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using MTSC.Server;
|
||||
using MTSC.Exceptions;
|
||||
using MTSC.Logging;
|
||||
using MTSC.Server;
|
||||
using MTSC.Server.Handlers;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
@@ -11,8 +13,14 @@ namespace MTSC_TestServer
|
||||
{
|
||||
Server server = new Server(555);
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
|
||||
EncryptionHandler encryptionHandler = new EncryptionHandler(rsa);
|
||||
server.AddHandler(encryptionHandler).Run();
|
||||
EncryptionHandler encryptionHandler = new EncryptionHandler(rsa, server);
|
||||
BroadcastHandler broadcastHandler = new BroadcastHandler(server);
|
||||
server
|
||||
.AddHandler(encryptionHandler)
|
||||
.AddLogger(new ConsoleLogger())
|
||||
.AddExceptionHandler(new ExceptionConsoleLogger())
|
||||
.AddHandler(broadcastHandler)
|
||||
.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTSC", "MTSC\MTSC.csproj",
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTSC-TestServer", "MTSC-TestServer\MTSC-TestServer.csproj", "{08A53F8F-BA6B-4C1C-B24B-CFD2626DE6C3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MTSC-TestClient", "MTSC-TestClient\MTSC-TestClient.csproj", "{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -31,6 +33,14 @@ Global
|
||||
{08A53F8F-BA6B-4C1C-B24B-CFD2626DE6C3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08A53F8F-BA6B-4C1C-B24B-CFD2626DE6C3}.Release|x64.ActiveCfg = Release|x64
|
||||
{08A53F8F-BA6B-4C1C-B24B-CFD2626DE6C3}.Release|x64.Build.0 = Release|x64
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6792D3B-E141-48AC-B1E1-BCC0096ECF51}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
+116
-32
@@ -1,4 +1,6 @@
|
||||
using MTSC.Client.Handlers;
|
||||
using MTSC.Exceptions;
|
||||
using MTSC.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
@@ -19,6 +21,9 @@ namespace MTSC.Client
|
||||
TcpClient tcpClient;
|
||||
CancellationTokenSource cancelMonitorToken;
|
||||
List<IHandler> handlers = new List<IHandler>();
|
||||
List<ILogger> loggers = new List<ILogger>();
|
||||
List<IExceptionHandler> exceptionHandlers = new List<IExceptionHandler>();
|
||||
Queue<byte[]> messageQueue = new Queue<byte[]>();
|
||||
#endregion
|
||||
#region Properties
|
||||
public bool Connected
|
||||
@@ -42,6 +47,25 @@ namespace MTSC.Client
|
||||
#endregion
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Add a message to the message queue.
|
||||
/// </summary>
|
||||
/// <param name="message">Message to be sent.</param>
|
||||
public void QueueMessage(byte[] message)
|
||||
{
|
||||
messageQueue.Enqueue(message);
|
||||
}
|
||||
/// <summary>
|
||||
/// Logs the message onto the associated loggers.
|
||||
/// </summary>
|
||||
/// <param name="log">Message to be logged.</param>
|
||||
public void Log(string log)
|
||||
{
|
||||
foreach (ILogger logger in loggers)
|
||||
{
|
||||
logger.Log(log + "\n");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the server address.
|
||||
/// </summary>
|
||||
/// <param name="address">Address of the server.</param>
|
||||
@@ -72,28 +96,63 @@ namespace MTSC.Client
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds an exception handler to the client.
|
||||
/// </summary>
|
||||
/// <param name="handler">Exception handler to be added.</param>
|
||||
/// <returns>This client object.</returns>
|
||||
public Client AddExceptionHandler(IExceptionHandler handler)
|
||||
{
|
||||
exceptionHandlers.Add(handler);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a logger onto the client.
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger to be added.</param>
|
||||
/// <returns>This client object.</returns>
|
||||
public Client AddLogger(ILogger logger)
|
||||
{
|
||||
loggers.Add(logger);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Attemps to connect to the specified server.
|
||||
/// </summary>
|
||||
/// <returns>True if connection was successful.</returns>
|
||||
public bool Connect()
|
||||
{
|
||||
if(tcpClient != null)
|
||||
try
|
||||
{
|
||||
cancelMonitorToken?.Cancel();
|
||||
tcpClient.Dispose();
|
||||
}
|
||||
tcpClient = new TcpClient();
|
||||
tcpClient.Connect(address, port);
|
||||
foreach(IHandler handler in handlers)
|
||||
{
|
||||
if (!handler.InitializeConnection(tcpClient))
|
||||
if (tcpClient != null)
|
||||
{
|
||||
return false;
|
||||
cancelMonitorToken?.Cancel();
|
||||
tcpClient.Dispose();
|
||||
}
|
||||
tcpClient = new TcpClient();
|
||||
tcpClient.Connect(address, port);
|
||||
foreach(ILogger logger in loggers)
|
||||
{
|
||||
logger.Log("Connected to: " + tcpClient.Client.RemoteEndPoint.ToString());
|
||||
}
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if (!handler.InitializeConnection(tcpClient))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cancelMonitorToken = new CancellationTokenSource();
|
||||
Task.Run(MonitorConnection, cancelMonitorToken.Token);
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
foreach(IExceptionHandler exceptionHandler in exceptionHandlers)
|
||||
{
|
||||
exceptionHandler.HandleException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
cancelMonitorToken = new CancellationTokenSource();
|
||||
Task.Run(MonitorConnection, cancelMonitorToken.Token);
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Attempts to connect to the specified server.
|
||||
@@ -117,31 +176,56 @@ namespace MTSC.Client
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if(tcpClient.Available > 0)
|
||||
try
|
||||
{
|
||||
/*
|
||||
* When a message has been received, process it.
|
||||
*/
|
||||
Message message = CommunicationPrimitives.GetMessage(tcpClient);
|
||||
/*
|
||||
* Preprocess message.
|
||||
*/
|
||||
foreach(IHandler handler in handlers)
|
||||
if(messageQueue.Count > 0)
|
||||
{
|
||||
if(handler.PreHandleReceivedMessage(tcpClient, ref message))
|
||||
byte[] messagebytes = messageQueue.Dequeue();
|
||||
Message sendMessage = CommunicationPrimitives.BuildMessage(messagebytes);
|
||||
foreach(IHandler handler in handlers)
|
||||
{
|
||||
break;
|
||||
handler.HandleSendMessage(tcpClient, ref sendMessage);
|
||||
}
|
||||
CommunicationPrimitives.SendMessage(tcpClient, sendMessage);
|
||||
}
|
||||
if (tcpClient.Available > 0)
|
||||
{
|
||||
/*
|
||||
* When a message has been received, process it.
|
||||
*/
|
||||
Message message = CommunicationPrimitives.GetMessage(tcpClient);
|
||||
Log("Received a message of size: " + message.MessageLength);
|
||||
/*
|
||||
* Preprocess message.
|
||||
*/
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if (handler.PreHandleReceivedMessage(tcpClient, ref message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Process the final message structure.
|
||||
*/
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if (handler.HandleReceivedMessage(tcpClient, message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Process the final message structure.
|
||||
*/
|
||||
foreach(IHandler handler in handlers)
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if(handler.HandleReceivedMessage(tcpClient, message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
handler.Tick(tcpClient);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
foreach(IExceptionHandler exceptionHandler in exceptionHandlers)
|
||||
{
|
||||
exceptionHandler.HandleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace MTSC.Client.Handlers
|
||||
{
|
||||
public class BroadcastHandler : IHandler
|
||||
{
|
||||
private List<string> buffer = new List<string>();
|
||||
private Client managedClient;
|
||||
/// <summary>
|
||||
/// Creates a new instance of BroadcastHandler.
|
||||
/// </summary>
|
||||
/// <param name="client">Client managed by the handler.</param>
|
||||
public BroadcastHandler(Client client)
|
||||
{
|
||||
this.managedClient = client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast a message to all other clients connected to the server.
|
||||
/// </summary>
|
||||
/// <param name="message">Message to be broadcasted.</param>
|
||||
public void Broadcast(string message)
|
||||
{
|
||||
managedClient.QueueMessage(ASCIIEncoding.ASCII.GetBytes(message));
|
||||
}
|
||||
|
||||
public void Disconnected(TcpClient client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool HandleReceivedMessage(TcpClient client, Message message)
|
||||
{
|
||||
managedClient.Log("Broadcast: " + ASCIIEncoding.ASCII.GetString(message.MessageBytes));
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HandleSendMessage(TcpClient client, ref Message message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool InitializeConnection(TcpClient client)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PreHandleReceivedMessage(TcpClient client, ref Message message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Tick(TcpClient tcpClient)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,22 @@ namespace MTSC.Client.Handlers
|
||||
NegotiatingSymKey,
|
||||
Encrypted
|
||||
}
|
||||
|
||||
private Client managedClient;
|
||||
#region Fields
|
||||
private ConnectionState connectionState = ConnectionState.Initial;
|
||||
private byte[] aesKey;
|
||||
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Creates an instance of EncryptionHandler.
|
||||
/// </summary>
|
||||
/// <param name="client">Client object that this handler manages.</param>
|
||||
public EncryptionHandler(Client client)
|
||||
{
|
||||
this.managedClient = client;
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Tries to initialize an encrypted connection.
|
||||
/// </summary>
|
||||
@@ -87,7 +99,7 @@ namespace MTSC.Client.Handlers
|
||||
if (ascii.Contains(CommunicationPrimitives.SendPublicKey))
|
||||
{
|
||||
byte[] publicKeyBytes = new byte[message.MessageLength - CommunicationPrimitives.SendPublicKey.Length - 1];
|
||||
Array.Copy(message.MessageBytes, message.MessageLength + 1, publicKeyBytes, 0, publicKeyBytes.Length);
|
||||
Array.Copy(message.MessageBytes, CommunicationPrimitives.SendPublicKey.Length + 1, publicKeyBytes, 0, publicKeyBytes.Length);
|
||||
string publicKey = ASCIIEncoding.ASCII.GetString(publicKeyBytes);
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
|
||||
RSAParameters parameters = new RSAParameters();
|
||||
@@ -118,15 +130,14 @@ namespace MTSC.Client.Handlers
|
||||
byte[] messageBytes = new byte[encryptedSymKey.Length + messageHeader.Length];
|
||||
Array.Copy(messageHeader, 0, messageBytes, 0, messageHeader.Length);
|
||||
Array.Copy(encryptedSymKey, 0, messageBytes, messageHeader.Length, encryptedSymKey.Length);
|
||||
Message sendMessage = CommunicationPrimitives.BuildMessage(messageBytes);
|
||||
CommunicationPrimitives.SendMessage(client, sendMessage);
|
||||
managedClient.QueueMessage(messageBytes);
|
||||
connectionState = ConnectionState.NegotiatingSymKey;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(connectionState == ConnectionState.NegotiatingSymKey)
|
||||
{
|
||||
string ascii = ASCIIEncoding.ASCII.GetString(message.MessageBytes);
|
||||
string ascii = ASCIIEncoding.ASCII.GetString(DecryptBytes(message.MessageBytes));
|
||||
if(ascii == CommunicationPrimitives.AcceptEncryptionKey)
|
||||
{
|
||||
connectionState = ConnectionState.Encrypted;
|
||||
@@ -144,18 +155,18 @@ namespace MTSC.Client.Handlers
|
||||
/// Called on every tick by the client object.
|
||||
/// Performs regular operations.
|
||||
/// </summary>
|
||||
/// <param name="client">Client connection.</param>
|
||||
public void Tick(TcpClient client)
|
||||
/// <param name="tcpClient">Client connection.</param>
|
||||
public void Tick(TcpClient tcpClient)
|
||||
{
|
||||
if(connectionState == ConnectionState.Initial)
|
||||
{
|
||||
Message message = CommunicationPrimitives.BuildMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.RequestPublicKey));
|
||||
CommunicationPrimitives.SendMessage(client, message);
|
||||
|
||||
managedClient.QueueMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.RequestPublicKey));
|
||||
this.connectionState = ConnectionState.RequestingPublicKey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region Private Methods
|
||||
private string GetUniqueKey(int size)
|
||||
{
|
||||
return Convert.ToBase64String(GetUniqueByteKey(size));
|
||||
@@ -260,5 +271,6 @@ namespace MTSC.Client.Handlers
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ namespace MTSC.Client.Handlers
|
||||
/// Called every cycle. This method should perform regular actions on the connection.
|
||||
/// </summary>
|
||||
/// <param name="client">Client object.</param>
|
||||
void Tick(TcpClient client);
|
||||
/// <param name="tcpClient">TcpClient connection.</param>
|
||||
void Tick(TcpClient tcpClient);
|
||||
/// <summary>
|
||||
/// Called when the client is disconnected.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MTSC.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs the received exceptions to the console.
|
||||
/// </summary>
|
||||
public class ExceptionConsoleLogger : IExceptionHandler
|
||||
{
|
||||
public bool HandleException(Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message + "\nStackTrace:\n" + e.StackTrace);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MTSC.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Throws all handled exceptions.
|
||||
/// </summary>
|
||||
public class ExceptionThrower : IExceptionHandler
|
||||
{
|
||||
public bool HandleException(Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MTSC.Server.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Broadcast handler.
|
||||
/// </summary>
|
||||
public class BroadcastHandler : IHandler
|
||||
{
|
||||
private Server managedServer;
|
||||
|
||||
public BroadcastHandler(Server server)
|
||||
{
|
||||
this.managedServer = server;
|
||||
}
|
||||
|
||||
public void ClientRemoved(ClientStruct client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool HandleClient(ClientStruct client)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HandleReceivedMessage(ClientStruct client, Message message)
|
||||
{
|
||||
managedServer.Log("Broadcast: " + ASCIIEncoding.ASCII.GetString(message.MessageBytes));
|
||||
managedServer.Log("From: " + client.TcpClient.Client.RemoteEndPoint.ToString());
|
||||
foreach(ClientStruct clientStruct in managedServer.Clients)
|
||||
{
|
||||
managedServer.QueueMessage(clientStruct, message.MessageBytes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HandleSendMessage(ClientStruct client, ref Message message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PreHandleReceivedMessage(ClientStruct client, ref Message message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ namespace MTSC.Server.Handlers
|
||||
private Dictionary<ClientStruct, AdditionalData> additionalData;
|
||||
private RSACryptoServiceProvider rsa;
|
||||
private string privateKey, publicKey;
|
||||
private Server managedServer;
|
||||
#endregion
|
||||
#region Properties
|
||||
#endregion
|
||||
@@ -35,9 +36,12 @@ namespace MTSC.Server.Handlers
|
||||
/// Creates an instance of EncryptionHandler.
|
||||
/// </summary>
|
||||
/// <param name="rsa">Symmetrical algorithm to be used for end-to-end encryption.</param>
|
||||
public EncryptionHandler(RSACryptoServiceProvider rsa)
|
||||
/// <param name="server">Server object managed by the handler.</param>
|
||||
public EncryptionHandler(RSACryptoServiceProvider rsa, Server server)
|
||||
{
|
||||
managedServer = server;
|
||||
additionalData = new Dictionary<ClientStruct, AdditionalData>();
|
||||
this.rsa = rsa;
|
||||
privateKey = HelperFunctions.ToXmlString(rsa, true);
|
||||
publicKey = HelperFunctions.ToXmlString(rsa, false);
|
||||
}
|
||||
@@ -67,15 +71,14 @@ namespace MTSC.Server.Handlers
|
||||
/// <param name="client">Client connection.</param>
|
||||
/// <param name="message">Received message.</param>
|
||||
/// <returns>True if no other handler should handle current message.</returns>
|
||||
public bool HandleMessage(ClientStruct client, Message message)
|
||||
public bool HandleReceivedMessage(ClientStruct client, Message message)
|
||||
{
|
||||
if (additionalData[client].ClientState == ClientState.Initial || additionalData[client].ClientState == ClientState.Negotiating)
|
||||
{
|
||||
string asciiMessage = ASCIIEncoding.ASCII.GetString(message.MessageBytes);
|
||||
if (asciiMessage == CommunicationPrimitives.RequestPublicKey)
|
||||
{
|
||||
Message sendMessage = CommunicationPrimitives.BuildMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendPublicKey + ":" + publicKey));
|
||||
CommunicationPrimitives.SendMessage(client.TcpClient, sendMessage);
|
||||
managedServer.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.SendPublicKey + ":" + publicKey));
|
||||
additionalData[client].ClientState = ClientState.Negotiating;
|
||||
return true;
|
||||
}
|
||||
@@ -85,8 +88,7 @@ namespace MTSC.Server.Handlers
|
||||
Array.Copy(message.MessageBytes, CommunicationPrimitives.SendEncryptionKey.Length + 1, encryptedKey, 0, encryptedKey.Length);
|
||||
byte[] decryptedKey = rsa.Decrypt(encryptedKey, false);
|
||||
additionalData[client].Key = decryptedKey;
|
||||
Message sendMessage = CommunicationPrimitives.BuildMessage(ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.AcceptEncryptionKey));
|
||||
CommunicationPrimitives.SendMessage(client.TcpClient, sendMessage);
|
||||
managedServer.QueueMessage(client, ASCIIEncoding.ASCII.GetBytes(CommunicationPrimitives.AcceptEncryptionKey));
|
||||
additionalData[client].ClientState = ClientState.Encrypted;
|
||||
return true;
|
||||
}
|
||||
@@ -106,7 +108,7 @@ namespace MTSC.Server.Handlers
|
||||
/// <param name="client">Client connection.</param>
|
||||
/// <param name="message">Message to be processed.</param>
|
||||
/// <returns>True if no other handlers should perform operations on current message.</returns>
|
||||
public bool PreHandleMessage(ClientStruct client, ref Message message)
|
||||
public bool PreHandleReceivedMessage(ClientStruct client, ref Message message)
|
||||
{
|
||||
if(additionalData[client].ClientState == ClientState.Encrypted)
|
||||
{
|
||||
@@ -132,6 +134,20 @@ namespace MTSC.Server.Handlers
|
||||
public void Tick()
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Encrypts the message before sending.
|
||||
/// </summary>
|
||||
/// <param name="client">Client object.</param>
|
||||
/// <param name="message">Message to be processed.</param>
|
||||
/// <returns>True if no other handler should process this message.</returns>
|
||||
public bool HandleSendMessage(ClientStruct client, ref Message message)
|
||||
{
|
||||
if(additionalData[client].ClientState == ClientState.Encrypted)
|
||||
{
|
||||
message = CommunicationPrimitives.BuildMessage(EncryptBytes(additionalData[client].Key, message.MessageBytes));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
|
||||
@@ -17,19 +17,26 @@ namespace MTSC.Server.Handlers
|
||||
/// <returns>True if the handler processed the client.</returns>
|
||||
bool HandleClient(ClientStruct client);
|
||||
/// <summary>
|
||||
/// Handles a message before sending.
|
||||
/// </summary>
|
||||
/// <param name="client">Client object.</param>
|
||||
/// <param name="message">Message to be processed.</param>
|
||||
/// <returns>True if no other handler should handle this message.</returns>
|
||||
bool HandleSendMessage(ClientStruct client, ref Message message);
|
||||
/// <summary>
|
||||
/// Called before the message handling.
|
||||
/// Perform here any processing of the message.
|
||||
/// </summary>
|
||||
/// <param name="client">Client structure.</param>
|
||||
/// <param name="message">Message to be preprocessed.</param>
|
||||
/// <returns>True if the message has been preprocessed and no other handler should handle it anymore.</returns>
|
||||
bool PreHandleMessage(ClientStruct client, ref Message message);
|
||||
bool PreHandleReceivedMessage(ClientStruct client, ref Message message);
|
||||
/// <summary>
|
||||
/// Handles the received message.
|
||||
/// </summary>
|
||||
/// <param name="message">Message to be handled.</param>
|
||||
/// <returns>True if the message has been handled, false if the message has not been handled.</returns>
|
||||
bool HandleMessage(ClientStruct client, Message message);
|
||||
bool HandleReceivedMessage(ClientStruct client, Message message);
|
||||
/// <summary>
|
||||
/// Handles the removal of a client from the server.
|
||||
/// </summary>
|
||||
|
||||
+48
-6
@@ -24,13 +24,21 @@ namespace MTSC.Server
|
||||
List<IHandler> handlers = new List<IHandler>();
|
||||
List<ILogger> loggers = new List<ILogger>();
|
||||
List<IExceptionHandler> exceptionHandlers = new List<IExceptionHandler>();
|
||||
Queue<Tuple<ClientStruct, byte[]>> messageQueue = new Queue<Tuple<ClientStruct, byte[]>>();
|
||||
#endregion
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Server port.
|
||||
/// </summary>
|
||||
public int Port { get => port; set => port = value; }
|
||||
/// <summary>
|
||||
/// Returns the state of the server.
|
||||
/// </summary>
|
||||
public bool Running { get => running; }
|
||||
/// <summary>
|
||||
/// List of clients currently connected to the server.
|
||||
/// </summary>
|
||||
public List<ClientStruct> Clients { get => clients; set => clients = value; }
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
@@ -91,6 +99,26 @@ namespace MTSC.Server
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Queues a message to be sent.
|
||||
/// </summary>
|
||||
/// <param name="target">Target client.</param>
|
||||
/// <param name="message">Message to be sent.</param>
|
||||
public void QueueMessage(ClientStruct target, byte[] message)
|
||||
{
|
||||
messageQueue.Enqueue(new Tuple<ClientStruct, byte[]>(target, message));
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a message to be logged by the associated loggers.
|
||||
/// </summary>
|
||||
/// <param name="">Message to be logged</param>
|
||||
public void Log(string log)
|
||||
{
|
||||
foreach (ILogger logger in loggers)
|
||||
{
|
||||
logger.Log(log + "\n");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Blocking method. Runs the server on the current thread.
|
||||
/// </summary>
|
||||
public void Run()
|
||||
@@ -98,8 +126,24 @@ namespace MTSC.Server
|
||||
listener?.Stop();
|
||||
listener = new TcpListener(IPAddress.Any, port);
|
||||
listener.Start();
|
||||
running = true;
|
||||
Log("Server started on: " + listener.LocalEndpoint.ToString());
|
||||
while (running)
|
||||
{
|
||||
/*
|
||||
* Check if there are messages queued to be sent.
|
||||
*/
|
||||
if(messageQueue.Count > 0)
|
||||
{
|
||||
Tuple<ClientStruct, byte[]> queuedOrder = messageQueue.Dequeue();
|
||||
Message sendMessage = CommunicationPrimitives.BuildMessage(queuedOrder.Item2);
|
||||
foreach(IHandler handler in handlers)
|
||||
{
|
||||
handler.HandleSendMessage(queuedOrder.Item1, ref sendMessage);
|
||||
}
|
||||
CommunicationPrimitives.SendMessage(queuedOrder.Item1.TcpClient, sendMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the server has any pending connections.
|
||||
* If it has a new connection, process it.
|
||||
@@ -116,6 +160,7 @@ namespace MTSC.Server
|
||||
}
|
||||
}
|
||||
clients.Add(clientStruct);
|
||||
Log("Accepted new connection: " + tcpClient.Client.RemoteEndPoint.ToString());
|
||||
}
|
||||
/*
|
||||
* Process in parallel all clients.
|
||||
@@ -127,21 +172,18 @@ namespace MTSC.Server
|
||||
if (client.TcpClient.Available > 0)
|
||||
{
|
||||
Message message = CommunicationPrimitives.GetMessage(client.TcpClient);
|
||||
foreach (ILogger logger in loggers)
|
||||
{
|
||||
logger.Log("Received message from " + client.TcpClient.Client.RemoteEndPoint.ToString() +
|
||||
Log("Received message from " + client.TcpClient.Client.RemoteEndPoint.ToString() +
|
||||
" Message length: " + message.MessageLength);
|
||||
}
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if (handler.PreHandleMessage(client, ref message))
|
||||
if (handler.PreHandleReceivedMessage(client, ref message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (IHandler handler in handlers)
|
||||
{
|
||||
if (handler.HandleMessage(client, message))
|
||||
if (handler.HandleReceivedMessage(client, message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user