From f79198e5aa5e0cfd24d4c47d49c3561e1835cc8e Mon Sep 17 00:00:00 2001 From: EonaCat Date: Sun, 23 Mar 2025 20:08:18 +0100 Subject: [PATCH] Added EonaCat.Network.Tester --- .../EonaCat.Network.Tester.csproj | 14 ++ EonaCat.Network.Tester/Program.cs | 188 ++++++++++++++++++ EonaCat.Network.Tester/TestModule.cs | 16 ++ JsonTester/JsonTester.csproj | 7 +- 4 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 EonaCat.Network.Tester/EonaCat.Network.Tester.csproj create mode 100644 EonaCat.Network.Tester/Program.cs create mode 100644 EonaCat.Network.Tester/TestModule.cs diff --git a/EonaCat.Network.Tester/EonaCat.Network.Tester.csproj b/EonaCat.Network.Tester/EonaCat.Network.Tester.csproj new file mode 100644 index 0000000..3b0107d --- /dev/null +++ b/EonaCat.Network.Tester/EonaCat.Network.Tester.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/EonaCat.Network.Tester/Program.cs b/EonaCat.Network.Tester/Program.cs new file mode 100644 index 0000000..88cd9bb --- /dev/null +++ b/EonaCat.Network.Tester/Program.cs @@ -0,0 +1,188 @@ +// This file is part of the EonaCat project(s) which is released under the Apache License. +// See the LICENSE file or go to https://EonaCat.com/License for full license details. + +using System.Net.Security; +using System.Reflection; +using System.Security.Authentication; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using EonaCat.WebSockets; + +internal class Program +{ + private static AsyncWebSocketClient _client; + private static AsyncWebSocketServer _server; + + private static async Task Main(string[] args) + { + // Menu loop + while (true) + { + Console.WriteLine("0. Create a HTTPS certificate"); + Console.WriteLine("1. Start the server and client"); + Console.WriteLine("2. Send Message"); + Console.WriteLine("3. Quit"); + + var choice = Console.ReadLine(); + + switch (choice) + { + case "0": + CreateCertificate(); + break; + + case "1": + await CreateServerAndClientAsync().ConfigureAwait(false); + break; + + case "2": + if (_client != null) + { + Console.Write("Enter message: "); + var message = Console.ReadLine(); + await _client.SendTextAsync(message).ConfigureAwait(false); + } + + break; + + case "3": + _client?.CloseAsync().ConfigureAwait(false); + return; + + default: + Console.WriteLine("Invalid choice. Try again."); + break; + } + } + } + + private static async Task CreateServerAndClientAsync() + { + var serverUri = "wss://localhost:8443"; + var clientUri = "wss://localhost:8443/Welcome"; + var certificatePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "localhost.pfx"); + var certificatePassword = ""; + var requiredPassword = ""; + + // Start the server + StartServer(serverUri, certificatePath, certificatePassword, requiredPassword); + + // Start the client in the main thread + await StartClientAsync(clientUri, certificatePath, certificatePassword).ConfigureAwait(false); + Console.WriteLine("Connected to the server."); + } + + private static async Task StartClientAsync(string clientUri, string certificatePath, string certificatePassword) + { + var configuration = new AsyncWebSocketClientConfiguration(); + configuration.SslTargetHost = "localhost"; + configuration.SslEncryptionPolicy = EncryptionPolicy.RequireEncryption; + configuration.SslCheckCertificateRevocation = false; + configuration.SslPolicyErrorsBypassed = true; + configuration.SslEnabledProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; + configuration.SslClientCertificates = new X509CertificateCollection { new X509Certificate2(certificatePath, certificatePassword) }; + + _client = new AsyncWebSocketClient(new Uri(clientUri), OnServerTextReceived, OnServerBinaryReceived, OnServerConnected, OnServerDisconnected, OnServerFragmentationStreamOpened, OnServerFragmentationStreamOpened, OnServerFragmentationStreamClosed, configuration); + await _client.ConnectAsync().ConfigureAwait(false); + } + + private static Task OnServerFragmentationStreamClosed(AsyncWebSocketClient arg1, byte[] arg2, int arg3, int arg4) + { + // Do nothing + return Task.CompletedTask; + } + + private static Task OnServerFragmentationStreamOpened(AsyncWebSocketClient arg1, byte[] arg2, int arg3, int arg4) + { + // Do nothing + return Task.CompletedTask; + } + + private static Task OnServerDisconnected(AsyncWebSocketClient arg) + { + Console.WriteLine("Disconnected from server."); + return Task.CompletedTask; + } + + private static Task OnServerConnected(AsyncWebSocketClient arg) + { + Console.WriteLine("Connected to server."); + return Task.CompletedTask; + } + + private static Task OnServerBinaryReceived(AsyncWebSocketClient arg1, byte[] bytes, int arg3, int arg4) + { + Console.WriteLine($"Received binary {bytes} {arg3} {arg4}"); + return Task.CompletedTask; + } + + private static Task OnServerTextReceived(AsyncWebSocketClient arg1, string data) + { + Console.WriteLine($"Received message from server: {data}"); + return Task.CompletedTask; + } + + private static void CreateCertificate() + { + Console.Write("Enter hostname: (default: localhost) "); + var hostname = Console.ReadLine(); + + if (string.IsNullOrWhiteSpace(hostname)) + { + hostname = "localhost"; + } + + var days = 30; + Console.Write("Enter days until expiration: (default: 30 days) "); + if (int.TryParse(Console.ReadLine(), out var givenDays)) + { + days = givenDays; + } + + Console.Write("Enter password, enter to skip: "); + var password = Console.ReadLine(); + + var rsa = RSA.Create(); + + // Create a certificate request with the specified subject and key pair + var request = new CertificateRequest( + $"CN={hostname}", + rsa, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + // Create a self-signed certificate from the certificate request + var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(days)); + + // Export the certificate to a file with password + var certBytes = string.IsNullOrEmpty(password) + ? certificate.Export(X509ContentType.Pfx) + : certificate.Export(X509ContentType.Pfx, password); + File.WriteAllBytes($"{hostname}.pfx", certBytes); + + Console.WriteLine( + $"Certificate for {hostname} created successfully and will expire on {certificate.NotAfter}."); + Console.WriteLine($"Path: {Path.Combine(AppContext.BaseDirectory, hostname)}.pfx"); + } + + private static void StartServer(string serverUri, string certificatePath, string certificatePassword, + string requiredPassword) + { + // split the server uri to get the port + var uri = new Uri(serverUri); + var port = uri.Port; + + var test = new AsyncWebSocketServerModuleCatalog(); + test.RegisterModule(new TestModule()); + var configuration = new AsyncWebSocketServerConfiguration(); + configuration.SslEnabled = true; + configuration.SslEncryptionPolicy = EncryptionPolicy.RequireEncryption; + configuration.SslCheckCertificateRevocation = false; + configuration.SslPolicyErrorsBypassed = true; + configuration.SslClientCertificateRequired = true; + configuration.SslEnabledProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; + configuration.SslServerCertificate = new X509Certificate2(certificatePath, certificatePassword); + _server = new AsyncWebSocketServer(port, test, configuration); + _server.Listen(); + } +} \ No newline at end of file diff --git a/EonaCat.Network.Tester/TestModule.cs b/EonaCat.Network.Tester/TestModule.cs new file mode 100644 index 0000000..13d372b --- /dev/null +++ b/EonaCat.Network.Tester/TestModule.cs @@ -0,0 +1,16 @@ +// This file is part of the EonaCat project(s) which is released under the Apache License. +// See the LICENSE file or go to https://EonaCat.com/License for full license details. + +using EonaCat.WebSockets; + +internal class TestModule : AsyncWebSocketServerModule +{ + public TestModule() + : base("/Welcome") + { + } + public override async Task OnSessionTextReceived(AsyncWebSocketSession session, string text) + { + await session.SendTextAsync(text); + } +} \ No newline at end of file diff --git a/JsonTester/JsonTester.csproj b/JsonTester/JsonTester.csproj index d729163..bcc0f02 100644 --- a/JsonTester/JsonTester.csproj +++ b/JsonTester/JsonTester.csproj @@ -8,9 +8,14 @@ - + + + ..\..\EonaCat.Json\EonaCat.Json\bin\Release\netstandard2.1\EonaCat.Json.dll + + +