From 52c8683bcf35a74edd1bcefbe5005746821df36c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 2 Sep 2021 16:53:55 -0700 Subject: [PATCH] GUACAMOLE-377: Add protocol-level support for reporting remote frame statistics. --- src/libguac/client.c | 8 +++++-- src/libguac/guacamole/client.h | 39 ++++++++++++++++++++++++++++---- src/libguac/guacamole/protocol.h | 19 ++++++++++++---- src/libguac/protocol.c | 5 +++- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/libguac/client.c b/src/libguac/client.c index 9738c0c2..80ba1741 100644 --- a/src/libguac/client.c +++ b/src/libguac/client.c @@ -413,15 +413,19 @@ void* guac_client_for_user(guac_client* client, guac_user* user, } int guac_client_end_frame(guac_client* client) { + return guac_client_end_multiple_frames(client, 0); +} + +int guac_client_end_multiple_frames(guac_client* client, int frames) { /* Update and send timestamp */ client->last_sent_timestamp = guac_timestamp_current(); /* Log received timestamp and calculated lag (at TRACE level only) */ guac_client_log(client, GUAC_LOG_TRACE, "Server completed " - "frame %" PRIu64 "ms.", client->last_sent_timestamp); + "frame %" PRIu64 "ms (%i logical frames)", client->last_sent_timestamp, frames); - return guac_protocol_send_sync(client->socket, client->last_sent_timestamp); + return guac_protocol_send_sync(client->socket, client->last_sent_timestamp, frames); } diff --git a/src/libguac/guacamole/client.h b/src/libguac/guacamole/client.h index 4ffe5cf4..b94f8418 100644 --- a/src/libguac/guacamole/client.h +++ b/src/libguac/guacamole/client.h @@ -509,18 +509,47 @@ void* guac_client_for_user(guac_client* client, guac_user* user, guac_user_callback* callback, void* data); /** - * Marks the end of the current frame by sending a "sync" instruction to - * all connected users. This instruction will contain the current timestamp. - * The last_sent_timestamp member of guac_client will be updated accordingly. + * Marks the end of the current frame by sending a "sync" instruction to all + * connected users, where the number of input frames that were considered in + * creating this frame is either unknown or inapplicable. This instruction will + * contain the current timestamp. The last_sent_timestamp member of guac_client + * will be updated accordingly. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param client The guac_client which has finished a frame. - * @return Zero on success, non-zero on error. + * @param client + * The guac_client which has finished a frame. + * + * @return + * Zero on success, non-zero on error. */ int guac_client_end_frame(guac_client* client); +/** + * Marks the end of the current frame by sending a "sync" instruction to all + * connected users, where that frame may combine or otherwise represent the + * changes of an arbitrary number of input frames. This instruction will + * contain the current timestamp, as well as the number of frames that were + * considered in creating that frame. The last_sent_timestamp member of + * guac_client will be updated accordingly. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param client + * The guac_client which has finished a frame. + * + * @param frames + * The number of distinct frames that were considered or combined when + * generating the current frame, or zero if the boundaries of relevant + * frames are unknown. + * + * @return + * Zero on success, non-zero on error. + */ +int guac_client_end_multiple_frames(guac_client* client, int frames); + /** * Initializes the given guac_client using the initialization routine provided * by the plugin corresponding to the named protocol. This will automatically diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h index 362351c5..1d3c883e 100644 --- a/src/libguac/guacamole/protocol.h +++ b/src/libguac/guacamole/protocol.h @@ -363,11 +363,22 @@ int guac_protocol_send_select(guac_socket* socket, const char* protocol); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param socket The guac_socket connection to use. - * @param timestamp The current timestamp (in milliseconds). - * @return Zero on success, non-zero on error. + * @param socket + * The guac_socket connection to use. + * + * @param timestamp + * The current timestamp (in milliseconds). + * + * @param frames + * The number of distinct frames that were considered or combined when + * generating the frame terminated by this instruction, or zero if the + * boundaries of relevant frames are unknown. + * + * @return + * Zero on success, non-zero on error. */ -int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp, + int frames); /* OBJECT INSTRUCTIONS */ diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c index 1c53c200..b7cd5e41 100644 --- a/src/libguac/protocol.c +++ b/src/libguac/protocol.c @@ -1181,7 +1181,8 @@ int guac_protocol_send_start(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp, + int frames) { int ret_val; @@ -1189,6 +1190,8 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { ret_val = guac_socket_write_string(socket, "4.sync,") || __guac_socket_write_length_int(socket, timestamp) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, frames) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket);