diff --git a/libguac/Makefile.am b/libguac/Makefile.am index f20371cc..5801e5f7 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h lib_LTLIBRARIES = libguac.la diff --git a/libguac/configure.in b/libguac/configure.in index 5ed6f722..c401cf1c 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -12,9 +12,10 @@ AC_PROG_LIBTOOL # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) +AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h pngstruct.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 8499ea3e..da4aa8f5 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -79,13 +79,6 @@ typedef struct GUACIO { */ char* instructionbuf; - /** - * The transfer limit, in kilobytes per second. If 0, there is no - * transfer limit. If non-zero, sleep calls are used at the end of - * a write to ensure output never exceeds the specified limit. - */ - unsigned int transfer_limit; /* KB/sec */ - } GUACIO; /** diff --git a/libguac/include/log.h b/libguac/include/log.h new file mode 100644 index 00000000..e8499f16 --- /dev/null +++ b/libguac/include/log.h @@ -0,0 +1,38 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _LOG_H +#define _LOG_H + +#ifdef HAVE_SYSLOG_H + + /* Logging for UNIX */ + #include + #define GUAC_LOG_ERROR(...) syslog(LOG_ERR, __VA_ARGS__) + #define GUAC_LOG_INFO(...) syslog(LOG_INFO, __VA_ARGS__) + +#else + + /* Logging for W32 */ + #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") + #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") + +#endif + +#endif diff --git a/libguac/src/client.c b/libguac/src/client.c index eae2dc56..e5bc4979 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -20,11 +20,9 @@ #include #include #include - -#include - #include +#include "log.h" #include "guacio.h" #include "protocol.h" #include "client.h" @@ -100,7 +98,7 @@ guac_client* guac_get_client(int client_fd) { int result = guac_read_instruction(io, &instruction); if (result < 0) { - syslog(LOG_ERR, "Error reading instruction while waiting for select"); + GUAC_LOG_ERROR("Error reading instruction while waiting for select"); guac_close(io); return NULL; } @@ -122,7 +120,7 @@ guac_client* guac_get_client(int client_fd) { /* Load client plugin */ client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!(client->client_plugin_handle)) { - syslog(LOG_ERR, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + GUAC_LOG_ERROR("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); guac_close(io); @@ -136,7 +134,7 @@ guac_client* guac_get_client(int client_fd) { alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { - syslog(LOG_ERR, "Could not get guac_client_init in plugin: %s\n", error); + GUAC_LOG_ERROR("Could not get guac_client_init in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -148,7 +146,7 @@ guac_client* guac_get_client(int client_fd) { client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - syslog(LOG_ERR, "Could not get GUAC_CLIENT_ in plugin: %s\n", error); + GUAC_LOG_ERROR("Could not get GUAC_CLIENT_ in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -175,7 +173,7 @@ guac_client* guac_get_client(int client_fd) { int result = guac_read_instruction(io, &instruction); if (result < 0) { - syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + GUAC_LOG_ERROR("Error reading instruction while waiting for connect"); guac_close(io); return NULL; } @@ -213,14 +211,14 @@ void guac_free_client(guac_client* client) { if (client->free_handler) { if (client->free_handler(client)) - syslog(LOG_ERR, "Error calling client free handler"); + GUAC_LOG_ERROR("Error calling client free handler"); } guac_close(client->io); /* Unload client plugin */ if (dlclose(client->client_plugin_handle)) { - syslog(LOG_ERR, "Could not close client plugin while unloading client: %s", dlerror()); + GUAC_LOG_ERROR("Could not close client plugin while unloading client: %s", dlerror()); } free(client); @@ -241,7 +239,7 @@ void guac_start_client(guac_client* client) { int retval = client->handle_messages(client); if (retval) { - syslog(LOG_ERR, "Error handling server messages"); + GUAC_LOG_ERROR("Error handling server messages"); return; } @@ -270,7 +268,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling mouse instruction"); + GUAC_LOG_ERROR("Error handling mouse instruction"); guac_free_instruction_data(&instruction); return; @@ -287,7 +285,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling key instruction"); + GUAC_LOG_ERROR("Error handling key instruction"); guac_free_instruction_data(&instruction); return; @@ -303,7 +301,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling clipboard instruction"); + GUAC_LOG_ERROR("Error handling clipboard instruction"); guac_free_instruction_data(&instruction); return; @@ -311,7 +309,7 @@ void guac_start_client(guac_client* client) { } else if (strcmp(instruction.opcode, "disconnect") == 0) { - syslog(LOG_INFO, "Client requested disconnect"); + GUAC_LOG_INFO("Client requested disconnect"); guac_free_instruction_data(&instruction); return; } @@ -321,13 +319,13 @@ void guac_start_client(guac_client* client) { } while ((retval = guac_read_instruction(io, &instruction)) > 0); if (retval < 0) { - syslog(LOG_ERR, "Error reading instruction from stream"); + GUAC_LOG_ERROR("Error reading instruction from stream"); return; } } if (retval < 0) { - syslog(LOG_ERR, "Error or end of stream"); + GUAC_LOG_ERROR("Error or end of stream"); return; /* EOF or error */ } @@ -335,7 +333,7 @@ void guac_start_client(guac_client* client) { } else if (wait_result < 0) { - syslog(LOG_ERR, "Error waiting for next instruction"); + GUAC_LOG_ERROR("Error waiting for next instruction"); return; } diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index e9f0e5b9..78ec98d6 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -23,8 +23,13 @@ #include #include -#include +#ifdef __MINGW32__ +#include +#else #include +#endif + +#include #include #include "guacio.h" @@ -48,9 +53,6 @@ GUACIO* guac_open(int fd) { io->instructionbuf = malloc(io->instructionbuf_size); io->instructionbuf_used_length = 0; - /* Set limit */ - io->transfer_limit = 0; - return io; } @@ -64,41 +66,15 @@ void guac_close(GUACIO* io) { /* Write bytes, limit rate */ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { - struct timeval start, end; int retval; - /* Write and time how long the write takes (microseconds) */ - gettimeofday(&start, NULL); +#ifdef __MINGW32__ + /* MINGW32 WINSOCK only works with send() */ + retval = send(io->fd, buf, count, 0); +#else + /* Use write() for all other platforms */ retval = write(io->fd, buf, count); - gettimeofday(&end, NULL); - - if (retval < 0) - return retval; - - if (io->transfer_limit > 0) { - - suseconds_t elapsed; - suseconds_t required_usecs; - - /* Get elapsed time */ - elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; - - /* Calculate how much time we must sleep */ - required_usecs = retval * 1000 / io->transfer_limit - elapsed; /* useconds at transfer_limit KB/s*/ - - /* Sleep as necessary */ - if (required_usecs > 0) { - - struct timespec required_sleep; - - required_sleep.tv_sec = required_usecs / 1000000; - required_sleep.tv_nsec = (required_usecs % 1000000) * 1000; - - nanosleep(&required_sleep, NULL); - - } - - } +#endif return retval; } @@ -136,19 +112,11 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { /* Flush when necessary, return on error */ if (io->written > 8188 /* sizeof(out_buf) - 4 */) { - struct timeval start, end; - suseconds_t elapsed; - - gettimeofday(&start, NULL); retval = __guac_write(io, out_buf, io->written); - gettimeofday(&end, NULL); if (retval < 0) return retval; - /* Get elapsed time */ - elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; - io->written = 0; } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 5a37e403..ec63a5da 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -23,8 +23,17 @@ #include #include +#ifdef HAVE_PNGSTRUCT_H +#include +#endif + #include + +#ifdef __MINGW32__ +#include +#else #include +#endif #include "guacio.h" #include "protocol.h"