Sync message support.

This commit is contained in:
Michael Jumper 2011-03-11 18:57:53 -08:00
parent 90993d5d75
commit e463360aad
6 changed files with 80 additions and 11 deletions

View File

@ -48,7 +48,7 @@ AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writi
AC_CHECK_LIB([wsock32], [main]) AC_CHECK_LIB([wsock32], [main])
# Checks for header files. # Checks for header files.
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h pngstruct.h]) AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h pngstruct.h])
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
@ -57,7 +57,7 @@ AC_TYPE_SSIZE_T
# Checks for library functions. # Checks for library functions.
AC_FUNC_MALLOC AC_FUNC_MALLOC
AC_FUNC_REALLOC AC_FUNC_REALLOC
AC_CHECK_FUNCS([gettimeofday memmove memset select strdup png_get_io_ptr]) AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr])
AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([Makefile])
AC_OUTPUT AC_OUTPUT

View File

@ -118,7 +118,7 @@ GUACIO* guac_open(int fd);
* @param i The unsigned int to write. * @param i The unsigned int to write.
* @return Zero on success, or non-zero if an error occurs while writing. * @return Zero on success, or non-zero if an error occurs while writing.
*/ */
ssize_t guac_write_int(GUACIO* io, unsigned int i); ssize_t guac_write_int(GUACIO* io, unsigned long i);
/** /**
* Writes the given string to the given GUACIO object. The data * Writes the given string to the given GUACIO object. The data

View File

@ -131,6 +131,15 @@ void guac_send_args(GUACIO* io, const char** name);
*/ */
void guac_send_name(GUACIO* io, const char* name); void guac_send_name(GUACIO* io, const char* name);
/**
* Sends a sync instruction over the given GUACIO connection. The
* current time in milliseconds should be passed in as the timestamp.
*
* @param io The GUACIO connection to use.
* @param timestamp The current timestamp (in milliseconds).
*/
void guac_send_sync(GUACIO* io, long timestamp);
/** /**
* Sends an error instruction over the given GUACIO connection. The * Sends an error instruction over the given GUACIO connection. The
* error description given will be automatically escaped for * error description given will be automatically escaped for

View File

@ -37,6 +37,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_CLOCK_GETTIME
#include <time.h>
#else
#include <sys/time.h>
#endif
#include <string.h> #include <string.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -243,11 +248,42 @@ void guac_free_client(guac_client* client) {
} }
long __guac_current_timestamp() {
#ifdef HAVE_CLOCK_GETTIME
struct timespec current;
/* Get current time */
clock_gettime(CLOCK_REALTIME, &current);
/* Calculate milliseconds */
return current.tv_sec * 1000 + current.tv_nsec / 1000000;
#else
struct timeval current;
/* Get current time */
gettimeofday(&current, NULL);
/* Calculate milliseconds */
return current.tv_sec * 1000 + current.tv_usec / 1000;
#endif
}
void guac_start_client(guac_client* client) { void guac_start_client(guac_client* client) {
GUACIO* io = client->io; GUACIO* io = client->io;
guac_instruction instruction; guac_instruction instruction;
int wait_result; int wait_result;
long last_received_timestamp;
long last_sent_timestamp;
/* Init timestamps */
last_received_timestamp = last_sent_timestamp = __guac_current_timestamp();
/* VNC Client Loop */ /* VNC Client Loop */
for (;;) { for (;;) {
@ -255,13 +291,21 @@ void guac_start_client(guac_client* client) {
/* Handle server messages */ /* Handle server messages */
if (client->handle_messages) { if (client->handle_messages) {
/* Only handle messages if synced within threshold */
if (last_sent_timestamp - last_received_timestamp < 200) {
int retval = client->handle_messages(client); int retval = client->handle_messages(client);
if (retval) { if (retval) {
GUAC_LOG_ERROR("Error handling server messages"); GUAC_LOG_ERROR("Error handling server messages");
return; return;
} }
/* Send sync after updates */
last_sent_timestamp = __guac_current_timestamp();
guac_send_sync(io, last_sent_timestamp);
guac_flush(io); guac_flush(io);
}
} }
@ -275,7 +319,15 @@ void guac_start_client(guac_client* client) {
do { do {
if (strcmp(instruction.opcode, "mouse") == 0) { if (strcmp(instruction.opcode, "sync") == 0) {
last_received_timestamp = atol(instruction.argv[0]);
if (last_received_timestamp > last_sent_timestamp) {
guac_send_error(io, "Received sync from future.");
guac_free_instruction_data(&instruction);
return;
}
}
else if (strcmp(instruction.opcode, "mouse") == 0) {
if (client->mouse_handler) if (client->mouse_handler)
if ( if (
client->mouse_handler( client->mouse_handler(

View File

@ -97,7 +97,7 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) {
return retval; return retval;
} }
ssize_t guac_write_int(GUACIO* io, unsigned int i) { ssize_t guac_write_int(GUACIO* io, unsigned long i) {
char buffer[128]; char buffer[128];
char* ptr = &(buffer[127]); char* ptr = &(buffer[127]);

View File

@ -226,6 +226,14 @@ void guac_send_error(GUACIO* io, const char* error) {
} }
void guac_send_sync(GUACIO* io, long timestamp) {
guac_write_string(io, "sync:");
guac_write_int(io, timestamp);
guac_write_string(io, ";");
}
void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) {
guac_write_string(io, "copy:"); guac_write_string(io, "copy:");
guac_write_int(io, srcl); guac_write_int(io, srcl);