using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; namespace Crestron.SimplSharp.WebScripting { /// Mock HttpCwsServer class for HTTP web server functionality public class HttpCwsServer : IDisposable { private HttpListener? _httpListener; private bool _listening; private readonly Dictionary _routes = new Dictionary(); /// Gets or sets the port number public int Port { get; set; } /// Gets whether the server is listening public bool Listening => _listening; /// Initializes a new instance of HttpCwsServer public HttpCwsServer() { Port = 80; } /// Initializes a new instance of HttpCwsServer /// Port number to listen on public HttpCwsServer(int port) { Port = port; } /// Starts the HTTP server /// True if started successfully public bool Start() { if (_listening) return true; try { _httpListener = new HttpListener(); _httpListener.Prefixes.Add($"http://+:{Port}/"); _httpListener.Start(); _listening = true; _ = Task.Run(ProcessRequestsAsync); return true; } catch (Exception) { return false; } } /// Stops the HTTP server /// True if stopped successfully public bool Stop() { if (!_listening) return true; try { _listening = false; _httpListener?.Stop(); _httpListener?.Close(); return true; } catch (Exception) { return false; } } /// Adds a route handler /// Route path /// Handler for the route public void AddRoute(string route, IHttpCwsHandler handler) { _routes[route.ToLowerInvariant()] = handler; } /// Removes a route handler /// Route path to remove public void RemoveRoute(string route) { _routes.Remove(route.ToLowerInvariant()); } /// Unregisters a route handler /// Route path to unregister public void Unregister(string route) { RemoveRoute(route); } private async Task ProcessRequestsAsync() { while (_listening && _httpListener != null) { try { var context = await _httpListener.GetContextAsync(); _ = Task.Run(() => HandleRequest(context)); } catch (HttpListenerException) { // Listener was stopped break; } catch (ObjectDisposedException) { // Listener was disposed break; } catch (Exception) { // Handle other exceptions continue; } } } private void HandleRequest(HttpListenerContext context) { try { var request = context.Request; var response = context.Response; var path = request.Url?.AbsolutePath?.ToLowerInvariant() ?? "/"; var cwsContext = new HttpCwsContext(context); if (_routes.TryGetValue(path, out var handler)) { handler.ProcessRequest(cwsContext); } else { // Default 404 response response.StatusCode = 404; var buffer = Encoding.UTF8.GetBytes("Not Found"); response.ContentLength64 = buffer.Length; response.OutputStream.Write(buffer, 0, buffer.Length); } response.Close(); } catch (Exception) { // Handle request processing errors try { context.Response.StatusCode = 500; context.Response.Close(); } catch { // Ignore errors when closing response } } } /// Disposes the HttpCwsServer public void Dispose() { Stop(); _httpListener?.Close(); } } /// Mock HttpCwsContext class representing an HTTP request/response context public class HttpCwsContext { private readonly HttpListenerContext _context; /// Gets the HTTP request public HttpCwsRequest Request { get; } /// Gets the HTTP response public HttpCwsResponse Response { get; } /// Initializes a new instance of HttpCwsContext /// Underlying HttpListenerContext public HttpCwsContext(HttpListenerContext context) { _context = context; Request = new HttpCwsRequest(context.Request); Response = new HttpCwsResponse(context.Response); } } /// Mock HttpCwsRequest class representing an HTTP request public class HttpCwsRequest { private readonly HttpListenerRequest _request; /// Gets the HTTP method public string HttpMethod => _request.HttpMethod; /// Gets the request URL public Uri? Url => _request.Url; /// Gets the request headers public System.Collections.Specialized.NameValueCollection Headers => _request.Headers; /// Gets the query string public System.Collections.Specialized.NameValueCollection QueryString => _request.QueryString; /// Gets the content type public string? ContentType => _request.ContentType; /// Gets the content length public long ContentLength => _request.ContentLength64; /// Gets the input stream public Stream InputStream => _request.InputStream; /// Initializes a new instance of HttpCwsRequest /// Underlying HttpListenerRequest public HttpCwsRequest(HttpListenerRequest request) { _request = request; } /// Gets the request body as a string /// Request body content public string GetRequestBodyAsString() { using var reader = new StreamReader(InputStream, Encoding.UTF8); return reader.ReadToEnd(); } } /// Mock HttpCwsResponse class representing an HTTP response public class HttpCwsResponse { private readonly HttpListenerResponse _response; /// Gets or sets the status code public int StatusCode { get => _response.StatusCode; set => _response.StatusCode = value; } /// Gets or sets the status description public string StatusDescription { get => _response.StatusDescription; set => _response.StatusDescription = value; } /// Gets or sets the content type public string? ContentType { get => _response.ContentType; set => _response.ContentType = value; } /// Gets or sets the content length public long ContentLength { get => _response.ContentLength64; set => _response.ContentLength64 = value; } /// Gets the response headers public WebHeaderCollection Headers => _response.Headers; /// Gets the output stream public Stream OutputStream => _response.OutputStream; /// Initializes a new instance of HttpCwsResponse /// Underlying HttpListenerResponse public HttpCwsResponse(HttpListenerResponse response) { _response = response; } /// Writes a string to the response /// Content to write public void Write(string content) { var buffer = Encoding.UTF8.GetBytes(content); ContentLength = buffer.Length; OutputStream.Write(buffer, 0, buffer.Length); } /// Writes bytes to the response /// Buffer to write /// Offset in buffer /// Number of bytes to write public void Write(byte[] buffer, int offset, int count) { OutputStream.Write(buffer, offset, count); } /// Ends the response public void End() { try { _response.Close(); } catch (Exception) { // Ignore exceptions during close } } } /// Interface for HTTP request handlers public interface IHttpCwsHandler { /// Processes an HTTP request /// HTTP context void ProcessRequest(HttpCwsContext context); } /// Mock HttpCwsRoute class for route management public class HttpCwsRoute { /// Gets or sets the route path public string Path { get; set; } = string.Empty; /// Gets or sets the HTTP method public string Method { get; set; } = "GET"; /// Gets or sets the route handler public IHttpCwsHandler? Handler { get; set; } /// Initializes a new instance of HttpCwsRoute public HttpCwsRoute() { } /// Initializes a new instance of HttpCwsRoute /// Route path /// Route handler public HttpCwsRoute(string path, IHttpCwsHandler handler) { Path = path; Handler = handler; } /// Initializes a new instance of HttpCwsRoute /// Route path /// HTTP method /// Route handler public HttpCwsRoute(string path, string method, IHttpCwsHandler handler) { Path = path; Method = method; Handler = handler; } } /// Mock HTTP CWS route collection public class HttpCwsRouteCollection { private readonly List _routes = new List(); /// Adds a route /// Route to add public void Add(HttpCwsRoute route) { _routes.Add(route); } /// Removes a route /// Route to remove public void Remove(HttpCwsRoute route) { _routes.Remove(route); } /// Clears all routes public void Clear() { _routes.Clear(); } /// Gets route count public int Count => _routes.Count; } /// Mock HTTP CWS request event args public class HttpCwsRequestEventArgs : EventArgs { /// Gets the HTTP context public HttpCwsContext Context { get; private set; } /// Initializes new instance /// HTTP context public HttpCwsRequestEventArgs(HttpCwsContext context) { Context = context; } } }