GUACAMOLE-622: Require guac_terminal_start() to be invoked before the terminal will render frames or accept user input.

This commit is contained in:
Michael Jumper 2018-08-30 10:01:41 -07:00
parent 332e187813
commit 61a51df1b2
2 changed files with 54 additions and 4 deletions

View File

@ -596,6 +596,7 @@ guac_terminal* guac_terminal_create(guac_client* client,
available_width = 0; available_width = 0;
guac_terminal* term = malloc(sizeof(guac_terminal)); guac_terminal* term = malloc(sizeof(guac_terminal));
term->started = false;
term->client = client; term->client = client;
term->upload_path_handler = NULL; term->upload_path_handler = NULL;
term->file_download_handler = NULL; term->file_download_handler = NULL;
@ -723,6 +724,11 @@ guac_terminal* guac_terminal_create(guac_client* client,
} }
void guac_terminal_start(guac_terminal* term) {
term->started = true;
guac_terminal_notify(term);
}
void guac_terminal_stop(guac_terminal* term) { void guac_terminal_stop(guac_terminal* term) {
/* Close input pipe and set fds to invalid */ /* Close input pipe and set fds to invalid */
@ -851,11 +857,13 @@ wait_complete:
int guac_terminal_render_frame(guac_terminal* terminal) { int guac_terminal_render_frame(guac_terminal* terminal) {
guac_client* client = terminal->client;
int wait_result; int wait_result;
/* Wait for data to be available */ /* Wait for data to be available */
wait_result = guac_terminal_wait(terminal, 1000); wait_result = guac_terminal_wait(terminal, 1000);
if (wait_result) { if (wait_result || !terminal->started) {
guac_timestamp frame_start = guac_timestamp_current(); guac_timestamp frame_start = guac_timestamp_current();
@ -867,13 +875,14 @@ int guac_terminal_render_frame(guac_terminal* terminal) {
- frame_end; - frame_end;
/* Wait again if frame remaining */ /* Wait again if frame remaining */
if (frame_remaining > 0) if (frame_remaining > 0 || !terminal->started)
wait_result = guac_terminal_wait(terminal, wait_result = guac_terminal_wait(terminal,
GUAC_TERMINAL_FRAME_TIMEOUT); GUAC_TERMINAL_FRAME_TIMEOUT);
else else
break; break;
} while (wait_result > 0); } while (client->state == GUAC_CLIENT_RUNNING
&& (wait_result > 0 || !terminal->started));
/* Flush terminal */ /* Flush terminal */
guac_terminal_lock(terminal); guac_terminal_lock(terminal);
@ -1672,6 +1681,13 @@ int guac_terminal_send_string(guac_terminal* term, const char* data) {
static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) { static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) {
/* Ignore user input if terminal is not started */
if (!term->started) {
guac_client_log(term->client, GUAC_LOG_DEBUG, "Ignoring user input "
"while terminal has not yet started.");
return 0;
}
/* Hide mouse cursor if not already hidden */ /* Hide mouse cursor if not already hidden */
if (term->current_cursor != GUAC_TERMINAL_CURSOR_BLANK) { if (term->current_cursor != GUAC_TERMINAL_CURSOR_BLANK) {
term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK; term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK;
@ -1845,6 +1861,13 @@ int guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) {
static int __guac_terminal_send_mouse(guac_terminal* term, guac_user* user, static int __guac_terminal_send_mouse(guac_terminal* term, guac_user* user,
int x, int y, int mask) { int x, int y, int mask) {
/* Ignore user input if terminal is not started */
if (!term->started) {
guac_client_log(term->client, GUAC_LOG_DEBUG, "Ignoring user input "
"while terminal has not yet started.");
return 0;
}
/* Determine which buttons were just released and pressed */ /* Determine which buttons were just released and pressed */
int released_mask = term->mouse_mask & ~mask; int released_mask = term->mouse_mask & ~mask;
int pressed_mask = ~term->mouse_mask & mask; int pressed_mask = ~term->mouse_mask & mask;

View File

@ -171,6 +171,16 @@ struct guac_terminal {
*/ */
guac_client* client; guac_client* client;
/**
* Whether user input should be handled and this terminal should render
* frames. Initially, this will be false, user input will be ignored, and
* rendering of frames will be withheld until guac_terminal_start() has
* been invoked. The data within frames will still be rendered, and text
* data received will still be handled, however actual frame boundaries
* will not be sent.
*/
bool started;
/** /**
* The terminal render thread. * The terminal render thread.
*/ */
@ -526,7 +536,13 @@ struct guac_terminal {
/** /**
* Creates a new guac_terminal, having the given width and height, and * Creates a new guac_terminal, having the given width and height, and
* rendering to the given client. * rendering to the given client. As failover mechanisms and the Guacamole
* client implementation typically use the receipt of a "sync" message to
* denote successful connection, rendering of frames (sending of "sync") will
* be withheld until guac_terminal_start() is called, and user input will be
* ignored. The guac_terminal_start() function should be invoked only after
* either the underlying connection has truly succeeded, or until visible
* terminal output or user input is required.
* *
* @param client * @param client
* The client to which the terminal will be rendered. * The client to which the terminal will be rendered.
@ -604,6 +620,17 @@ int guac_terminal_render_frame(guac_terminal* terminal);
*/ */
int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size); int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size);
/**
* Notifies the terminal that rendering should begin and that user input should
* now be accepted. This function must be invoked following terminal creation
* for the end of frames to be signalled with "sync" messages. Until this
* function is invoked, "sync" messages will be withheld.
*
* @param term
* The terminal to start.
*/
void guac_terminal_start(guac_terminal* term);
/** /**
* Manually stop the terminal to forcibly unblock any pending reads/writes, * Manually stop the terminal to forcibly unblock any pending reads/writes,
* e.g. forcing guac_terminal_read_stdin() to return and cease all terminal I/O. * e.g. forcing guac_terminal_read_stdin() to return and cease all terminal I/O.