GUACAMOLE-610: Allow scrollback size to be specified for SSH and telnet.

This commit is contained in:
Michael Jumper 2018-08-13 00:48:46 -07:00
parent 6a576f0121
commit 0e6d549a40
8 changed files with 158 additions and 19 deletions

View File

@ -59,6 +59,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
"server-alive-interval",
"backspace",
"terminal-type",
"scrollback",
NULL
};
@ -232,6 +233,11 @@ enum SSH_ARGS_IDX {
*/
IDX_TERMINAL_TYPE,
/**
* The maximum size of the scrollback buffer in rows.
*/
IDX_SCROLLBACK,
SSH_ARGS_COUNT
};
@ -274,6 +280,11 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
IDX_PASSPHRASE, NULL);
/* Read maximum scrollback size */
settings->max_scrollback =
guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv,
IDX_SCROLLBACK, GUAC_SSH_DEFAULT_MAX_SCROLLBACK);
/* Read font name */
settings->font_name =
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,

View File

@ -58,6 +58,11 @@
*/
#define GUAC_SSH_DEFAULT_POLL_TIMEOUT 1000
/**
* The default maximum scrollback size in rows.
*/
#define GUAC_SSH_DEFAULT_MAX_SCROLLBACK 1000
/**
* Settings for the SSH connection. The values for this structure are parsed
* from the arguments given during the Guacamole protocol handshake using the
@ -115,6 +120,11 @@ typedef struct guac_ssh_settings {
*/
char* command;
/**
* The maximum size of the scrollback buffer in rows.
*/
int max_scrollback;
/**
* The name of the font to use for display rendering.
*/

View File

@ -207,7 +207,7 @@ void* ssh_client_thread(void* data) {
/* Create terminal */
ssh_client->term = guac_terminal_create(client, ssh_client->clipboard,
settings->font_name, settings->font_size,
settings->max_scrollback, settings->font_name, settings->font_size,
settings->resolution, settings->width, settings->height,
settings->color_scheme, settings->backspace);

View File

@ -52,6 +52,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = {
"read-only",
"backspace",
"terminal-type",
"scrollback",
NULL
};
@ -190,6 +191,11 @@ enum TELNET_ARGS_IDX {
*/
IDX_TERMINAL_TYPE,
/**
* The maximum size of the scrollback buffer in rows.
*/
IDX_SCROLLBACK,
TELNET_ARGS_COUNT
};
@ -274,6 +280,11 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_READ_ONLY, false);
/* Read maximum scrollback size */
settings->max_scrollback =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_SCROLLBACK, GUAC_TELNET_DEFAULT_MAX_SCROLLBACK);
/* Read font name */
settings->font_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,

View File

@ -67,6 +67,11 @@
*/
#define GUAC_TELNET_DEFAULT_PASSWORD_REGEX "[Pp]assword:"
/**
* The default maximum scrollback size in rows.
*/
#define GUAC_TELNET_DEFAULT_MAX_SCROLLBACK 1000
/**
* Settings for the telnet connection. The values for this structure are parsed
* from the arguments given during the Guacamole protocol handshake using the
@ -117,6 +122,11 @@ typedef struct guac_telnet_settings {
*/
bool read_only;
/**
* The maximum size of the scrollback buffer in rows.
*/
int max_scrollback;
/**
* The name of the font to use for display rendering.
*/

View File

@ -479,7 +479,7 @@ void* guac_telnet_client_thread(void* data) {
/* Create terminal */
telnet_client->term = guac_terminal_create(client,
telnet_client->clipboard,
settings->font_name, settings->font_size,
settings->max_scrollback, settings->font_name, settings->font_size,
settings->resolution, settings->width, settings->height,
settings->color_scheme, settings->backspace);

View File

@ -149,6 +149,59 @@ static void __guac_terminal_force_break(guac_terminal* terminal, int row, int ed
}
/**
* Returns the number of rows available within the terminal buffer, taking
* changes to the desired scrollback size into account. Regardless of the
* true buffer length, only the number of rows that should be made available
* will be returned.
*
* @param term
* The terminal whose effective buffer length should be retrieved.
*
* @return
* The number of rows effectively available within the terminal buffer,
* taking changes to the desired scrollback size into account.
*/
static int guac_terminal_effective_buffer_length(guac_terminal* term) {
int scrollback = term->requested_scrollback;
/* Limit available scrollback to defined maximum */
if (scrollback > term->max_scrollback)
scrollback = term->max_scrollback;
/* There must always be at least enough scrollback to cover the visible
* terminal display */
else if (scrollback < term->term_height)
scrollback = term->term_height;
/* If the buffer contains more rows than requested, pretend it only
* contains the requested number of rows */
int effective_length = term->buffer->length;
if (effective_length > scrollback)
effective_length = scrollback;
return effective_length;
}
/**
* Returns the number of rows within the buffer of the given terminal which are
* not currently displayed on screen. Adjustments to the desired scrollback
* size are taken into account, and rows which are within the buffer but
* unavailable due to being outside the desired scrollback range are ignored.
*
* @param term
* The terminal whose off-screen row count should be determined.
*
* @return
* The number of rows within the buffer which are not currently displayed
* on screen.
*/
static int guac_terminal_available_scroll(guac_terminal* term) {
return guac_terminal_effective_buffer_length(term) - term->term_height;
}
void guac_terminal_reset(guac_terminal* term) {
int row;
@ -171,7 +224,7 @@ void guac_terminal_reset(guac_terminal* term) {
term->scroll_offset = 0;
/* Reset scrollbar bounds */
guac_terminal_scrollbar_set_bounds(term->scrollbar, term->term_height - term->buffer->length, 0);
guac_terminal_scrollbar_set_bounds(term->scrollbar, 0, 0);
guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset);
/* Reset flags */
@ -507,7 +560,7 @@ static void guac_terminal_parse_color_scheme(guac_client* client,
}
guac_terminal* guac_terminal_create(guac_client* client,
guac_common_clipboard* clipboard,
guac_common_clipboard* clipboard, int max_scrollback,
const char* font_name, int font_size, int dpi,
int width, int height, const char* color_scheme,
const int backspace) {
@ -565,8 +618,19 @@ guac_terminal* guac_terminal_create(guac_client* client,
pthread_cond_init(&(term->modified_cond), NULL);
pthread_mutex_init(&(term->modified_lock), NULL);
/* Maximum and requested scrollback are initially the same */
term->max_scrollback = max_scrollback;
term->requested_scrollback = max_scrollback;
/* Allocate enough space for maximum scrollback, bumping up internal
* storage as necessary to allow screen to be resized to maximum height */
int initial_scrollback = max_scrollback;
if (initial_scrollback < GUAC_TERMINAL_MAX_ROWS)
initial_scrollback = GUAC_TERMINAL_MAX_ROWS;
/* Init buffer */
term->buffer = guac_terminal_buffer_alloc(1000, &default_char);
term->buffer = guac_terminal_buffer_alloc(initial_scrollback,
&default_char);
/* Init display */
term->display = guac_terminal_display_alloc(client,
@ -1031,7 +1095,8 @@ int guac_terminal_scroll_up(guac_terminal* term,
term->buffer->length = term->buffer->available;
/* Reset scrollbar bounds */
guac_terminal_scrollbar_set_bounds(term->scrollbar, term->term_height - term->buffer->length, 0);
guac_terminal_scrollbar_set_bounds(term->scrollbar,
-guac_terminal_available_scroll(term), 0);
/* Update cursor location if within region */
if (term->visible_cursor_row >= start_row &&
@ -1241,8 +1306,9 @@ void guac_terminal_scroll_display_up(guac_terminal* terminal,
int row, column;
/* Limit scroll amount by size of scrollback buffer */
if (terminal->scroll_offset + scroll_amount > terminal->buffer->length - terminal->term_height)
scroll_amount = terminal->buffer->length - terminal->scroll_offset - terminal->term_height;
int available_scroll = guac_terminal_available_scroll(terminal);
if (terminal->scroll_offset + scroll_amount > available_scroll)
scroll_amount = available_scroll - terminal->scroll_offset;
/* If not scrolling at all, don't bother trying */
if (scroll_amount <= 0)
@ -1404,7 +1470,7 @@ static void __guac_terminal_resize(guac_terminal* term, int width, int height) {
int shift_amount;
/* Get number of rows actually occupying terminal space */
int used_height = term->buffer->length;
int used_height = guac_terminal_effective_buffer_length(term);
if (used_height > term->term_height)
used_height = term->term_height;
@ -1440,16 +1506,15 @@ static void __guac_terminal_resize(guac_terminal* term, int width, int height) {
if (height > term->term_height) {
/* If undisplayed rows exist in the buffer, shift them into view */
if (term->term_height < term->buffer->length) {
int available_scroll = guac_terminal_available_scroll(term);
if (available_scroll > 0) {
/* If the new terminal bottom reveals N rows, shift down N rows */
int shift_amount = height - term->term_height;
/* The maximum amount we can shift is the number of undisplayed rows */
int max_shift = term->buffer->length - term->term_height;
if (shift_amount > max_shift)
shift_amount = max_shift;
if (shift_amount > available_scroll)
shift_amount = available_scroll;
/* Update buffer top and cursor row based on shift */
term->buffer->top -= shift_amount;
@ -1544,10 +1609,6 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) {
/* Resize default layer to given pixel dimensions */
guac_terminal_repaint_default_layer(terminal, client->socket);
/* Notify scrollbar of resize */
guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height, rows);
guac_terminal_scrollbar_set_bounds(terminal->scrollbar, rows - terminal->buffer->length, 0);
/* Resize terminal if row/column dimensions have changed */
if (columns != terminal->term_width || rows != terminal->term_height) {
@ -1562,6 +1623,12 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) {
}
/* Notify scrollbar of resize */
guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height, rows);
guac_terminal_scrollbar_set_bounds(terminal->scrollbar,
-guac_terminal_available_scroll(terminal), 0);
/* Release terminal */
guac_terminal_unlock(terminal);

View File

@ -282,6 +282,26 @@ struct guac_terminal {
*/
int scroll_offset;
/**
* The maximum number of rows to allow within the terminal buffer. Note
* that while this value is traditionally referred to as the scrollback
* size, it actually encompasses both the display and the off-screen
* region. The terminal will ensure enough buffer space is allocated for
* the on-screen rows, even if this exceeds the defined maximum, however
* additional rows for off-screen data will only be available if the
* display is smaller than this value.
*/
int max_scrollback;
/**
* The number of rows that the user has requested be avalable within the
* terminal buffer. This value may be adjusted by the user while the
* terminal is running through console codes, and will adjust the number
* of rows available within the terminal buffer, subject to the maximum
* defined at terminal creation and stored within max_scrollback.
*/
int requested_scrollback;
/**
* The width of the terminal, in pixels.
*/
@ -518,6 +538,16 @@ struct guac_terminal {
* clipboard instructions. This clipboard will not be automatically
* freed when this terminal is freed.
*
* @param max_scrollback
* The maximum number of rows to allow within the scrollback buffer. The
* user may still alter the size of the scrollback buffer using terminal
* codes, however the size can never exceed the maximum size given here.
* Note that this space is shared with the display, with the scrollable
* area actually only containing the given number of rows less the number
* of rows currently displayed, and sufficient buffer space will always be
* allocated to represent the display area of the terminal regardless of
* the value given here.
*
* @param font_name
* The name of the font to use when rendering glyphs.
*
@ -550,7 +580,7 @@ struct guac_terminal {
* which renders all text to the given client.
*/
guac_terminal* guac_terminal_create(guac_client* client,
guac_common_clipboard* clipboard,
guac_common_clipboard* clipboard, int max_scrollback,
const char* font_name, int font_size, int dpi,
int width, int height, const char* color_scheme,
const int backspace);