GUAC-779: Synchronize access to shared libssh2 handles.

This commit is contained in:
Michael Jumper 2014-07-21 11:15:55 -07:00
parent d608b3a30b
commit be9c56f9a3
3 changed files with 28 additions and 3 deletions

View File

@ -137,6 +137,11 @@ typedef struct ssh_guac_client_data {
*/ */
LIBSSH2_CHANNEL* term_channel; LIBSSH2_CHANNEL* term_channel;
/**
* Lock dictating access to the SSH terminal channel.
*/
pthread_mutex_t term_channel_lock;
/** /**
* The terminal which will render all output from the SSH client. * The terminal which will render all output from the SSH client.
*/ */

View File

@ -74,9 +74,12 @@ int ssh_guac_client_size_handler(guac_client* client, int width, int height) {
guac_terminal_resize(terminal, width, height); guac_terminal_resize(terminal, width, height);
/* Update SSH pty size if connected */ /* Update SSH pty size if connected */
if (guac_client_data->term_channel != NULL) if (guac_client_data->term_channel != NULL) {
pthread_mutex_lock(&(guac_client_data->term_channel_lock));
libssh2_channel_request_pty_size(guac_client_data->term_channel, libssh2_channel_request_pty_size(guac_client_data->term_channel,
terminal->term_width, terminal->term_height); terminal->term_width, terminal->term_height);
pthread_mutex_unlock(&(guac_client_data->term_channel_lock));
}
return 0; return 0;
} }

View File

@ -64,8 +64,11 @@ void* ssh_input_thread(void* data) {
int bytes_read; int bytes_read;
/* Write all data read */ /* Write all data read */
while ((bytes_read = guac_terminal_read_stdin(client_data->term, buffer, sizeof(buffer))) > 0) while ((bytes_read = guac_terminal_read_stdin(client_data->term, buffer, sizeof(buffer))) > 0) {
pthread_mutex_lock(&(client_data->term_channel_lock));
libssh2_channel_write(client_data->term_channel, buffer, bytes_read); libssh2_channel_write(client_data->term_channel, buffer, bytes_read);
pthread_mutex_unlock(&(client_data->term_channel_lock));
}
return NULL; return NULL;
@ -474,6 +477,8 @@ void* ssh_client_thread(void* data) {
/* Logged in */ /* Logged in */
guac_client_log_info(client, "SSH connection successful."); guac_client_log_info(client, "SSH connection successful.");
pthread_mutex_init(&client_data->term_channel_lock, NULL);
/* Start input thread */ /* Start input thread */
if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
@ -485,15 +490,25 @@ void* ssh_client_thread(void* data) {
/* While data available, write to terminal */ /* While data available, write to terminal */
bytes_read = 0; bytes_read = 0;
while (!libssh2_channel_eof(client_data->term_channel)) { for (;;) {
/* Track total amount of data read */ /* Track total amount of data read */
int total_read = 0; int total_read = 0;
pthread_mutex_lock(&(client_data->term_channel_lock));
/* Stop reading at EOF */
if (libssh2_channel_eof(client_data->term_channel)) {
pthread_mutex_unlock(&(client_data->term_channel_lock));
break;
}
/* Read terminal data */ /* Read terminal data */
bytes_read = libssh2_channel_read(client_data->term_channel, bytes_read = libssh2_channel_read(client_data->term_channel,
buffer, sizeof(buffer)); buffer, sizeof(buffer));
pthread_mutex_unlock(&(client_data->term_channel_lock));
/* Attempt to write data received. Exit on failure. */ /* Attempt to write data received. Exit on failure. */
if (bytes_read > 0) { if (bytes_read > 0) {
int written = guac_terminal_write_stdout(client_data->term, buffer, bytes_read); int written = guac_terminal_write_stdout(client_data->term, buffer, bytes_read);
@ -540,6 +555,8 @@ void* ssh_client_thread(void* data) {
pthread_join(input_thread, NULL); pthread_join(input_thread, NULL);
__openssl_free_locks(CRYPTO_num_locks()); __openssl_free_locks(CRYPTO_num_locks());
pthread_mutex_destroy(&client_data->term_channel_lock);
guac_client_log_info(client, "SSH connection ended."); guac_client_log_info(client, "SSH connection ended.");
return NULL; return NULL;