GUACAMOLE-377: Add protocol-level support for reporting remote frame statistics.

This commit is contained in:
Michael Jumper 2021-09-02 16:53:55 -07:00
parent c19eab9691
commit 52c8683bcf
4 changed files with 59 additions and 12 deletions

View File

@ -413,15 +413,19 @@ void* guac_client_for_user(guac_client* client, guac_user* user,
} }
int guac_client_end_frame(guac_client* client) { 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 */ /* Update and send timestamp */
client->last_sent_timestamp = guac_timestamp_current(); client->last_sent_timestamp = guac_timestamp_current();
/* Log received timestamp and calculated lag (at TRACE level only) */ /* Log received timestamp and calculated lag (at TRACE level only) */
guac_client_log(client, GUAC_LOG_TRACE, "Server completed " 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);
} }

View File

@ -509,18 +509,47 @@ void* guac_client_for_user(guac_client* client, guac_user* user,
guac_user_callback* callback, void* data); guac_user_callback* callback, void* data);
/** /**
* Marks the end of the current frame by sending a "sync" instruction to * Marks the end of the current frame by sending a "sync" instruction to all
* all connected users. This instruction will contain the current timestamp. * connected users, where the number of input frames that were considered in
* The last_sent_timestamp member of guac_client will be updated accordingly. * 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 * If an error occurs sending the instruction, a non-zero value is
* returned, and guac_error is set appropriately. * returned, and guac_error is set appropriately.
* *
* @param client The guac_client which has finished a frame. * @param client
* @return Zero on success, non-zero on error. * The guac_client which has finished a frame.
*
* @return
* Zero on success, non-zero on error.
*/ */
int guac_client_end_frame(guac_client* client); 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 * Initializes the given guac_client using the initialization routine provided
* by the plugin corresponding to the named protocol. This will automatically * by the plugin corresponding to the named protocol. This will automatically

View File

@ -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 * If an error occurs sending the instruction, a non-zero value is
* returned, and guac_error is set appropriately. * returned, and guac_error is set appropriately.
* *
* @param socket The guac_socket connection to use. * @param socket
* @param timestamp The current timestamp (in milliseconds). * The guac_socket connection to use.
* @return Zero on success, non-zero on error. *
* @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 */ /* OBJECT INSTRUCTIONS */

View File

@ -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; int ret_val;
@ -1189,6 +1190,8 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) {
ret_val = ret_val =
guac_socket_write_string(socket, "4.sync,") guac_socket_write_string(socket, "4.sync,")
|| __guac_socket_write_length_int(socket, timestamp) || __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_write_string(socket, ";");
guac_socket_instruction_end(socket); guac_socket_instruction_end(socket);