// 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.Network; using System.Reflection; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; internal class Program { private static WSClient _client; private static WSServer _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(); break; case "2": if (_client != null) { Console.Write("Enter message: "); var message = Console.ReadLine(); _client.Send(message); } break; case "3": _client?.Close(); 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 clientName = "TestClient"; 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 _client = new WSClient(clientUri); _client.SSL.Certificates.Add(new X509Certificate(certificatePath, certificatePassword)); _client.OnConnect += (sender, e) => Console.WriteLine($"Connected to server"); _client.OnMessageReceived += (sender, e) => Console.WriteLine($"Received message from server: {e.Data}"); _client.OnDisconnect += (sender, e) => Console.WriteLine($"Disconnected from server: {e.Code} : {e.Reason}"); _client.OnError += (sender, e) => Console.WriteLine($"Error: {sender}\n{e}"); _client.ConnectAsync(); Console.WriteLine("Connected to the server."); } private static void CreateCertificate() { Console.Write("Enter hostname: (default: localhost) "); string hostname = Console.ReadLine(); if (string.IsNullOrWhiteSpace(hostname)) { hostname = "localhost"; } int days = 30; Console.Write("Enter days until expiration: (default: 30 days) "); if (int.TryParse(Console.ReadLine(), out int givenDays)) { days = givenDays; } Console.Write("Enter password, enter to skip: "); string password = Console.ReadLine(); RSA rsa = RSA.Create(); // Create a certificate request with the specified subject and key pair CertificateRequest request = new CertificateRequest( $"CN={hostname}", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); // Create a self-signed certificate from the certificate request X509Certificate2 certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(days)); // Export the certificate to a file with password byte[] 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) { _server = new WSServer(serverUri); _server.SslConfiguration.Certificate = new X509Certificate2(certificatePath, certificatePassword); _server.AddEndpoint("/Welcome"); _server.Start(); } }