diff --git a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs
index eeba5772..cfbf5785 100644
--- a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs
+++ b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs
@@ -72,6 +72,20 @@ namespace PepperDash.Core
///
public bool IsRunning { get => _httpsServer?.IsListening ?? false; }
+ ///
+ /// Gets a value indicating whether there are active WebSocket connections.
+ ///
+ public bool HasActiveConnections
+ {
+ get
+ {
+ if (_httpsServer == null || !_httpsServer.IsListening) return false;
+ var service = _httpsServer.WebSocketServices[_path];
+ if (service == null) return false;
+ return service.Sessions.Count > 0;
+ }
+ }
+
private readonly ITextFormatter _textFormatter;
@@ -217,6 +231,8 @@ namespace PepperDash.Core
{
Debug.LogInformation("Starting Websocket Server on port: {0}", port);
+
+
Start(port, CertPath, _certificatePassword);
}
diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs
index d1d27194..59c662dc 100644
--- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs
+++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs
@@ -17,7 +17,10 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
/// Represents a DebugSessionRequestHandler
///
public class DebugSessionRequestHandler : WebApiBaseRequestHandler
- {
+ {
+ private CTimer _portForwardTimeoutTimer;
+ private readonly object _timerLock = new object();
+
///
/// Constructor
///
@@ -81,6 +84,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
else
{
Debug.LogMessage(LogEventLevel.Information, "Port {0} forwarded to CS LAN for debug websocket", port);
+ StartPortForwardTimeout(port, csIp);
}
}
}
@@ -126,6 +130,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
///
protected override void HandlePost(HttpCwsContext context)
{
+ CancelPortForwardTimeout();
+
var port = Debug.WebsocketSink.Port;
Debug.WebsocketSink.StopServer();
@@ -174,5 +180,55 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
Debug.LogMessage(LogEventLevel.Information, "Websocket Debug Session Stopped");
}
+ private void StartPortForwardTimeout(int port, string csIp)
+ {
+ lock (_timerLock)
+ {
+ _portForwardTimeoutTimer?.Dispose();
+ _portForwardTimeoutTimer = new CTimer(_ =>
+ {
+ if (Debug.WebsocketSink.HasActiveConnections)
+ {
+ Debug.LogMessage(LogEventLevel.Debug, "Debug websocket has active connections; keeping port forward");
+ return;
+ }
+
+ Debug.LogMessage(LogEventLevel.Information, "No debug websocket connection within 30 seconds; removing port forward for port {0}", port);
+
+ try
+ {
+ var result = CrestronEthernetHelper.RemovePortForwarding(
+ (ushort)port, (ushort)port, csIp,
+ CrestronEthernetHelper.ePortMapTransport.TCP);
+
+ if (result != CrestronEthernetHelper.PortForwardingUserPatRetCodes.NoErr)
+ {
+ Debug.LogMessage(LogEventLevel.Warning, "Error removing port forwarding on timeout: {0}", result);
+ }
+ else
+ {
+ Debug.LogMessage(LogEventLevel.Information, "Port forwarding for port {0} removed due to timeout", port);
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.LogMessage(LogEventLevel.Warning, "Error removing port forwarding on timeout: {0}", ex.Message);
+ }
+ }, 30000);
+ }
+ }
+
+ ///
+ /// Cancels the port forward timeout timer if a session is being explicitly stopped.
+ ///
+ private void CancelPortForwardTimeout()
+ {
+ lock (_timerLock)
+ {
+ _portForwardTimeoutTimer?.Dispose();
+ _portForwardTimeoutTimer = null;
+ }
+ }
+
}
}