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; }
}
}