From a732c5e08e37ec5e3d9e241061fd210938fd9ac3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 23 Jun 2026 16:08:42 -0600 Subject: [PATCH] feat: enhance WebSocket services with HTTP GET handler for certificate confirmation and increase timeout for port forwarding --- .../Logging/DebugWebsocketSink.cs | 11 ++++++++ .../DebugSessionRequestHandler.cs | 4 +-- .../RoutingFeedbackSessionRequestHandler.cs | 2 +- .../Web/RoutingFeedbackWebsocket.cs | 11 ++++++++ .../VideoCodec/MockVC/MockVC.cs | 28 ++++++++++++++++++- .../VideoCodec/VideoCodecBase.cs | 2 +- 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs index 3027640f..07e8f489 100644 --- a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs +++ b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs @@ -262,6 +262,7 @@ public class DebugWebsocketSink : ILogEventSink, IKeyed } Debug.LogInformation("Adding Debug Client Service"); _httpsServer.AddWebSocketService(_path); + _httpsServer.OnGet += HandleHttpGet; Debug.LogInformation("Assigning Log Info"); _httpsServer.Log.Level = LogLevel.Trace; _httpsServer.Log.Output = WriteWebSocketInternalLog; @@ -279,6 +280,16 @@ public class DebugWebsocketSink : ILogEventSink, IKeyed } } + private void HandleHttpGet(object sender, HttpRequestEventArgs e) + { + var res = e.Response; + var body = System.Text.Encoding.UTF8.GetBytes( + "

Certificate accepted.

You can close this tab and return to the application.

"); + res.ContentType = "text/html"; + res.ContentLength64 = body.Length; + res.Close(body, true); + } + /// /// Stops the WebSocket server if it is currently running. /// diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs index c6303190..ea9c5b82 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs @@ -196,7 +196,7 @@ public class DebugSessionRequestHandler : WebApiBaseRequestHandler return; } - Debug.LogMessage(LogEventLevel.Information, "No debug websocket connection within 30 seconds; removing port forward for port {0}", port); + Debug.LogMessage(LogEventLevel.Information, "No debug websocket connection within timeout; removing port forward for port {0}", port); try { @@ -217,7 +217,7 @@ public class DebugSessionRequestHandler : WebApiBaseRequestHandler { Debug.LogMessage(LogEventLevel.Warning, "Error removing port forwarding on timeout: {0}", ex.Message); } - }, 30000); + }, 120000); } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/RoutingFeedbackSessionRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/RoutingFeedbackSessionRequestHandler.cs index 2ca432c3..d095b78f 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/RoutingFeedbackSessionRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/RoutingFeedbackSessionRequestHandler.cs @@ -210,7 +210,7 @@ public class RoutingFeedbackSessionRequestHandler : WebApiBaseRequestHandler { Debug.LogMessage(LogEventLevel.Warning, "Error removing port forwarding on timeout: {0}", ex.Message); } - }, 30000); + }, 120000); } } diff --git a/src/PepperDash.Essentials.Core/Web/RoutingFeedbackWebsocket.cs b/src/PepperDash.Essentials.Core/Web/RoutingFeedbackWebsocket.cs index 14139323..444a1e8c 100644 --- a/src/PepperDash.Essentials.Core/Web/RoutingFeedbackWebsocket.cs +++ b/src/PepperDash.Essentials.Core/Web/RoutingFeedbackWebsocket.cs @@ -113,6 +113,7 @@ public class RoutingFeedbackWebsocket : IKeyed _httpsServer.SslConfiguration.ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; _httpsServer.AddWebSocketService(_path); + _httpsServer.OnGet += HandleHttpGet; _httpsServer.Log.Level = LogLevel.Warn; _httpsServer.Start(); @@ -338,6 +339,16 @@ public class RoutingFeedbackWebsocket : IKeyed service.Sessions.Broadcast(message); } + private void HandleHttpGet(object sender, HttpRequestEventArgs e) + { + var res = e.Response; + var body = System.Text.Encoding.UTF8.GetBytes( + "

Certificate accepted.

You can close this tab and return to the application.

"); + res.ContentType = "text/html"; + res.ContentLength64 = body.Length; + res.Close(body, true); + } + private static X509Certificate2 LoadCert(string certPath, string certPassword) { return new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.EphemeralKeySet); diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs index 7b8f73a3..56a4106e 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs @@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// Represents a MockVC /// - public class MockVC : VideoCodecBase, IRoutingSource, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites, IHasDirectory, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets + public class MockVC : VideoCodecBase, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites, IHasDirectory, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IRoutingSinkWithFeedback { /// /// Gets or sets the PropertiesConfig @@ -858,6 +858,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #endregion + #region IRoutingSinkWithFeedback Members + + public RoutingInputPort CurrentInputPort { get; private set; } + + public event InputChangedEventHandler InputChanged; + + #endregion + + #region ICurrentSources Members + + public Dictionary CurrentSources { get; private set; } = new Dictionary(); + + public Dictionary CurrentSourceKeys { get; private set; } = new Dictionary(); + + public event EventHandler CurrentSourcesChanged; + + public void SetCurrentSource(eRoutingSignalType signalType, IRoutingSource sourceDevice) + { + CurrentSources.TryGetValue(signalType, out var previousSource); + CurrentSources[signalType] = sourceDevice; + CurrentSourceKeys[signalType] = sourceDevice?.Key; + CurrentSourcesChanged?.Invoke(this, new CurrentSourcesChangedEventArgs(signalType, previousSource, sourceDevice)); + } + + #endregion + /// protected override void CustomSetConfig(DeviceConfig config) { diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs index de6900af..98a44b40 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs @@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec; /// Base class for video codecs. Contains common properties, methods, and feedback for video codecs. /// Also contains the logic to link commonly implemented interfaces to the API bridge. /// -public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingMidpoint, +public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingSource, IUsageTracking, ICodecCallControls, IHasContentSharing, ICodecAudio, IVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode, IHasReady { private const int XSigEncoding = 28591;