diff --git a/libguac/include/client.h b/libguac/include/client.h index b5d6682d..3f4a4a1d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -396,6 +396,22 @@ struct guac_client { */ guac_layer* __last_available_buffer; + /** + * The index of the next available layer. + */ + int __next_layer_index; + + /** + * The head pointer of the list of all available (allocated but not used) + * layers. + */ + guac_layer* __available_layers; + + /** + * Pointer to the last layer in the list of all available layers. + */ + guac_layer* __last_available_layer; + /** * The head pointer of the list of all allocated layers, regardless of use * status. @@ -467,14 +483,13 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru 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. + * Allocates a new layer. An arbitrary index is automatically assigned + * if no existing layer is available for use. * * @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); +guac_layer* guac_client_alloc_layer(guac_client* client); /** * Returns the given buffer to the pool of available buffers, such that it @@ -485,6 +500,16 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ 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 buffer to return to the pool of available layer. + */ +void guac_client_free_layer(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 diff --git a/libguac/src/client.c b/libguac/src/client.c index ac073535..f247bf0b 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -57,18 +57,37 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_layer* guac_client_alloc_layer(guac_client* client, int index) { +guac_layer* guac_client_alloc_layer(guac_client* client) { guac_layer* allocd_layer; - /* Init new layer */ - allocd_layer = malloc(sizeof(guac_layer)); + /* If available layers, pop off first available layer */ + if (client->__next_layer_index >= GUAC_BUFFER_POOL_INITIAL_SIZE && + client->__available_layers != NULL) { - /* Add to __all_layers list */ - allocd_layer->__next = client->__all_layers; - client->__all_layers = allocd_layer; + allocd_layer = client->__available_layers; + client->__available_layers = client->__available_layers->__next_available; + allocd_layer->__next_available = NULL; + + /* If last layer, reset last available layer pointer */ + if (allocd_layer == client->__last_available_layer) + client->__last_available_layer = NULL; + + } + + /* If no available layer, allocate new layer, add to __all_layers list */ + else { + + /* Init new layer */ + allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->index = client->__next_layer_index++; + + /* Add to __all_layers list */ + allocd_layer->__next = client->__all_layers; + client->__all_layers = allocd_layer; + + } - allocd_layer->index = index; return allocd_layer; } @@ -118,6 +137,16 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { } +void guac_client_free_layer(guac_client* client, guac_layer* layer) { + + /* Add layer to tail of pool of available layers */ + if (client->__last_available_layer != NULL) + client->__last_available_layer->__next_available = layer; + + client->__last_available_layer = layer; + +} + guac_client_plugin* guac_client_plugin_open(const char* protocol) { guac_client_plugin* plugin; @@ -222,9 +251,11 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->state = GUAC_CLIENT_RUNNING; client->__all_layers = NULL; - client->__available_buffers = NULL; + client->__available_buffers = client->__last_available_buffer = NULL; + client->__available_layers = client->__last_available_layer = NULL; client->__next_buffer_index = -1; + client->__next_layer_index = 1; if (plugin->init_handler(client, argc, argv) != 0) { free(client);