diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 7db1ad03..fff061c1 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,11 +40,11 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/error.h +libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/error.c +libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c libguac_la_LDFLAGS = -version-info 2:0:0 diff --git a/libguac/include/client.h b/libguac/include/client.h index fbe00a0b..d3aa7e0a 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -39,7 +39,9 @@ #ifndef _GUAC_CLIENT_H #define _GUAC_CLIENT_H -#include "guacio.h" +#include + +#include "socket.h" #include "protocol.h" /** @@ -77,6 +79,11 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(guac_client* client); +/** + * Handler for logging messages + */ +typedef void guac_client_log_handler(guac_client* client, const char* format, va_list args); + /** * Possible current states of the Guacamole client. Currently, the only * two states are RUNNING and STOPPING. @@ -106,12 +113,12 @@ typedef enum guac_client_state { struct guac_client { /** - * The GUACIO structure to be used to communicate with the web-client. It is + * The guac_socket structure to be used to communicate with the web-client. It is * expected that the implementor of any Guacamole proxy client will provide - * their own mechanism of I/O for their protocol. The GUACIO structure is + * their own mechanism of I/O for their protocol. The guac_socket structure is * used only to communicate conveniently with the Guacamole web-client. */ - GUACIO* io; + guac_socket* io; /** * The current state of the client. When the client is first allocated, @@ -169,7 +176,7 @@ struct guac_client { * * Example: * @code - * void handle_messages(guac_client* client); + * int handle_messages(guac_client* client); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->handle_messages = handle_messages; @@ -196,7 +203,7 @@ struct guac_client { * Example: * @code - * void mouse_handler(guac_client* client, int x, int y, int button_mask); + * int mouse_handler(guac_client* client, int x, int y, int button_mask); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->mouse_handler = mouse_handler; @@ -214,7 +221,7 @@ struct guac_client { * * Example: * @code - * void key_handler(guac_client* client, int keysym, int pressed); + * int key_handler(guac_client* client, int keysym, int pressed); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->key_handler = key_handler; @@ -235,7 +242,7 @@ struct guac_client { * * Example: * @code - * void clipboard_handler(guac_client* client, char* copied); + * int clipboard_handler(guac_client* client, char* copied); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->clipboard_handler = clipboard_handler; @@ -255,7 +262,7 @@ struct guac_client { * * Example: * @code - * void free_handler(guac_client* client); + * int free_handler(guac_client* client); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->free_handler = free_handler; @@ -264,6 +271,60 @@ struct guac_client { */ guac_client_free_handler* free_handler; + /** + * Handler for logging informational messages. This handler will be called + * via guac_client_log_info() when the client needs to log information. + * + * In general, only programs loading the client should implement this + * handler, as those are the programs that would provide the logging + * facilities. + * + * Client implementations should expect these handlers to already be + * set. + * + * Example: + * @code + * void log_handler(guac_client* client, const char* format, va_list args); + * + * void function_of_daemon() { + * + * guac_client* client = [client from guac_get_client()]; + * + * client->log_info_handler = log_handler; + * + * } + * @endcode + */ + guac_client_log_handler* log_info_handler; + + + /** + * Handler for logging error messages. This handler will be called + * via guac_client_log_error() when the client needs to log an error. + * + * In general, only programs loading the client should implement this + * handler, as those are the programs that would provide the logging + * facilities. + * + * Client implementations should expect these handlers to already be + * set. + * + * Example: + * @code + * void log_handler(guac_client* client, const char* format, va_list args); + * + * void function_of_daemon() { + * + * guac_client* client = [client from guac_get_client()]; + * + * client->log_error_handler = log_handler; + * + * } + * @endcode + */ + guac_client_log_handler* log_error_handler; + + }; /** @@ -272,8 +333,9 @@ struct guac_client { typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); /** - * Initialize and return a new guac_client. The pluggable client will be chosen based on - * the first connect message received on the given file descriptor. + * Initialize and return a new guac_client. The pluggable client will be + * chosen based on the first connect message received on the given file + * descriptor. * * @param client_fd The file descriptor associated with the socket associated * with the connection to the web-client tunnel. @@ -288,7 +350,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout); * * @param client The proxy client to free all reasources of. */ -void guac_free_client(guac_client* client); +void guac_client_free(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -330,6 +392,56 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); +/** + * Logs an informational message in the log used by the given client. The + * logger used will normally be defined by guacd (or whichever program loads + * the proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an informational message for. + * @param format A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ +void guac_client_log_info(guac_client* client, const char* format, ...); + +/** + * Logs an error message in the log used by the given client. The logger + * used will normally be defined by guacd (or whichever program loads the + * proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an error for. + * @param format A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ +void guac_client_log_error(guac_client* client, const char* format, ...); + +/** + * Logs an informational message in the log used by the given client. The + * logger used will normally be defined by guacd (or whichever program loads + * the proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an informational message for. + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_client_log_info(guac_client* client, const char* format, va_list ap); + +/** + * Logs an error message in the log used by the given client. The logger + * used will normally be defined by guacd (or whichever program loads the + * proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an error for. + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_client_log_error(guac_client* client, const char* format, va_list ap); + /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/include/log.h b/libguac/include/log.h deleted file mode 100644 index fc531896..00000000 --- a/libguac/include/log.h +++ /dev/null @@ -1,95 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _GUAC_LOG_H -#define _GUAC_LOG_H - -#include - -/** - * Provides basic cross-platform logging facilities. - * - * @file log.h - */ - -/** - * Logs an informational message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ... Arguments to use when filling the format string for printing. - */ -void guac_log_info(const char* format, ...); - -/** - * Logs an informational message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ap The va_list containing the arguments to be used when filling the - * format string for printing. - */ -void vguac_log_info(const char* format, va_list ap); - -/** - * Logs an error message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ... Arguments to use when filling the format string for printing. - */ -void guac_log_error(const char* format, ...); - -/** - * Logs an error message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ap The va_list containing the arguments to be used when filling the - * format string for printing. - */ -void vguac_log_error(const char* format, va_list ap); - -#endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5c165492..302c71e2 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -40,11 +40,11 @@ #include -#include "guacio.h" +#include "socket.h" /** * Provides functions and structures required for communicating using the - * Guacamole protocol over a GUACIO connection, such as that provided by + * Guacamole protocol over a guac_socket connection, such as that provided by * guac_client objects. * * @file protocol.h @@ -147,86 +147,86 @@ typedef struct guac_instruction { * * @param instruction The instruction to free. */ -void guac_free_instruction(guac_instruction* instruction); +void guac_instruction_free(guac_instruction* instruction); /** - * Sends an args instruction over the given GUACIO connection. + * Sends an args instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param args The NULL-terminated array of argument names (strings). * @return Zero on success, non-zero on error. */ -int guac_send_args(GUACIO* io, const char** name); +int guac_protocol_send_args(guac_socket* io, const char** name); /** - * Sends a name instruction over the given GUACIO connection. + * Sends a name instruction over the given guac_socket connection. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param name The name to send within the name instruction. * @return Zero on success, non-zero on error. */ -int guac_send_name(GUACIO* io, const char* name); +int guac_protocol_send_name(guac_socket* io, const char* name); /** - * Sends a sync instruction over the given GUACIO connection. The + * Sends a sync instruction over the given guac_socket connection. The * current time in milliseconds should be passed in as the timestamp. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ -int guac_send_sync(GUACIO* io, guac_timestamp timestamp); +int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp); /** - * Sends an error instruction over the given GUACIO connection. + * Sends an error instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param error The description associated with the error. * @return Zero on success, non-zero on error. */ -int guac_send_error(GUACIO* io, const char* error); +int guac_protocol_send_error(guac_socket* io, const char* error); /** - * Sends a clipboard instruction over the given GUACIO connection. + * Sends a clipboard instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param data The clipboard data to send. * @return Zero on success, non-zero on error. */ -int guac_send_clipboard(GUACIO* io, const char* data); +int guac_protocol_send_clipboard(guac_socket* io, const char* data); /** - * Sends a size instruction over the given GUACIO connection. + * Sends a size instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param w The width of the display. * @param h The height of the display. * @return Zero on success, non-zero on error. */ -int guac_send_size(GUACIO* io, int w, int h); +int guac_protocol_send_size(guac_socket* io, int w, int h); /** - * Sends a copy instruction over the given GUACIO connection. + * Sends a copy instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. @@ -240,17 +240,17 @@ int guac_send_size(GUACIO* io, int w, int h); * should be copied. * @return Zero on success, non-zero on error. */ -int guac_send_copy(GUACIO* io, +int guac_protocol_send_copy(guac_socket* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); /** - * Sends a rect instruction over the given GUACIO connection. + * Sends a rect instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The X coordinate of the rectangle. @@ -263,18 +263,18 @@ int guac_send_copy(GUACIO* io, * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ -int guac_send_rect(GUACIO* io, +int guac_protocol_send_rect(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); /** - * Sends a clip instruction over the given GUACIO connection. + * Sends a clip instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @param x The X coordinate of the clipping rectangle. * @param y The Y coordinate of the clipping rectangle. @@ -282,17 +282,17 @@ int guac_send_rect(GUACIO* io, * @param height The height of the clipping rectangle. * @return Zero on success, non-zero on error. */ -int guac_send_clip(GUACIO* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, int x, int y, int width, int height); /** - * Sends a png instruction over the given GUACIO connection. The PNG image data + * Sends a png instruction over the given guac_socket connection. The PNG image data * given will be automatically base64-encoded for transmission. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The destination X coordinate. @@ -300,53 +300,75 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_png(GUACIO* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** - * Sends a cursor instruction over the given GUACIO connection. The PNG image + * Sends a cursor instruction over the given guac_socket connection. The PNG image * data given will be automatically base64-encoded for transmission. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); +int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface); /** - * Returns whether new instruction data is available on the given GUACIO + * Returns whether new instruction data is available on the given guac_socket * connection for parsing. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A positive value if data is available, negative on error, or * zero if no data is currently available. */ -int guac_instructions_waiting(GUACIO* io, int usec_timeout); +int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout); /** - * Reads a single instruction from the given GUACIO connection. + * Reads a single instruction from the given guac_socket connection. * * If an error occurs reading the instruction, NULL is returned, * and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A new instruction if data was successfully read, NULL on * error or if the instruction could not be read completely * because the timeout elapsed, in which case guac_error will be * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to - * guac_read_instruction() will return the parsed instruction once + * guac_protocol_read_instruction() will return the parsed instruction once * enough data is available. */ -guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout); +guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout); + +/** + * Reads a single instruction with the given opcode from the given guac_socket + * connection. + * + * If an error occurs reading the instruction, NULL is returned, + * and guac_error is set appropriately. + * + * If the instruction read is not the expected instruction, NULL is returned, + * and guac_error is set to GUAC_STATUS_BAD_STATE. + * + * @param io The guac_socket connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. + * @param opcode The opcode of the instruction to read. + * @return A new instruction if an instruction with the given opcode was read, + * NULL otherwise. If an instruction was read, but the instruction had + * a different opcode, NULL is returned and guac_error is set to + * GUAC_STATUS_BAD_STATE. + */ +guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, + const char* opcode); /** * Returns an arbitrary timestamp. The difference between return values of any @@ -356,7 +378,7 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout); * * @return An arbitrary millisecond timestamp. */ -guac_timestamp guac_current_timestamp(); +guac_timestamp guac_protocol_get_timestamp(); /** * Suspends execution of the current thread for the given number of diff --git a/libguac/include/guacio.h b/libguac/include/socket.h similarity index 76% rename from libguac/include/guacio.h rename to libguac/include/socket.h index 6b5ac161..38f8108a 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/socket.h @@ -35,24 +35,24 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef _GUAC_GUACIO_H -#define _GUAC_GUACIO_H +#ifndef _GUAC_SOCKET_H +#define _GUAC_SOCKET_H #include #include /** - * Defines the GUACIO object and functionss for using and manipulating it. + * Defines the guac_socket object and functionss for using and manipulating it. * - * @file guacio.h + * @file socket.h */ /** - * The core I/O object of Guacamole. GUACIO provides buffered input and output - * as well as convenience methods for efficiently writing base64 data. + * The core I/O object of Guacamole. guac_socket provides buffered input and + * output as well as convenience methods for efficiently writing base64 data. */ -typedef struct GUACIO { +typedef struct guac_socket { /** * The file descriptor to be read from / written to. @@ -114,21 +114,21 @@ typedef struct GUACIO { */ char* __instructionbuf_elementv[64]; -} GUACIO; +} guac_socket; /** - * Allocates and initializes a new GUACIO object with the given open + * Allocates and initializes a new guac_socket object with the given open * file descriptor. * - * If an error occurs while allocating the GUACIO object, NULL is returned, + * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * - * @param fd An open file descriptor that this GUACIO object should manage. - * @return A newly allocated GUACIO object associated with the given + * @param fd An open file descriptor that this guac_socket object should manage. + * @return A newly allocated guac_socket object associated with the given * file descriptor, or NULL if an error occurs while allocating - * the GUACIO object. + * the guac_socket object. */ -GUACIO* guac_open(int fd); +guac_socket* guac_socket_open(int fd); /** * Parses the given string as a decimal number, returning the result as @@ -142,21 +142,21 @@ GUACIO* guac_open(int fd); int64_t guac_parse_int(const char* str); /** - * Writes the given unsigned int to the given GUACIO object. The data + * Writes the given unsigned int to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, int64_t i); +ssize_t guac_socket_write_int(guac_socket* io, int64_t i); /** - * Writes the given string to the given GUACIO object. The data + * Writes the given string to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. Note that if the string can contain characters used * internally by the Guacamole protocol (commas, semicolons, or @@ -165,29 +165,29 @@ ssize_t guac_write_int(GUACIO* io, int64_t i); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_string(GUACIO* io, const char* str); +ssize_t guac_socket_write_string(guac_socket* io, const char* str); /** - * Writes the given binary data to the given GUACIO object as base64-encoded + * Writes the given binary data to the given guac_socket object as base64-encoded * data. The data written may be buffered until the buffer is flushed * automatically or manually. Beware that because base64 data is buffered - * on top of the write buffer already used, a call to guac_flush_base64() must + * on top of the write buffer already used, a call to guac_socket_flush_base64() must * be made before non-base64 writes (or writes of an independent block of * base64 data) can be made. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); +ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. @@ -195,10 +195,10 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to flush + * @param io The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush_base64(GUACIO* io); +ssize_t guac_socket_flush_base64(guac_socket* io); /** * Flushes the write buffer. @@ -206,14 +206,14 @@ ssize_t guac_flush_base64(GUACIO* io); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to flush + * @param io The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush(GUACIO* io); +ssize_t guac_socket_flush(guac_socket* io); /** - * Waits for input to be available on the given GUACIO object until the + * Waits for input to be available on the given guac_socket object until the * specified timeout elapses. * * If an error occurs while waiting, a negative value is returned, and @@ -222,22 +222,22 @@ ssize_t guac_flush(GUACIO* io); * If a timeout occurs while waiting, zero value is returned, and * guac_error is set to GUAC_STATUS_INPUT_TIMEOUT. * - * @param io The GUACIO object to wait for. + * @param io The guac_socket object to wait for. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ -int guac_select(GUACIO* io, int usec_timeout); +int guac_socket_select(guac_socket* io, int usec_timeout); /** - * Frees resources allocated to the given GUACIO object. Note that this + * Frees resources allocated to the given guac_socket object. Note that this * implicitly flush all buffers, but will NOT close the associated file * descriptor. * - * @param io The GUACIO object to close. + * @param io The guac_socket object to close. */ -void guac_close(GUACIO* io); +void guac_socket_close(guac_socket* io); #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 320c10a3..0ba54118 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -40,8 +40,7 @@ #include #include -#include "log.h" -#include "guacio.h" +#include "socket.h" #include "protocol.h" #include "client.h" #include "client-handlers.h" @@ -57,7 +56,7 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_client* __guac_alloc_client(GUACIO* io) { +guac_client* __guac_alloc_client(guac_socket* io) { /* Allocate new client (not handoff) */ guac_client* client = malloc(sizeof(guac_client)); @@ -65,7 +64,7 @@ guac_client* __guac_alloc_client(GUACIO* io) { /* Init new client */ client->io = io; - client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); + client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); client->state = RUNNING; client->__all_layers = NULL; @@ -131,7 +130,7 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_client* client; - GUACIO* io = guac_open(client_fd); + guac_socket* io = guac_socket_open(client_fd); /* Pluggable client */ char protocol_lib[256] = "libguac-client-"; @@ -159,22 +158,22 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io, usec_timeout); + result = guac_protocol_instructions_waiting(io, usec_timeout); if (result == 0) { - guac_send_error(io, "Select timeout."); - guac_close(io); + guac_protocol_send_error(io, "Select timeout."); + guac_socket_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ if (result < 0) { - guac_close(io); + guac_socket_close(io); return NULL; } - instruction = guac_read_instruction(io, usec_timeout); + instruction = guac_protocol_read_instruction(io, usec_timeout); if (instruction == NULL) { - guac_close(io); + guac_socket_close(io); return NULL; } @@ -195,11 +194,11 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { /* Load client plugin */ client->__client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!(client->__client_plugin_handle)) { - 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); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + guac_protocol_send_error(io, "Could not load server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } @@ -209,11 +208,11 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { alias.obj = dlsym(client->__client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { - 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); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not get guac_client_init in plugin: %s\n", error); + guac_protocol_send_error(io, "Invalid server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } @@ -221,29 +220,29 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { client_args = (const char**) dlsym(client->__client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - guac_log_error("Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); - guac_send_error(io, "Invalid server-side client plugin."); - guac_flush(io); - guac_close(io); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); + guac_protocol_send_error(io, "Invalid server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } if ( /* Send args */ - guac_send_args(io, client_args) - || guac_flush(io) + guac_protocol_send_args(io, client_args) + || guac_socket_flush(io) ) { - guac_close(io); - guac_free_instruction(instruction); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } - guac_free_instruction(instruction); + guac_instruction_free(instruction); break; } /* end if select */ - guac_free_instruction(instruction); + guac_instruction_free(instruction); } } @@ -254,23 +253,23 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io, usec_timeout); + result = guac_protocol_instructions_waiting(io, usec_timeout); if (result == 0) { - guac_send_error(io, "Connect timeout."); - guac_close(io); + guac_protocol_send_error(io, "Connect timeout."); + guac_socket_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ if (result < 0) { - guac_close(io); + guac_socket_close(io); return NULL; } - instruction = guac_read_instruction(io, usec_timeout); + instruction = guac_protocol_read_instruction(io, usec_timeout); if (instruction == NULL) { - guac_log_error("Error reading instruction while waiting for connect"); - guac_close(io); + guac_client_log_error(client, "Error reading instruction while waiting for connect"); + guac_socket_close(io); return NULL; } @@ -285,35 +284,35 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { if (alias.client_init(client, argc, argv) != 0) { /* NOTE: On error, proxy client will send appropriate error message */ - guac_free_instruction(instruction); - guac_close(io); + guac_instruction_free(instruction); + guac_socket_close(io); return NULL; } - guac_free_instruction(instruction); + guac_instruction_free(instruction); return client; } /* end if connect */ - guac_free_instruction(instruction); + guac_instruction_free(instruction); } } } -void guac_free_client(guac_client* client) { +void guac_client_free(guac_client* client) { if (client->free_handler) { if (client->free_handler(client)) - guac_log_error("Error calling client free handler"); + guac_client_log_error(client, "Error calling client free handler"); } - guac_close(client->io); + guac_socket_close(client->io); /* Unload client plugin */ if (dlclose(client->__client_plugin_handle)) { - guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); + guac_client_log_error(client, "Could not close client plugin while unloading client: %s", dlerror()); } /* Free all layers */ diff --git a/libguac/src/log.c b/libguac/src/log.c deleted file mode 100644 index c51bff15..00000000 --- a/libguac/src/log.c +++ /dev/null @@ -1,89 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifdef HAVE_SYSLOG_H - #include -#else - #include -#endif - -#include - -#include "log.h" - -void vguac_log_info(const char* format, va_list ap) { -#ifdef HAVE_SYSLOG_H - vsyslog(LOG_ERR, format, ap); -#else - fprintf(stderr, "guacamole: info: "); - vfprintf(stderr, format, ap); - fprintf(stderr, "\n"); -#endif -} - -void vguac_log_error(const char* format, va_list ap) { -#ifdef HAVE_SYSLOG_H - vsyslog(LOG_INFO, format, ap); -#else - fprintf(stderr, "guacamole: error: "); - vfprintf(stderr, format, ap); - fprintf(stderr, "\n"); -#endif -} - -void guac_log_info(const char* format, ...) { - - va_list args; - va_start(args, format); - - vguac_log_info(format, args); - - va_end(args); - -} - -void guac_log_error(const char* format, ...) { - - va_list args; - va_start(args, format); - - vguac_log_error(format, args); - - va_end(args); - -} - diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f2c86791..faafe65d 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -60,181 +60,181 @@ #include #endif -#include "guacio.h" +#include "socket.h" #include "protocol.h" #include "error.h" -ssize_t __guac_write_length_string(GUACIO* io, const char* str) { +ssize_t __guac_socket_write_length_string(guac_socket* io, const char* str) { return - guac_write_int(io, strlen(str)) - || guac_write_string(io, ".") - || guac_write_string(io, str); + guac_socket_write_int(io, strlen(str)) + || guac_socket_write_string(io, ".") + || guac_socket_write_string(io, str); } -ssize_t __guac_write_length_int(GUACIO* io, int64_t i) { +ssize_t __guac_socket_write_length_int(guac_socket* io, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return __guac_write_length_string(io, buffer); + return __guac_socket_write_length_string(io, buffer); } -int guac_send_args(GUACIO* io, const char** args) { +int guac_protocol_send_args(guac_socket* io, const char** args) { int i; - if (guac_write_string(io, "4.args")) return -1; + if (guac_socket_write_string(io, "4.args")) return -1; for (i=0; args[i] != NULL; i++) { - if (guac_write_string(io, ",")) + if (guac_socket_write_string(io, ",")) return -1; - if (__guac_write_length_string(io, args[i])) + if (__guac_socket_write_length_string(io, args[i])) return -1; } - return guac_write_string(io, ";"); + return guac_socket_write_string(io, ";"); } -int guac_send_name(GUACIO* io, const char* name) { +int guac_protocol_send_name(guac_socket* io, const char* name) { return - guac_write_string(io, "4.name,") - || __guac_write_length_string(io, name) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.name,") + || __guac_socket_write_length_string(io, name) + || guac_socket_write_string(io, ";"); } -int guac_send_size(GUACIO* io, int w, int h) { +int guac_protocol_send_size(guac_socket* io, int w, int h) { return - guac_write_string(io, "4.size,") - || __guac_write_length_int(io, w) - || guac_write_string(io, ",") - || __guac_write_length_int(io, h) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.size,") + || __guac_socket_write_length_int(io, w) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, h) + || guac_socket_write_string(io, ";"); } -int guac_send_clipboard(GUACIO* io, const char* data) { +int guac_protocol_send_clipboard(guac_socket* io, const char* data) { return - guac_write_string(io, "9.clipboard,") - || __guac_write_length_string(io, data) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "9.clipboard,") + || __guac_socket_write_length_string(io, data) + || guac_socket_write_string(io, ";"); } -int guac_send_error(GUACIO* io, const char* error) { +int guac_protocol_send_error(guac_socket* io, const char* error) { return - guac_write_string(io, "5.error,") - || __guac_write_length_string(io, error) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "5.error,") + || __guac_socket_write_length_string(io, error) + || guac_socket_write_string(io, ";"); } -int guac_send_sync(GUACIO* io, guac_timestamp timestamp) { +int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp) { return - guac_write_string(io, "4.sync,") - || __guac_write_length_int(io, timestamp) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.sync,") + || __guac_socket_write_length_int(io, timestamp) + || guac_socket_write_string(io, ";"); } -int guac_send_copy(GUACIO* io, +int guac_protocol_send_copy(guac_socket* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { return - guac_write_string(io, "4.copy,") - || __guac_write_length_int(io, srcl->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, srcx) - || guac_write_string(io, ",") - || __guac_write_length_int(io, srcy) - || guac_write_string(io, ",") - || __guac_write_length_int(io, w) - || guac_write_string(io, ",") - || __guac_write_length_int(io, h) - || guac_write_string(io, ",") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dstl->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dstx) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dsty) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.copy,") + || __guac_socket_write_length_int(io, srcl->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, srcx) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, srcy) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, w) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, h) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dstl->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dstx) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dsty) + || guac_socket_write_string(io, ";"); } -int guac_send_rect(GUACIO* io, +int guac_protocol_send_rect(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a) { return - guac_write_string(io, "4.rect,") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_int(io, width) - || guac_write_string(io, ",") - || __guac_write_length_int(io, height) - || guac_write_string(io, ",") - || __guac_write_length_int(io, r) - || guac_write_string(io, ",") - || __guac_write_length_int(io, g) - || guac_write_string(io, ",") - || __guac_write_length_int(io, b) - || guac_write_string(io, ",") - || __guac_write_length_int(io, a) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.rect,") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, width) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, height) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, r) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, g) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, b) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, a) + || guac_socket_write_string(io, ";"); } -int guac_send_clip(GUACIO* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, int x, int y, int width, int height) { return - guac_write_string(io, "4.clip,") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_int(io, width) - || guac_write_string(io, ",") - || __guac_write_length_int(io, height) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.clip,") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, width) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, height) + || guac_socket_write_string(io, ";"); } -typedef struct __guac_write_png_data { +typedef struct __guac_socket_write_png_data { - GUACIO* io; + guac_socket* io; char* buffer; int buffer_size; int data_size; -} __guac_write_png_data; +} __guac_socket_write_png_data; -cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) { +cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, unsigned int length) { - __guac_write_png_data* png_data = (__guac_write_png_data*) closure; + __guac_socket_write_png_data* png_data = (__guac_socket_write_png_data*) closure; /* Calculate next buffer size */ int next_size = png_data->data_size + length; @@ -262,9 +262,9 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign } -int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { +int __guac_socket_write_length_png(guac_socket* io, cairo_surface_t* surface) { - __guac_write_png_data png_data; + __guac_socket_write_png_data png_data; int base64_length; /* Write surface */ @@ -274,7 +274,7 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { png_data.buffer = malloc(png_data.buffer_size); png_data.data_size = 0; - if (cairo_surface_write_to_png_stream(surface, __guac_write_png, &png_data) != CAIRO_STATUS_SUCCESS) { + if (cairo_surface_write_to_png_stream(surface, __guac_socket_write_png, &png_data) != CAIRO_STATUS_SUCCESS) { return -1; } @@ -282,10 +282,10 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { /* Write length and data */ if ( - guac_write_int(io, base64_length) - || guac_write_string(io, ".") - || guac_write_base64(io, png_data.buffer, png_data.data_size) - || guac_flush_base64(io)) { + guac_socket_write_int(io, base64_length) + || guac_socket_write_string(io, ".") + || guac_socket_write_base64(io, png_data.buffer, png_data.data_size) + || guac_socket_flush_base64(io)) { free(png_data.buffer); return -1; } @@ -296,40 +296,40 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { } -int guac_send_png(GUACIO* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { return - guac_write_string(io, "3.png,") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_png(io, surface) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "3.png,") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_png(io, surface) + || guac_socket_write_string(io, ";"); } -int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { +int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface) { return - guac_write_string(io, "6.cursor,") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_png(io, surface) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "6.cursor,") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_png(io, surface) + || guac_socket_write_string(io, ";"); } -int __guac_fill_instructionbuf(GUACIO* io) { +int __guac_fill_instructionbuf(guac_socket* io) { int retval; @@ -357,7 +357,7 @@ int __guac_fill_instructionbuf(GUACIO* io) { } /* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { +guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout) { int retval; int i = io->__instructionbuf_parse_start; @@ -482,7 +482,7 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { } /* No instruction yet? Get more data ... */ - retval = guac_select(io, usec_timeout); + retval = guac_socket_select(io, usec_timeout); if (retval <= 0) return NULL; @@ -503,28 +503,54 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { } -void guac_free_instruction_data(guac_instruction* instruction) { +guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, + const char* opcode) { + + guac_instruction* instruction; + + /* Wait for data until timeout */ + if (guac_protocol_instructions_waiting(io, usec_timeout) <= 0) + return NULL; + + /* Read available instruction */ + instruction = guac_protocol_read_instruction(io, usec_timeout); + if (instruction == NULL) + return NULL; + + /* Validate instruction */ + if (strcmp(instruction->opcode, opcode) != 0) { + guac_error = GUAC_STATUS_BAD_STATE; + guac_instruction_free(instruction); + return NULL; + } + + /* Return instruction if valid */ + return instruction; + +} + +void guac_instruction_free_data(guac_instruction* instruction) { free(instruction->opcode); if (instruction->argv) free(instruction->argv); } -void guac_free_instruction(guac_instruction* instruction) { - guac_free_instruction_data(instruction); +void guac_instruction_free(guac_instruction* instruction) { + guac_instruction_free_data(instruction); free(instruction); } -int guac_instructions_waiting(GUACIO* io, int usec_timeout) { +int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout) { if (io->__instructionbuf_used_length > 0) return 1; - return guac_select(io, usec_timeout); + return guac_socket_select(io, usec_timeout); } -guac_timestamp guac_current_timestamp() { +guac_timestamp guac_protocol_get_timestamp() { #ifdef HAVE_CLOCK_GETTIME diff --git a/libguac/src/guacio.c b/libguac/src/socket.c similarity index 75% rename from libguac/src/guacio.c rename to libguac/src/socket.c index cd523c17..66f5c050 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/socket.c @@ -52,19 +52,19 @@ #include #include -#include "guacio.h" +#include "socket.h" #include "error.h" -char __GUACIO_BASE64_CHARACTERS[64] = { +char __guac_socket_BASE64_CHARACTERS[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', }; -GUACIO* guac_open(int fd) { +guac_socket* guac_socket_open(int fd) { - GUACIO* io = malloc(sizeof(GUACIO)); + guac_socket* io = malloc(sizeof(guac_socket)); /* If no memory available, return with error */ if (io == NULL) { @@ -96,14 +96,14 @@ GUACIO* guac_open(int fd) { } -void guac_close(GUACIO* io) { - guac_flush(io); +void guac_socket_close(guac_socket* io) { + guac_socket_flush(io); free(io->__instructionbuf); free(io); } /* Write bytes, limit rate */ -ssize_t __guac_write(GUACIO* io, const char* buf, int count) { +ssize_t __guac_socket_write(guac_socket* io, const char* buf, int count) { int retval; @@ -140,15 +140,15 @@ int64_t guac_parse_int(const char* str) { } -ssize_t guac_write_int(GUACIO* io, int64_t i) { +ssize_t guac_socket_write_int(guac_socket* io, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return guac_write_string(io, buffer); + return guac_socket_write_string(io, buffer); } -ssize_t guac_write_string(GUACIO* io, const char* str) { +ssize_t guac_socket_write_string(guac_socket* io, const char* str) { char* __out_buf = io->__out_buf; @@ -161,7 +161,7 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { /* Flush when necessary, return on error */ if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_write(io, __out_buf, io->__written); + retval = __guac_socket_write(io, __out_buf, io->__written); if (retval < 0) return retval; @@ -175,29 +175,29 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { } -ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { +ssize_t __guac_socket_write_base64_triplet(guac_socket* io, int a, int b, int c) { char* __out_buf = io->__out_buf; int retval; /* Byte 1 */ - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ if (b >= 0) { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ if (c >= 0) { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ } else { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ __out_buf[io->__written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ } } else { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ __out_buf[io->__written++] = '='; /* AAAAAA AA----[------]------ */ __out_buf[io->__written++] = '='; /* AAAAAA AA---- ------[------] */ } @@ -206,7 +206,7 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { /* Flush when necessary, return on error */ if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_write(io, __out_buf, io->__written); + retval = __guac_socket_write(io, __out_buf, io->__written); if (retval < 0) return retval; @@ -223,7 +223,7 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { } -ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { +ssize_t __guac_socket_write_base64_byte(guac_socket* io, char buf) { int* __ready_buf = io->__ready_buf; @@ -233,7 +233,7 @@ ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { /* Flush triplet */ if (io->__ready == 3) { - retval = __guac_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); + retval = __guac_socket_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); if (retval < 0) return retval; @@ -243,7 +243,7 @@ ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { return 1; } -ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { +ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) { int retval; @@ -252,7 +252,7 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { while (char_buf < end) { - retval = __guac_write_base64_byte(io, *(char_buf++)); + retval = __guac_socket_write_base64_byte(io, *(char_buf++)); if (retval < 0) return retval; @@ -262,13 +262,13 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { } -ssize_t guac_flush(GUACIO* io) { +ssize_t guac_socket_flush(guac_socket* io) { int retval; /* Flush remaining bytes in buffer */ if (io->__written > 0) { - retval = __guac_write(io, io->__out_buf, io->__written); + retval = __guac_socket_write(io, io->__out_buf, io->__written); if (retval < 0) return retval; @@ -279,13 +279,13 @@ ssize_t guac_flush(GUACIO* io) { } -ssize_t guac_flush_base64(GUACIO* io) { +ssize_t guac_socket_flush_base64(guac_socket* io) { int retval; /* Flush triplet to output buffer */ while (io->__ready > 0) { - retval = __guac_write_base64_byte(io, -1); + retval = __guac_socket_write_base64_byte(io, -1); if (retval < 0) return retval; } @@ -295,7 +295,7 @@ ssize_t guac_flush_base64(GUACIO* io) { } -int guac_select(GUACIO* io, int usec_timeout) { +int guac_socket_select(guac_socket* io, int usec_timeout) { fd_set fds; struct timeval timeout;