Commands + Server first development release ready (USER: TEST, PASS: 1234) (Serveradress: 185.113.120.99, PORT: 3767)

This commit is contained in:
Tim G. | SnapixLP 2025-06-05 22:58:56 +02:00
parent 838b31cb1f
commit 38a9a72740
15 changed files with 148 additions and 138 deletions

View File

@ -24,6 +24,7 @@ public abstract class TcpServer
optionsList = new List<string>(); optionsList = new List<string>();
this.dx86 = new DX86(ms, ServerType.TCP); this.dx86 = new DX86(ms, ServerType.TCP);
optionsList.Add("cancel"); optionsList.Add("cancel");
LoggedInClients = new Dictionary<TcpClient, string>();
ms.Log("[DX86] Server Setup Complete."); ms.Log("[DX86] Server Setup Complete.");
_ = RunServer(); _ = RunServer();
} }

View File

@ -2,5 +2,44 @@
public class Employee public class Employee
{ {
private string _id;
private string _code;
private string _surname;
private string _forename;
private string _email;
private string _phone;
private string _street;
private string _city;
private string _postcode;
private string _country;
private string _department;
private string _position;
private EmployeeState _employeeState;
public Employee(string code)
{
_code = code;
}
public string Id
{
get => _id;
}
public string Code
{
get => _code;
}
public string Surname
{
get => _surname;
set => _surname = value;
}
public string Forename
{
get => _forename;
set => _forename = value;
}
} }

View File

@ -12,6 +12,12 @@ public class Server
private StreamReader reader; private StreamReader reader;
private StreamWriter writer; private StreamWriter writer;
private Action<string> onMessageReceived; private Action<string> onMessageReceived;
public Action<string> OnMessageReceived
{
get => onMessageReceived;
set => onMessageReceived = value ?? throw new ArgumentNullException(nameof(value), "onMessageReceived cannot be null.");
}
private ConcurrentDictionary<string, TaskCompletionSource<string>> pendingRequests = new(); private ConcurrentDictionary<string, TaskCompletionSource<string>> pendingRequests = new();
@ -41,11 +47,20 @@ public class Server
string message = await reader.ReadLineAsync(); string message = await reader.ReadLineAsync();
if (message != null) if (message != null)
{ {
// Parse the JSON response if (message.StartsWith("{") && message.EndsWith("}"))
var response = JsonSerializer.Deserialize<JsonResponse>(message);
if (response != null && pendingRequests.TryRemove(response.Id, out var tcs))
{ {
tcs.SetResult(response.Response); // Complete the task with the response Console.WriteLine("Received: " + message);
// Parse the JSON response
var response = JsonSerializer.Deserialize<JsonResponse>(message);
Console.WriteLine("Parsed Response: " + (response != null ? $"Id={response.Id}, Response={response.Response}" : "null"));
if (response != null && pendingRequests.TryRemove(response.Id, out var tcs))
{
tcs.SetResult(response.Response); // Complete the task with the response
}
else
{
onMessageReceived?.Invoke(message); // Handle other messages
}
} }
else else
{ {
@ -90,13 +105,13 @@ public class Server
} }
} }
private class JsonRequest public class JsonRequest
{ {
public string cmd { get; set; } public string cmd { get; set; }
public string cid { get; set; } public string cid { get; set; }
} }
private class JsonResponse public class JsonResponse
{ {
public string Id { get; set; } public string Id { get; set; }
public string Response { get; set; } public string Response { get; set; }
@ -147,6 +162,9 @@ public class Server
} }
return Task.FromException<string>(new Exception("Failed to login.")); return Task.FromException<string>(new Exception("Failed to login."));
} }
public Task<string> HelpCommand() => ExecuteCommandAsync("help");
public Task<string> Logout() public Task<string> Logout()
{ {
@ -159,6 +177,25 @@ public class Server
return Task.FromException<string>(new Exception("Failed to logout.")); return Task.FromException<string>(new Exception("Failed to logout."));
} }
public Task<Employee> GetLoggedInEmployee()
{
var commandResult = ExecuteCommandAsync("getSelfUser").Result;
try
{
var employee = JsonSerializer.Deserialize<Employee>(commandResult);
if (employee != null)
{
return Task.FromResult(employee);
}
return Task.FromException<Employee>(new Exception("Failed to deserialize the employee data."));
}
catch (JsonException)
{
Console.WriteLine("Failed to deserialize the command result.");
}
return Task.FromException<Employee>(new Exception("Failed to get logged in employee."));
}
public Task<string> clockIn(Employee employee) public Task<string> clockIn(Employee employee)
{ {
var commandResult = ExecuteCommandAsync("clock in").Result; var commandResult = ExecuteCommandAsync("clock in").Result;

View File

@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csp
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DX86", "DX86\DX86.csproj", "{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DX86", "DX86\DX86.csproj", "{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -36,5 +38,9 @@ Global
{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Debug|Any CPU.Build.0 = Debug|Any CPU {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.ActiveCfg = Release|Any CPU {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.Build.0 = Release|Any CPU {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.Build.0 = Release|Any CPU
{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -43,6 +43,7 @@ public class BackendServer : DX86.TcpServer
JsonMessage? jsonMessage; JsonMessage? jsonMessage;
if (message.StartsWith("{") && message.EndsWith("}")) if (message.StartsWith("{") && message.EndsWith("}"))
{ {
this.SendMessageAsync(client, "Command received\n");
try try
{ {
jsonMessage = JsonSerializer.Deserialize<JsonMessage>(message); jsonMessage = JsonSerializer.Deserialize<JsonMessage>(message);

View File

@ -1,6 +0,0 @@
namespace Server.Commands;
public class ClockCommand
{
}

View File

@ -1,6 +1,7 @@
using System.Net.Sockets; using System.Net.Sockets;
using System.Text.Json;
using DX86; using DX86;
using Server.Commands; using Library;
namespace Server; namespace Server;
@ -26,21 +27,24 @@ public class CommandLibrary
#region Client Commands #region Client Commands
[Command("login")] [Command("login")]
public static string LoginCommand(string[] args, TcpClient? client, TcpServer? socket) public static string LoginCommand(string[] args, TcpClient? client, TcpServer? socket)
{ {
if (args.Length < 2) if (args.Length < 2)
throw new CommandException("Missing arguments: usage is login <username> <password>"); throw new CommandException("Missing arguments: usage is login <username> <password>");
string username = args[0]; string username = args[0];
string password = args[1]; string password = args[1];
if (socket?.LoggedInClients.ContainsKey(client) == true)
throw new CommandException("User already logged in.");
if (username == "test" && password == "1234") if (username == "TEST" && password == "1234")
{ {
if (client != null) if (client != null)
{ {
socket?.LoggedInClients.Add(client, username); socket?.LoggedInClients.Add(client, username);
return "Login successful"; return "success";
} }
throw new CommandException("No client connection detected."); throw new CommandException("No client connection detected.");
@ -55,10 +59,26 @@ public class CommandLibrary
if (client != null && socket?.LoggedInClients.ContainsKey(client) == true) if (client != null && socket?.LoggedInClients.ContainsKey(client) == true)
{ {
socket.LoggedInClients.Remove(client); socket.LoggedInClients.Remove(client);
return "Logout successful"; return "success";
} }
throw new CommandException("No client provided or not logged in"); throw new CommandException("No client provided or not logged in");
} }
[Command("getSelfUser")]
public static string GetSelfUserCommand(TcpClient? client, TcpServer? socket)
{
if (client == null || socket == null)
throw new CommandException("No client connection detected.");
if (socket.LoggedInClients.TryGetValue(client, out var username))
{
Employee returnEmployee = new Employee(username);
string jsonEmployee = JsonSerializer.Serialize(returnEmployee);
return jsonEmployee;
}
throw new CommandException("User not logged in.");
}
#endregion #endregion

View File

@ -2,7 +2,6 @@
using System.Reflection; using System.Reflection;
using System.Text.Json; using System.Text.Json;
using DX86; using DX86;
using Server.Commands;
namespace Server; namespace Server;
@ -29,8 +28,15 @@ public class CommandManager
Program.messageSender.Log($"[COMMANDMANAGER] Registered command: {attr.Name}"); Program.messageSender.Log($"[COMMANDMANAGER] Registered command: {attr.Name}");
} }
} }
public void ExecuteCommand(string executor, TcpClient? client = null, TcpServer? clientSocket = null, string cid = "", params string[] args) public void ExecuteCommand(string executor,
TcpClient? client = null,
TcpServer? clientSocket = null,
string cid = "",
params string[] args)
{ {
// — ensure args is never null —
args ??= Array.Empty<string>();
if (_commands.TryGetValue(executor.ToLower(), out var method)) if (_commands.TryGetValue(executor.ToLower(), out var method))
{ {
try try
@ -50,43 +56,55 @@ public class CommandManager
arguments[i] = clientSocket; arguments[i] = clientSocket;
else else
{ {
Program.messageSender.Warn($"[COMMANDMANAGER] Unknown parameter type '{param.ParameterType.Name}' in command '{executor}'. Defaulting to null."); Program.messageSender.Warn(
$"[COMMANDMANAGER] Unknown parameter type '{param.ParameterType.Name}' in '{executor}'. Defaulting that argument to null."
);
arguments[i] = null; arguments[i] = null;
} }
} }
Program.messageSender.Debug($"[COMMANDMANAGER] Executing command '{executor}'..."); Program.messageSender.Debug($"[COMMANDMANAGER] Executing command '{executor}'…");
string result = method.Invoke(null, arguments)?.ToString() ?? ""; var rawResult = method.Invoke(null, arguments); // invoke the static command method
string result = rawResult?.ToString() ?? "";
var returnMessage = new JsonMessage // **Log the returned string before sending**
Program.messageSender.Debug($"[COMMANDMANAGER] Command '{executor}' returned: \"{result}\"");
var returnMessage = new Library.Server.JsonResponse
{ {
cid = cid, Id = cid,
cmd = result Response = result
}; };
var sendClientMessage = JsonSerializer.Serialize(returnMessage); var sendClientMessage = JsonSerializer.Serialize(returnMessage);
clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n");
Program.messageSender.Debug($"[COMMANDMANAGER] Response sent to client."); Program.messageSender.Debug($"[COMMANDMANAGER] Response sent to client.");
} }
// If your command threw a CommandException, catch it here:
catch (TargetInvocationException ex) when (ex.InnerException is CommandException cmdEx) catch (TargetInvocationException ex) when (ex.InnerException is CommandException cmdEx)
{ {
Program.messageSender.Warn($"[COMMANDMANAGER] Command '{executor}' failed: {cmdEx.Message}"); Program.messageSender.Warn($"[COMMANDMANAGER] Command '{executor}' failed: {cmdEx.Message}");
var returnMessage = new JsonMessage var returnMessage = new Library.Server.JsonResponse
{ {
cid = cid, Id = cid,
cmd = $"Error: {cmdEx.Message}" Response = $"Error: {cmdEx.Message}"
}; };
var sendClientMessage = JsonSerializer.Serialize(returnMessage); var sendClientMessage = JsonSerializer.Serialize(returnMessage);
clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n");
} }
// Any other exception inside the invoked method
catch (TargetInvocationException ex) catch (TargetInvocationException ex)
{ {
var actualError = ex.InnerException?.Message ?? ex.Message; var actualError = ex.InnerException?.Message ?? ex.Message;
Program.messageSender.Error($"[COMMANDMANAGER] Unexpected error in command '{executor}': {actualError}"); Program.messageSender.Error(
Program.messageSender.Debug($"[COMMANDMANAGER] Stack Trace: {ex.InnerException?.StackTrace ?? ex.StackTrace}"); $"[COMMANDMANAGER] Unexpected error in command '{executor}': {actualError}"
);
Program.messageSender.Debug(
$"[COMMANDMANAGER] Stack Trace: {ex.InnerException?.StackTrace ?? ex.StackTrace}"
);
} }
// Anything else thrown before or during Invoke()
catch (Exception ex) catch (Exception ex)
{ {
Program.messageSender.Error($"[COMMANDMANAGER] Failed to invoke command '{executor}': {ex.Message}"); Program.messageSender.Error($"[COMMANDMANAGER] Failed to invoke command '{executor}': {ex.Message}");

View File

@ -1,6 +0,0 @@
namespace Server.Commands;
public class GetCommand
{
}

View File

@ -1,26 +0,0 @@
using System.Net.Sockets;
using DX86;
namespace Server.Commands;
public class HelpCommand : ICommand
{
public string Executor { get; }
public HelpCommand()
{
Executor = "help";
}
public string Exec(string[] args, TcpClient? client = null, TcpServer? clientSocket = null)
{
return
"Available commands:\n" +
"1. help - Show this help message\n" +
"2. exit - Exit the server\n" +
"3. user - User management\n" +
"4. settings - Server settings\n" +
"5. start - Start the server\n" +
"6. stop - Stop the server\n"
;
}
}

View File

@ -1,10 +0,0 @@
using System.Net.Sockets;
using DX86;
namespace Server.Commands;
public interface ICommand
{
string Executor { get; }
public string Exec(string[] args, TcpClient? client, TcpServer? clientSocket);
}

View File

@ -1,34 +0,0 @@
using System.Net.Sockets;
using DX86;
using MySqlX.XDevAPI;
namespace Server.Commands;
public class LoginCommand : ICommand
{
public string Executor { get; }
public LoginCommand()
{
Executor = "login";
}
public string Exec(string[] args, TcpClient? client, TcpServer? clientSocket)
{
if (args[0] == "test" && args[1] == "test")
{
if (client != null)
{
//clientSocket?.SendMessageAsync(client, "Login successful");
clientSocket?.LoggedInClients.Add(client, "test");
return "Login successful";
}
}
else
{
if (client != null) return "Invalid credentials";
}
return "No client provided or invalid credentials";
}
}

View File

@ -1,30 +0,0 @@
using System.Net.Sockets;
using DX86;
namespace Server.Commands;
public class LogoutCommand : ICommand
{
public string Executor { get; }
public LogoutCommand()
{
Executor = "logout";
}
public string Exec(string[] args, TcpClient? client = null, TcpServer? clientSocket = null)
{
if (clientSocket == null && client == null)
return "Please provide a valid client or clientSocket.";
if (client != null && clientSocket != null && clientSocket.LoggedInClients.ContainsKey(client))
{
clientSocket.LoggedInClients.Remove(client);
//clientSocket.SendMessageAsync(client, "Success");
return "Logout successful.";
}
else
{
//clientSocket?.SendMessageAsync(client, "Logout failed. You are not logged in.");
return "Logout failed. You are not logged in.";
}
}
}