using System; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; using System.Web.Script.Serialization; namespace Card_Dispenser_Service { // Wrapper to hand both the parsed values and the network connection back to DoWork internal class IncomingRequestContext { public CardTaskResponse TaskData { get; set; } public HttpListenerContext HttpContext { get; set; } } internal class API { private static HttpListener _httpListener; public static readonly JavaScriptSerializer _serializer = new JavaScriptSerializer(); public static void StartListener(int port) { try { _httpListener = new HttpListener(); _httpListener.Prefixes.Add($"http://*:{port}/"); _httpListener.Start(); Utils.LogToFile($"HTTP Server started listening on port {port}..."); } catch (Exception ex) { Utils.LogToFile($"Failed to start HTTP Listener: {ex.Message}"); throw; } } public static void StopListener() { try { if (_httpListener != null && _httpListener.IsListening) { _httpListener.Stop(); _httpListener.Close(); Utils.LogToFile("HTTP Server stopped."); } } catch (Exception ex) { Utils.LogToFile($"Error stopping HTTP Listener: {ex.Message}"); } } /// /// Asynchronously waits for a request, reads the payload, and holds the connection open. /// public static async Task WaitForRequestAsync() { if (_httpListener == null || !_httpListener.IsListening) { Utils.LogToFile("Cannot wait for request; HTTP listener is not running."); return null; } try { HttpListenerContext context = await _httpListener.GetContextAsync(); HttpListenerRequest request = context.Request; CardTaskResponse taskData = null; if (request.HasEntityBody) { using (Stream body = request.InputStream) using (StreamReader reader = new StreamReader(body, request.ContentEncoding)) { string jsonString = await reader.ReadToEndAsync(); taskData = _serializer.Deserialize(jsonString); } } return new IncomingRequestContext { TaskData = taskData, HttpContext = context }; } catch (Exception ex) { Utils.LogToFile($"Error processing incoming HTTP request: {ex.Message}"); return null; } } /// /// Sends the calculated hardware response text back to the waiting client. /// public static async Task SendResponseAsync(HttpListenerContext context, string jsonResponseString, HttpStatusCode statusCode = HttpStatusCode.OK) { try { if (context == null) return; HttpListenerResponse response = context.Response; byte[] buffer = Encoding.UTF8.GetBytes(jsonResponseString); response.ContentLength64 = buffer.Length; response.ContentType = "application/json"; response.StatusCode = (int)statusCode; using (Stream output = response.OutputStream) { await output.WriteAsync(buffer, 0, buffer.Length); } } catch (Exception ex) { Utils.LogToFile($"Error sending dynamic response to client: {ex.Message}"); } } } internal class CardTaskResponse { public string Command { get; set; } public int Sector { get; set; } public int Block { get; set; } public string Data { get; set; } public string Serial { get; set; } public int BaudRate { get; set; } } }