From 59784769102e003627e7da6c3281bf727ee814b1 Mon Sep 17 00:00:00 2001 From: Stephen Schiffli Date: Tue, 6 Jan 2026 14:47:09 -0800 Subject: [PATCH] GUACAMOLE-1170: Support sized IntegerPool to maximize time between stream index reuse. --- .../src/main/webapp/modules/Client.js | 21 +++++++++++++++++-- .../src/main/webapp/modules/IntegerPool.js | 17 ++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/guacamole-common-js/src/main/webapp/modules/Client.js b/guacamole-common-js/src/main/webapp/modules/Client.js index 03dee3e1b..14dab6fd3 100644 --- a/guacamole-common-js/src/main/webapp/modules/Client.js +++ b/guacamole-common-js/src/main/webapp/modules/Client.js @@ -139,8 +139,25 @@ Guacamole.Client = function(tunnel) { */ var objects = []; - // Pool of available stream indices - var stream_indices = new Guacamole.IntegerPool(); + /** + * The maximum number of streams supported by any one guac_user. This must + * match GUAC_USER_MAX_STREAMS defined in guacamole-server's user.h to + * ensure we stay within the server's stream index limits. + * + * @private + * @constant + * @type {!number} + */ + var GUAC_USER_MAX_STREAMS = 512; + + /** + * Pool of available stream indices. Initialized with min_size set to + * GUAC_USER_MAX_STREAMS to delay index reuse. + * + * @private + * @type {!Guacamole.IntegerPool} + */ + var stream_indices = new Guacamole.IntegerPool(GUAC_USER_MAX_STREAMS); // Array of allocated output streams by index var output_streams = []; diff --git a/guacamole-common-js/src/main/webapp/modules/IntegerPool.js b/guacamole-common-js/src/main/webapp/modules/IntegerPool.js index 6916cab14..e82d341a8 100644 --- a/guacamole-common-js/src/main/webapp/modules/IntegerPool.js +++ b/guacamole-common-js/src/main/webapp/modules/IntegerPool.js @@ -22,9 +22,16 @@ var Guacamole = Guacamole || {}; /** * Integer pool which returns consistently increasing integers while integers * are in use, and previously-used integers when possible. - * @constructor + * + * When a minimum pool size is specified, new integers are preferred over reused + * integers until the minimum size is reached. + * + * @constructor + * @param {number} [min_size] + * The minimum number of integers which must have been returned before + * previously-used and freed integers are allowed to be returned. */ -Guacamole.IntegerPool = function() { +Guacamole.IntegerPool = function(min_size) { /** * Reference to this integer pool. @@ -51,14 +58,14 @@ Guacamole.IntegerPool = function() { /** * Returns the next available integer in the pool. If possible, a previously * used integer will be returned. - * + * * @return {!number} * The next available integer. */ this.next = function() { - // If free'd integers exist, return one of those - if (pool.length > 0) + // If free'd integers exist and we've allocated the minimum, reuse it + if (pool.length > 0 && (!min_size || guac_pool.next_int >= min_size)) return pool.shift(); // Otherwise, return a new integer