From 6414631debcc762e26ecd59e2dbd74c8de160e5a Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 17 Jan 2023 09:49:16 -0600 Subject: [PATCH] feat: added crestron web server (cws) to Essentials_Core --- .../CrestronWebServerBase.cs | 197 ++++++++++++++++++ .../CrestronWebServerFactory.cs | 20 ++ .../RequestHandlerUnknown.cs | 19 ++ 3 files changed, 236 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs new file mode 100644 index 00000000..d9649a7d --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs @@ -0,0 +1,197 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + public class CrestronWebServerBase : EssentialsDevice, IDisposable + { + private HttpCwsServer _server; + private readonly CCriticalSection _serverLock = new CCriticalSection(); + + /// + /// CWS base path + /// + public string BasePath { get; private set; } + + /// + /// Constructor + /// + /// + /// + /// + public CrestronWebServerBase(string key, string name, string basePath) + : base(key, name) + { + Key = key; + + BasePath = string.IsNullOrEmpty(basePath) ? "/api" : basePath; + + CrestronEnvironment.ProgramStatusEventHandler += programEvent => + { + if (programEvent != eProgramStatusEventType.Stopping) + return; + + Dispose(true); + }; + } + + /// + /// Initializes the CWS class + /// + public override void Initialize() + { + ServerStart(); + base.Initialize(); + } + + /// + /// Starts the CWS server + /// + public void ServerStart() + { + try + { + _serverLock.Enter(); + + if (_server != null) + { + Debug.Console(1, this, "Server is already running"); + return; + } + + Debug.Console(1, this, "Starting server"); + + _server = new HttpCwsServer(BasePath) + { + HttpRequestHandler = new RequestHandlerUnknown() + }; + + // TODO [ ] Add server paths + } + catch (Exception ex) + { + Debug.Console(1, this, "ServerStart Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ServerStart Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ServerStart Exception InnerException: {0}", ex.InnerException); + } + finally + { + _serverLock.Leave(); + } + } + + /// + /// Stops the CWS server + /// + public void ServerStop() + { + try + { + _serverLock.Enter(); + if (_server == null) + { + Debug.Console(1, this, "Server is already stopped"); + return; + } + + _server.Unregister(); + _server.Dispose(); + _server = null; + } + catch (Exception ex) + { + Debug.Console(1, this, "ServerStop Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ServerStop Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ServerStop Exception InnerException: {0}", ex.InnerException); + } + finally + { + _serverLock.Leave(); + } + } + + /// + /// Received request handler + /// + /// + /// + public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args) + { + try + { + // TODO [ ] Add logic for received requests + Debug.Console(1, this, @"RecieveRequestEventHandler +Method: {0} +Path: {1} +PathInfo: {2} +PhysicalPath: {3} +ContentType: {4} +RawUrl: {5} +Url: {6} +UserAgent: {7} +UserHostAddress: {8} +UserHostName: {9}", + args.Context.Request.HttpMethod, + args.Context.Request.Path, + args.Context.Request.PathInfo, + args.Context.Request.PhysicalPath, + args.Context.Request.ContentType, + args.Context.Request.RawUrl, + args.Context.Request.Url, + args.Context.Request.UserAgent, + args.Context.Request.UserHostAddress, + args.Context.Request.UserHostName); + + } + catch (Exception ex) + { + Debug.Console(1, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException); + } + } + + #region Dispose + + /// + /// Tracks if the CWS is disposed + /// + public bool Disposed { get; private set; } + + /// + /// Disposes of the CWS + /// + public void Dispose() + { + Dispose(true); + CrestronEnvironment.GC.SuppressFinalize(this); + } + + protected void Dispose(bool disposing) + { + if (Disposed) + { + Debug.Console(1, this, "Server has already been disposed"); + return; + } + + if (!disposing) return; + + if (_server != null) ServerStop(); + + Disposed = _server == null; + } + + ~CrestronWebServerBase() + { + Dispose(true); + } + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs new file mode 100644 index 00000000..ab442ecb --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core +{ + public class CrestronWebServerFactory : EssentialsDeviceFactory + { + public CrestronWebServerFactory() + { + TypeNames = new List { "crestroncws", "cws" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Crestron CWS Device"); + + return new CrestronWebServerBase(dc.Key, dc.Name, ""); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs new file mode 100644 index 00000000..71cf383a --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs @@ -0,0 +1,19 @@ +using Crestron.SimplSharp.WebScripting; + +namespace PepperDash.Essentials.Core +{ + /// + /// Crestron CWS unknown request handler + /// + public class RequestHandlerUnknown : IHttpCwsHandler + { + + public void ProcessRequest(HttpCwsContext context) + { + // TODO [ ] Modify unknown request handler + context.Response.StatusCode = 418; + context.Response.ContentType = "application/json"; + context.Response.Write(string.Format("{0} {1}", context.Request.HttpMethod, context.Request.RawUrl), true); + } + } +} \ No newline at end of file