From 4a7a6ee2bf3404b55cf815f7f3f21f8c84418ef4 Mon Sep 17 00:00:00 2001 From: dheeraj12347 Date: Sat, 11 Apr 2026 11:12:36 +0530 Subject: [PATCH] Honour consoleproxy.session.timeout for noVNC sessions --- .../com/cloud/consoleproxy/ConsoleProxy.java | 17 ++++++++++++++++- .../consoleproxy/ConsoleProxyGCThread.java | 11 +++++++++-- .../consoleproxy/ConsoleProxyNoVNCHandler.java | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index e75ccea90441..abb388d7c532 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -80,6 +80,9 @@ public class ConsoleProxy { static String factoryClzName; static boolean standaloneStart = false; + // New: session timeout in milliseconds, default 300000 (5 minutes) + static int sessionTimeoutMillis = 300000; + static String encryptorPassword = "Dummy"; static final String[] skipProperties = new String[]{"certificate", "cacertificate", "keystore_password", "privatekey"}; @@ -165,6 +168,18 @@ private static void configProxy(Properties conf) { defaultBufferSize = Integer.parseInt(s); LOGGER.info("Setting defaultBufferSize=" + defaultBufferSize); } + + // New: read consoleproxy.session.timeout (milliseconds) + s = conf.getProperty("consoleproxy.session.timeout"); + if (s != null) { + try { + sessionTimeoutMillis = Integer.parseInt(s); + LOGGER.info("Setting consoleproxy.session.timeout=" + sessionTimeoutMillis); + } catch (NumberFormatException e) { + LOGGER.warn("Invalid value for consoleproxy.session.timeout: " + s + + ", using default " + sessionTimeoutMillis, e); + } + } } public static ConsoleProxyServerFactory getHttpServerFactory() { @@ -379,7 +394,7 @@ public static void start(Properties conf) { LOGGER.info("HTTP command port is disabled"); } - ConsoleProxyGCThread cthread = new ConsoleProxyGCThread(connectionMap, removedSessionsSet); + ConsoleProxyGCThread cthread = new ConsoleProxyGCThread(connectionMap, removedSessionsSet /*, sessionTimeoutMillis */); cthread.setName("Console Proxy GC Thread"); cthread.start(); } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyGCThread.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyGCThread.java index 0e8f576cf6db..c8225de6ed4d 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyGCThread.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyGCThread.java @@ -34,7 +34,7 @@ public class ConsoleProxyGCThread extends Thread { protected Logger logger = LogManager.getLogger(ConsoleProxyGCThread.class); - private final static int MAX_SESSION_IDLE_SECONDS = 180; + private final static int DEFAULT_MAX_SESSION_IDLE_SECONDS = 180; private final Map connMap; private final Set removedSessionsSet; @@ -45,6 +45,13 @@ public ConsoleProxyGCThread(Map connMap, Set this.removedSessionsSet = removedSet; } + private int getMaxSessionIdleSeconds() { + if (ConsoleProxy.sessionTimeoutMillis <= 0) { + return DEFAULT_MAX_SESSION_IDLE_SECONDS; + } + return ConsoleProxy.sessionTimeoutMillis / 1000; + } + private void cleanupLogging() { if (lastLogScan != 0 && System.currentTimeMillis() - lastLogScan < 3600000) return; @@ -92,7 +99,7 @@ public void run() { } long seconds_unused = (System.currentTimeMillis() - client.getClientLastFrontEndActivityTime()) / 1000; - if (seconds_unused < MAX_SESSION_IDLE_SECONDS) { + if (seconds_unused < getMaxSessionIdleSeconds()) { continue; } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVNCHandler.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVNCHandler.java index a148b988e40d..adcd23e8e6ac 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVNCHandler.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVNCHandler.java @@ -125,6 +125,10 @@ public void onConnect(final Session session) throws IOException, InterruptedExce } try { + session.setIdleTimeout(ConsoleProxy.sessionTimeoutMillis); + logger.debug("Set noVNC WebSocket idle timeout to {} ms for session UUID: {}.", + ConsoleProxy.sessionTimeoutMillis, sessionUuid); + ConsoleProxyClientParam param = new ConsoleProxyClientParam(); param.setClientHostAddress(host); param.setClientHostPort(port); @@ -185,12 +189,21 @@ public void onClose(Session session, int statusCode, String reason) throws IOExc @OnWebSocketFrame public void onFrame(Frame f) throws IOException { + if (viewer == null) { + logger.warn("Ignoring WebSocket frame because viewer is not initialized yet."); + return; + } logger.trace("Sending client [ID: {}] frame of {} bytes.", viewer.getClientId(), f.getPayloadLength()); viewer.sendClientFrame(f); } @OnWebSocketError public void onError(Throwable cause) { - logger.error("Error on WebSocket [client ID: {}, session UUID: {}].", cause, viewer.getClientId(), viewer.getSessionUuid()); + if (viewer != null) { + logger.error("Error on WebSocket [client ID: {}, session UUID: {}].", + viewer.getClientId(), viewer.getSessionUuid(), cause); + } else { + logger.error("Error on WebSocket before viewer initialization.", cause); + } } }