diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index b40e582c..a6316ef4 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -37,7 +37,7 @@ * milliseconds. If the server is silent for at least this amount of time, the * frame will be considered finished. */ -#define GUAC_RDP_FRAME_TIMEOUT 10 +#define GUAC_RDP_FRAME_TIMEOUT 0 /** * The amount of time to wait for a new message from the RDP server when diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 221c2bdc..47ec75c3 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -829,9 +829,10 @@ void* guac_rdp_client_thread(void* data) { /* Connection complete */ rdp_client->rdp_inst = rdp_inst; - rdpChannels* channels = rdp_inst->context->channels; + guac_timestamp last_frame_end = guac_timestamp_current(); + /* Handle messages from RDP server while client is running */ while (client->state == GUAC_CLIENT_RUNNING) { @@ -845,72 +846,88 @@ void* guac_rdp_client_thread(void* data) { /* Wait for data and construct a reasonable frame */ int wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_START_TIMEOUT); - guac_timestamp frame_start = guac_timestamp_current(); - while (wait_result > 0) { + if (wait_result > 0) { - guac_timestamp frame_end; - int frame_remaining; + int processing_lag = guac_client_get_processing_lag(client); + guac_timestamp frame_start = guac_timestamp_current(); - pthread_mutex_lock(&(rdp_client->rdp_lock)); + /* Read server messages until frame is built */ + do { - /* Check the libfreerdp fds */ - if (!freerdp_check_fds(rdp_inst)) { - guac_client_log(client, GUAC_LOG_DEBUG, - "Error handling RDP file descriptors"); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - return NULL; - } + guac_timestamp frame_end; + int frame_remaining; - /* Check channel fds */ - if (!freerdp_channels_check_fds(channels, rdp_inst)) { - guac_client_log(client, GUAC_LOG_DEBUG, - "Error handling RDP channel file descriptors"); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - return NULL; - } + pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Check for channel events */ - wMessage* event = freerdp_channels_pop_event(channels); - if (event) { + /* Check the libfreerdp fds */ + if (!freerdp_check_fds(rdp_inst)) { + guac_client_log(client, GUAC_LOG_DEBUG, + "Error handling RDP file descriptors"); + pthread_mutex_unlock(&(rdp_client->rdp_lock)); + return NULL; + } - /* Handle channel events (clipboard and RAIL) */ + /* Check channel fds */ + if (!freerdp_channels_check_fds(channels, rdp_inst)) { + guac_client_log(client, GUAC_LOG_DEBUG, + "Error handling RDP channel file descriptors"); + pthread_mutex_unlock(&(rdp_client->rdp_lock)); + return NULL; + } + + /* Check for channel events */ + wMessage* event = freerdp_channels_pop_event(channels); + if (event) { + + /* Handle channel events (clipboard and RAIL) */ #ifdef LEGACY_EVENT - if (event->event_class == CliprdrChannel_Class) - guac_rdp_process_cliprdr_event(client, event); - else if (event->event_class == RailChannel_Class) - guac_rdp_process_rail_event(client, event); + if (event->event_class == CliprdrChannel_Class) + guac_rdp_process_cliprdr_event(client, event); + else if (event->event_class == RailChannel_Class) + guac_rdp_process_rail_event(client, event); #else - if (GetMessageClass(event->id) == CliprdrChannel_Class) - guac_rdp_process_cliprdr_event(client, event); - else if (GetMessageClass(event->id) == RailChannel_Class) - guac_rdp_process_rail_event(client, event); + if (GetMessageClass(event->id) == CliprdrChannel_Class) + guac_rdp_process_cliprdr_event(client, event); + else if (GetMessageClass(event->id) == RailChannel_Class) + guac_rdp_process_rail_event(client, event); #endif - freerdp_event_free(event); + freerdp_event_free(event); - } + } + + /* Handle RDP disconnect */ + if (freerdp_shall_disconnect(rdp_inst)) { + guac_client_log(client, GUAC_LOG_INFO, + "RDP server closed connection"); + pthread_mutex_unlock(&(rdp_client->rdp_lock)); + return NULL; + } - /* Handle RDP disconnect */ - if (freerdp_shall_disconnect(rdp_inst)) { - guac_client_log(client, GUAC_LOG_INFO, - "RDP server closed connection"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); - return NULL; - } - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + /* Calculate time remaining in frame */ + frame_end = guac_timestamp_current(); + frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION + - frame_end; - /* Calculate time remaining in frame */ - frame_end = guac_timestamp_current(); - frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION - frame_end; + /* Calculate time that client needs to catch up */ + int time_elapsed = frame_end - last_frame_end; + int required_wait = processing_lag - time_elapsed; - /* Wait again if frame remaining */ - if (frame_remaining > 0) - wait_result = rdp_guac_client_wait_for_messages(client, - GUAC_RDP_FRAME_TIMEOUT*1000); - else - break; + /* Increase the duration of this frame if client is lagging */ + if (required_wait > GUAC_RDP_FRAME_TIMEOUT) + wait_result = rdp_guac_client_wait_for_messages(client, + required_wait*1000); + /* Wait again if frame remaining */ + else if (frame_remaining > 0) + wait_result = rdp_guac_client_wait_for_messages(client, + GUAC_RDP_FRAME_TIMEOUT*1000); + else + break; + + } while (wait_result > 0); } /* If an error occurred, fail */ @@ -923,6 +940,9 @@ void* guac_rdp_client_thread(void* data) { guac_client_end_frame(client); guac_socket_flush(client->socket); + /* Record end of frame */ + last_frame_end = guac_timestamp_current(); + } guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected"); diff --git a/src/protocols/vnc/client.h b/src/protocols/vnc/client.h index 316d3883..c3686396 100644 --- a/src/protocols/vnc/client.h +++ b/src/protocols/vnc/client.h @@ -36,7 +36,7 @@ * milliseconds. If the server is silent for at least this amount of time, the * frame will be considered finished. */ -#define GUAC_VNC_FRAME_TIMEOUT 10 +#define GUAC_VNC_FRAME_TIMEOUT 0 /** * The amount of time to wait for a new message from the VNC server when diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 7520d2e9..2467f430 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -345,6 +345,7 @@ void* guac_vnc_client_thread(void* data) { GUAC_VNC_FRAME_START_TIMEOUT); if (wait_result > 0) { + int processing_lag = guac_client_get_processing_lag(client); guac_timestamp frame_start = guac_timestamp_current(); /* Read server messages until frame is built */ @@ -366,8 +367,17 @@ void* guac_vnc_client_thread(void* data) { frame_remaining = frame_start + GUAC_VNC_FRAME_DURATION - frame_end; + /* Calculate time that client needs to catch up */ + int time_elapsed = frame_end - last_frame_end; + int required_wait = processing_lag - time_elapsed; + + /* Increase the duration of this frame if client is lagging */ + if (required_wait > GUAC_VNC_FRAME_TIMEOUT) + wait_result = guac_vnc_wait_for_messages(rfb_client, + required_wait*1000); + /* Wait again if frame remaining */ - if (frame_remaining > 0) + else if (frame_remaining > 0) wait_result = guac_vnc_wait_for_messages(rfb_client, GUAC_VNC_FRAME_TIMEOUT*1000); else @@ -386,17 +396,8 @@ void* guac_vnc_client_thread(void* data) { guac_client_end_frame(client); guac_socket_flush(client->socket); - /* Calculate time since previous frame ended */ - int current_frame_end = guac_timestamp_current(); - int time_elapsed = current_frame_end - last_frame_end; - int processing_lag = guac_client_get_processing_lag(client); - - /* Insert delays as necessary to allow client to catch up */ - if (time_elapsed < processing_lag) - guac_timestamp_msleep(processing_lag - time_elapsed); - /* Record end of frame */ - last_frame_end = current_frame_end; + last_frame_end = guac_timestamp_current(); }