using System.Net; using System.Text; using Inspectron.Epson.PrintServer.ConfigurationSources; namespace EpsonPrintService; public class SimpleHttpServer { private readonly HttpListener _listener; private readonly Func _getConfig; private readonly Func _getIsRunning; public SimpleHttpServer(Func getConfig, Func getIsRunning) { _listener = new HttpListener(); _listener.Prefixes.Add("http://+:80/"); _getConfig = getConfig; _getIsRunning = getIsRunning; } public async Task StartAsync(CancellationToken cancellationToken) { _listener.Start(); Console.WriteLine("Web UI listening on http://+:80/"); try { while (!cancellationToken.IsCancellationRequested) { var context = await _listener.GetContextAsync(); _ = Task.Run(() => HandleRequestAsync(context), cancellationToken); } } catch (HttpListenerException) when (cancellationToken.IsCancellationRequested) { // Expected on shutdown } finally { _listener.Stop(); } } private async Task HandleRequestAsync(HttpListenerContext context) { try { var request = context.Request; var response = context.Response; var path = request.Url?.AbsolutePath ?? "/"; var method = request.HttpMethod; string html; if (method == "GET" && path == "/") { html = await BuildIndexPageAsync(); } else if (method == "POST" && path == "/update-key") { html = await HandleUpdateKeyAsync(); } else { response.StatusCode = 404; html = "

Not Found

"; } var buffer = Encoding.UTF8.GetBytes(html); response.ContentType = "text/html; charset=utf-8"; response.ContentLength64 = buffer.Length; await response.OutputStream.WriteAsync(buffer); response.Close(); } catch (Exception ex) { Console.WriteLine($"HTTP error: {ex.Message}"); try { context.Response.Close(); } catch { } } } private async Task BuildIndexPageAsync() { var usbResult = await UsbKeyScanner.ScanForKeyAsync(); return HtmlPageBuilder.BuildConfigPage(_getConfig(), _getIsRunning(), usbResult); } private async Task HandleUpdateKeyAsync() { var usbResult = await UsbKeyScanner.ScanForKeyAsync(); if (!usbResult.Found || usbResult.Base64Content == null) { return HtmlPageBuilder.BuildConfigPage( _getConfig(), _getIsRunning(), usbResult, errorMessage: "No valid USB key found. Please insert a USB drive and try again."); } // Validate again var validation = ConfigurationLoader.TryLoadFromBase64(usbResult.Base64Content); if (!validation.Success) { return HtmlPageBuilder.BuildConfigPage( _getConfig(), _getIsRunning(), usbResult, errorMessage: $"Key validation failed: {validation.Error}"); } // Write config file try { var configPath = ConfigurationPaths.GetConfigPath(); var configDir = Path.GetDirectoryName(configPath); if (!string.IsNullOrEmpty(configDir) && !Directory.Exists(configDir)) Directory.CreateDirectory(configDir); await File.WriteAllTextAsync(configPath, usbResult.Base64Content); Console.WriteLine($"Configuration updated at {configPath}"); } catch (Exception ex) { return HtmlPageBuilder.BuildConfigPage( _getConfig(), _getIsRunning(), usbResult, errorMessage: $"Failed to write configuration: {ex.Message}"); } // Schedule exit so systemd restarts us with new config _ = Task.Run(async () => { await Task.Delay(500); Console.WriteLine("Exiting for restart with new configuration..."); Environment.Exit(0); }); return HtmlPageBuilder.BuildSuccessPage(validation.Config!); } }