From 6e8d28925d0628ca915da310562a93d738794a70 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2025 12:55:23 -0800 Subject: [PATCH 1/4] GUACAMOLE-377: Always update to latest dirty rect state, including if that state is empty. --- src/libguac/display-flush.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libguac/display-flush.c b/src/libguac/display-flush.c index 44436168..181c19e7 100644 --- a/src/libguac/display-flush.c +++ b/src/libguac/display-flush.c @@ -176,6 +176,12 @@ static int PFW_LFW_guac_display_frame_complete(guac_display* display) { } + /* Even if nothing has changed in the pending frame, we have to at + * least flush that fact to the last frame (otherwise, the last frame + * may contain stale dirty rects) */ + else + current->last_frame.dirty = (guac_rect) { 0 }; + /* Commit any change in layer size */ if (current->pending_frame.width != current->last_frame.width || current->pending_frame.height != current->last_frame.height) { From bb0c5b634d02583e38baf85c272f0dd3879da8cb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2025 13:03:56 -0800 Subject: [PATCH 2/4] GUACAMOLE-377: Avoid flushing empty frames purely for updated mouse positions. --- src/libguac/display-flush.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libguac/display-flush.c b/src/libguac/display-flush.c index 181c19e7..10f9667c 100644 --- a/src/libguac/display-flush.c +++ b/src/libguac/display-flush.c @@ -278,7 +278,9 @@ static int PFW_LFW_guac_display_frame_complete(guac_display* display) { display->last_frame.cursor_mask = display->pending_frame.cursor_mask; guac_client_foreach_user(client, LFR_guac_display_broadcast_cursor_state, display); - retval = 1; + /* NOTE: We DO NOT set retval here, as flushing a frame due purely to + * mouse position changes can cause slowdowns apparently from the sheer + * quantity of frames */ } From 6a68177374b61d5743719c32a2842cfbd9d99045 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Jan 2025 10:05:10 -0800 Subject: [PATCH 3/4] GUACAMOLE-377: Do NOT send extra frames just to allow copies to move forward. This seems to induce latency and possibly negatively affects tracking of client-side processing lag. --- src/libguac/display-worker.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libguac/display-worker.c b/src/libguac/display-worker.c index 39649f3f..a9bfb3be 100644 --- a/src/libguac/display-worker.c +++ b/src/libguac/display-worker.c @@ -454,10 +454,6 @@ void* guac_display_worker_thread(void* data) { } - /* Include an additional frame boundary to allow the client to also move forward with committing - * changes to the backing buffer while the server is receiving and preparing the next frame */ - guac_client_end_multiple_frames(client, 0); - /* This is now absolutely everything for the current frame, * and it's safe to flush any outstanding data */ guac_socket_flush(client->socket); From 91b31a288aa92fad70c0d451a448e0303bee3547 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Jan 2025 10:07:44 -0800 Subject: [PATCH 4/4] GUACAMOLE-377: Set TCP_NODELAY on socket to avoid unnecessary latency. --- src/guacd/daemon.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/guacd/daemon.c b/src/guacd/daemon.c index 8bf81482..378faffd 100644 --- a/src/guacd/daemon.c +++ b/src/guacd/daemon.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -537,6 +538,12 @@ int main(int argc, char* argv[]) { continue; } + /* Set TCP_NODELAY to avoid any latency that would otherwise be added by the OS' + * networking stack and Nagle's algorithm */ + const int SO_TRUE = 1; + setsockopt(connected_socket_fd, IPPROTO_TCP, TCP_NODELAY, + (const void*) &SO_TRUE, sizeof(SO_TRUE)); + /* Create parameters for connection thread */ guacd_connection_thread_params* params = guac_mem_alloc(sizeof(guacd_connection_thread_params)); if (params == NULL) {