Using C99, POSIX, and BSD. Added guac_layer and layer/buffer alloc/free.

This commit is contained in:
Michael Jumper 2011-07-20 12:36:02 -07:00
parent 208ff61edd
commit 6341346cb7
5 changed files with 192 additions and 12 deletions

View File

@ -40,8 +40,15 @@ AC_CONFIG_MACRO_DIR([m4])
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_CC_C99
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
# POSIX
AC_DEFINE(_POSIX_C_SOURCE, 199309L)
# BSD
AC_DEFINE(_BSD_SOURCE)
# Checks for libraries. # Checks for libraries.
AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins"))
AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions")) AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions"))

View File

@ -147,6 +147,29 @@ struct guac_client {
*/ */
guac_client_state state; guac_client_state state;
/**
* The head pointer of the list of all available (allocated but not used)
* layers.
*/
guac_layer* available_layers;
/**
* The index of the next available buffer.
*/
int next_buffer_index;
/**
* The head pointer of the list of all available (allocated but not used)
* buffers.
*/
guac_layer* available_buffers;
/**
* The head pointer of the list of all allocated layers, regardless of use
* status.
*/
guac_layer* all_layers;
/** /**
* The time (in milliseconds) of receipt of the last sync message from * The time (in milliseconds) of receipt of the last sync message from
* the client. * the client.
@ -328,4 +351,43 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru
*/ */
void guac_client_stop(guac_client* client); void guac_client_stop(guac_client* client);
/**
* Allocates a new buffer (invisible layer). An arbitrary index is
* automatically assigned if no existing buffer is available for use.
*
* @param client The proxy client to allocate the buffer for.
* @return The next available buffer, or a newly allocated buffer.
*/
guac_layer* guac_client_alloc_buffer(guac_client* client);
/**
* Allocates a new layer. The layer will be given the specified index,
* even if the layer returned was a previously used (and free'd) layer.
*
* @param client The proxy client to allocate the layer buffer for.
* @param index The index of the layer to allocate.
* @return The next available layer, or a newly allocated layer.
*/
guac_layer* guac_client_alloc_layer(guac_client* client, int index);
/**
* Returns the given buffer to the pool of available buffers, such that it
* can be reused by any subsequent call to guac_client_allow_buffer().
*
* @param client The proxy client to return the buffer to.
* @param layer The buffer to return to the pool of available buffers.
*/
void guac_client_free_buffer(guac_client* client, guac_layer* layer);
/**
* Returns the given layer to the pool of available layers, such that it
* can be reused by any subsequent call to guac_client_allow_layer().
*
* @param client The proxy client to return the layer to.
* @param layer The layer to return to the pool of available layers.
*/
void guac_client_free_layer(guac_client* client, guac_layer* layer);
extern const guac_layer* GUAC_DEFAULT_LAYER;
#endif #endif

View File

@ -102,6 +102,30 @@ typedef enum guac_composite_mode_t {
} guac_composite_mode_t; } guac_composite_mode_t;
typedef struct guac_layer guac_layer;
/**
* Represents a single layer within the Guacamole protocol.
*/
struct guac_layer {
/**
* The index of this layer.
*/
int index;
/**
* The next allocated layer in the list of all layers.
*/
guac_layer* next;
/**
* The next available (unused) layer in the list of
* allocated but free'd layers.
*/
guac_layer* next_available;
};
/** /**
* Represents a single instruction within the Guacamole protocol. * Represents a single instruction within the Guacamole protocol.
@ -230,13 +254,13 @@ int guac_send_size(GUACIO* io, int w, int h);
* Sends a copy instruction over the given GUACIO connection. * Sends a copy instruction over the given GUACIO connection.
* *
* @param io The GUACIO connection to use. * @param io The GUACIO connection to use.
* @param srcl The index of the source layer. * @param srcl The source layer.
* @param srcx The X coordinate of the source rectangle. * @param srcx The X coordinate of the source rectangle.
* @param srcy The Y coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle.
* @param w The width of the source rectangle. * @param w The width of the source rectangle.
* @param h The height of the source rectangle. * @param h The height of the source rectangle.
* @param mode The composite mode to use. * @param mode The composite mode to use.
* @param dstl The index of the destination layer. * @param dstl The destination layer.
* @param dstx The X coordinate of the destination, where the source rectangle * @param dstx The X coordinate of the destination, where the source rectangle
* should be copied. * should be copied.
* @param dsty The Y coordinate of the destination, where the source rectangle * @param dsty The Y coordinate of the destination, where the source rectangle
@ -244,8 +268,8 @@ int guac_send_size(GUACIO* io, int w, int h);
* @return Zero on success, non-zero on error. * @return Zero on success, non-zero on error.
*/ */
int guac_send_copy(GUACIO* io, int guac_send_copy(GUACIO* io,
int srcl, int srcx, int srcy, int w, int h, const guac_layer* srcl, int srcx, int srcy, int w, int h,
guac_composite_mode_t mode, int dstl, int dstx, int dsty); guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty);
/** /**
* Sends a png instruction over the given GUACIO connection. The PNG image data * Sends a png instruction over the given GUACIO connection. The PNG image data
@ -253,14 +277,14 @@ int guac_send_copy(GUACIO* io,
* *
* @param io The GUACIO connection to use. * @param io The GUACIO connection to use.
* @param mode The composite mode to use. * @param mode The composite mode to use.
* @param layer The index of the destination layer. * @param layer The destination layer.
* @param x The destination X coordinate. * @param x The destination X coordinate.
* @param y The destination Y coordinate. * @param y The destination Y coordinate.
* @param surface A cairo surface containing the image data to send. * @param surface A cairo surface containing the image data to send.
* @return Zero on success, non-zero on error. * @return Zero on success, non-zero on error.
*/ */
int guac_send_png(GUACIO* io, guac_composite_mode_t mode, int guac_send_png(GUACIO* io, guac_composite_mode_t mode,
int layer, int x, int y, cairo_surface_t* surface); 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 GUACIO connection. The PNG image

View File

@ -47,6 +47,15 @@
#include "client.h" #include "client.h"
#include "client-handlers.h" #include "client-handlers.h"
guac_layer __GUAC_DEFAULT_LAYER = {
.index = 0,
.next = NULL,
.next_available = NULL
};
const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER;
guac_client* __guac_alloc_client(GUACIO* io) { guac_client* __guac_alloc_client(GUACIO* io) {
/* Allocate new client (not handoff) */ /* Allocate new client (not handoff) */
@ -58,9 +67,80 @@ guac_client* __guac_alloc_client(GUACIO* io) {
client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp();
client->state = RUNNING; client->state = RUNNING;
client->all_layers = NULL;
client->available_layers = NULL;
client->available_buffers = NULL;
client->next_buffer_index = -1;
return client; return client;
} }
guac_layer* guac_client_alloc_layer(guac_client* client, int index) {
guac_layer* allocd_layer;
/* If available layers, pop off first available layer */
if (client->available_layers != NULL) {
allocd_layer = client->available_layers;
client->available_layers = client->available_layers->next_available;
allocd_layer->next_available = NULL;
}
/* If no available layers, allocate new layer, add to all_layers list */
else {
/* Init new layer */
allocd_layer = malloc(sizeof(guac_layer));
/* Add to all_layers list */
allocd_layer->next = client->all_layers;
client->all_layers = allocd_layer;
}
allocd_layer->index = index;
return allocd_layer;
}
void guac_client_free_layer(guac_client* client, guac_layer* layer) {
layer->next = client->available_layers;
client->available_layers = layer;
}
guac_layer* guac_client_alloc_buffer(guac_client* client) {
guac_layer* allocd_layer;
/* If available layers, pop off first available buffer */
if (client->available_buffers != NULL) {
allocd_layer = client->available_buffers;
client->available_buffers = client->available_buffers->next_available;
allocd_layer->next_available = NULL;
}
/* If no available buffer, allocate new buffer, add to all_layers list */
else {
/* Init new layer */
allocd_layer = malloc(sizeof(guac_layer));
allocd_layer->index = client->next_buffer_index--;
/* Add to all_layers list */
allocd_layer->next = client->all_layers;
client->all_layers = allocd_layer;
}
return allocd_layer;
}
void guac_client_free_buffer(guac_client* client, guac_layer* layer) {
layer->next = client->available_buffers;
client->available_buffers = layer;
}
guac_client* guac_get_client(int client_fd) { guac_client* guac_get_client(int client_fd) {
@ -254,6 +334,13 @@ void guac_free_client(guac_client* client) {
guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); guac_log_error("Could not close client plugin while unloading client: %s", dlerror());
} }
/* Free all layers */
while (client->all_layers != NULL) {
guac_layer* layer = client->all_layers;
client->all_layers = layer->next;
free(layer);
}
free(client); free(client);
} }

View File

@ -273,12 +273,12 @@ int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) {
} }
int guac_send_copy(GUACIO* io, int guac_send_copy(GUACIO* io,
int srcl, int srcx, int srcy, int w, int h, const guac_layer* srcl, int srcx, int srcy, int w, int h,
guac_composite_mode_t mode, int dstl, int dstx, int dsty) { guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) {
return return
guac_write_string(io, "copy:") guac_write_string(io, "copy:")
|| guac_write_int(io, srcl) || guac_write_int(io, srcl->index)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, srcx) || guac_write_int(io, srcx)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
@ -290,7 +290,7 @@ int guac_send_copy(GUACIO* io,
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, mode) || guac_write_int(io, mode)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, dstl) || guac_write_int(io, dstl->index)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, dstx) || guac_write_int(io, dstx)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
@ -311,7 +311,7 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign
} }
int guac_send_png(GUACIO* io, guac_composite_mode_t mode, int guac_send_png(GUACIO* io, guac_composite_mode_t mode,
int layer, int x, int y, cairo_surface_t* surface) { const guac_layer* layer, int x, int y, cairo_surface_t* surface) {
/* Write instruction and args */ /* Write instruction and args */
@ -319,7 +319,7 @@ int guac_send_png(GUACIO* io, guac_composite_mode_t mode,
guac_write_string(io, "png:") guac_write_string(io, "png:")
|| guac_write_int(io, mode) || guac_write_int(io, mode)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, layer) || guac_write_int(io, layer->index)
|| guac_write_string(io, ",") || guac_write_string(io, ",")
|| guac_write_int(io, x) || guac_write_int(io, x)
|| guac_write_string(io, ",") || guac_write_string(io, ",")