GUAC-1172: Add instruction handlers and storage for Guacamole protocol objects.

This commit is contained in:
Michael Jumper 2015-06-19 14:12:27 -07:00
parent df791b057b
commit f7e6deeaf4
9 changed files with 303 additions and 1 deletions

View File

@ -41,6 +41,8 @@ libguacinc_HEADERS = \
guacamole/instruction-types.h \ guacamole/instruction-types.h \
guacamole/layer.h \ guacamole/layer.h \
guacamole/layer-types.h \ guacamole/layer-types.h \
guacamole/object.h \
guacamole/object-types.h \
guacamole/plugin-constants.h \ guacamole/plugin-constants.h \
guacamole/plugin.h \ guacamole/plugin.h \
guacamole/plugin-types.h \ guacamole/plugin-types.h \

View File

@ -25,6 +25,7 @@
#include "client.h" #include "client.h"
#include "client-handlers.h" #include "client-handlers.h"
#include "instruction.h" #include "instruction.h"
#include "object.h"
#include "protocol.h" #include "protocol.h"
#include "stream.h" #include "stream.h"
#include "timestamp.h" #include "timestamp.h"
@ -47,6 +48,8 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = {
{"ack", __guac_handle_ack}, {"ack", __guac_handle_ack},
{"blob", __guac_handle_blob}, {"blob", __guac_handle_blob},
{"end", __guac_handle_end}, {"end", __guac_handle_end},
{"get", __guac_handle_get},
{"put", __guac_handle_put},
{NULL, NULL} {NULL, NULL}
}; };
@ -319,6 +322,77 @@ int __guac_handle_end(guac_client* client, guac_instruction* instruction) {
return result; return result;
} }
int __guac_handle_get(guac_client* client, guac_instruction* instruction) {
guac_object* object;
/* Validate object index */
int object_index = atoi(instruction->argv[0]);
if (object_index < 0 || object_index >= GUAC_CLIENT_MAX_OBJECTS)
return 0;
object = &(client->__objects[object_index]);
/* Validate initialization of object */
if (object->index == GUAC_CLIENT_UNDEFINED_OBJECT_INDEX)
return 0;
/* Call object handler if defined */
if (object->get_handler)
return object->get_handler(client, object,
instruction->argv[1] /* name */
);
/* Fall back to global handler if defined */
if (client->get_handler)
return client->get_handler(client, object,
instruction->argv[1] /* name */
);
return 0;
}
int __guac_handle_put(guac_client* client, guac_instruction* instruction) {
guac_object* object;
/* Validate object index */
int object_index = atoi(instruction->argv[0]);
if (object_index < 0 || object_index >= GUAC_CLIENT_MAX_OBJECTS)
return 0;
object = &(client->__objects[object_index]);
/* Validate initialization of object */
if (object->index == GUAC_CLIENT_UNDEFINED_OBJECT_INDEX)
return 0;
/* Pull corresponding stream */
int stream_index = atoi(instruction->argv[1]);
guac_stream* stream = __init_input_stream(client, stream_index);
if (stream == NULL)
return 0;
/* Call object handler if defined */
if (object->put_handler)
return object->put_handler(client, object, stream,
instruction->argv[2], /* mimetype */
instruction->argv[3] /* name */
);
/* Fall back to global handler if defined */
if (client->put_handler)
return client->put_handler(client, object, stream,
instruction->argv[2], /* mimetype */
instruction->argv[3] /* name */
);
/* Otherwise, abort */
guac_protocol_send_ack(client->socket, stream,
"Object write unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED);
return 0;
}
int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) { int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) {
guac_client_stop(client); guac_client_stop(client);
return 0; return 0;

View File

@ -122,6 +122,20 @@ int __guac_handle_blob(guac_client* client, guac_instruction* instruction);
*/ */
int __guac_handle_end(guac_client* client, guac_instruction* instruction); int __guac_handle_end(guac_client* client, guac_instruction* instruction);
/**
* Internal initial handler for the get instruction. When a get instruction
* is received, this handler will be called. The client's get handler will
* be invoked if defined.
*/
int __guac_handle_get(guac_client* client, guac_instruction* instruction);
/**
* Internal initial handler for the put instruction. When a put instruction
* is received, this handler will be called. The client's put handler will
* be invoked if defined.
*/
int __guac_handle_put(guac_client* client, guac_instruction* instruction);
/** /**
* Internal initial handler for the size instruction. When a size instruction * Internal initial handler for the size instruction. When a size instruction
* is received, this handler will be called. The client's size handler will * is received, this handler will be called. The client's size handler will

View File

@ -27,6 +27,7 @@
#include "error.h" #include "error.h"
#include "instruction.h" #include "instruction.h"
#include "layer.h" #include "layer.h"
#include "object.h"
#include "pool.h" #include "pool.h"
#include "protocol.h" #include "protocol.h"
#include "socket.h" #include "socket.h"
@ -216,7 +217,7 @@ guac_client* guac_client_alloc() {
/* Allocate stream pool */ /* Allocate stream pool */
client->__stream_pool = guac_pool_alloc(0); client->__stream_pool = guac_pool_alloc(0);
/* Initialze streams */ /* Initialize streams */
client->__input_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS); client->__input_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS);
client->__output_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS); client->__output_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS);
@ -225,6 +226,11 @@ guac_client* guac_client_alloc() {
client->__output_streams[i].index = GUAC_CLIENT_CLOSED_STREAM_INDEX; client->__output_streams[i].index = GUAC_CLIENT_CLOSED_STREAM_INDEX;
} }
/* Initialize objects */
client->__objects = malloc(sizeof(guac_object) * GUAC_CLIENT_MAX_OBJECTS);
for (i=0; i<GUAC_CLIENT_MAX_OBJECTS; i++)
client->__objects[i].index = GUAC_CLIENT_UNDEFINED_OBJECT_INDEX;
return client; return client;
} }
@ -246,6 +252,9 @@ void guac_client_free(guac_client* client) {
free(client->__input_streams); free(client->__input_streams);
free(client->__output_streams); free(client->__output_streams);
/* Free objects */
free(client->__objects);
/* Free stream pool */ /* Free stream pool */
guac_pool_free(client->__stream_pool); guac_pool_free(client->__stream_pool);

View File

@ -39,6 +39,16 @@
*/ */
#define GUAC_CLIENT_CLOSED_STREAM_INDEX -1 #define GUAC_CLIENT_CLOSED_STREAM_INDEX -1
/**
* The maximum number of objects supported by any one guac_client.
*/
#define GUAC_CLIENT_MAX_OBJECTS 64
/**
* The index of an object which has not been defined.
*/
#define GUAC_CLIENT_UNDEFINED_OBJECT_INDEX -1
/** /**
* The flag set in the mouse button mask when the left mouse button is down. * The flag set in the mouse button mask when the left mouse button is down.
*/ */

View File

@ -31,6 +31,7 @@
*/ */
#include "client-types.h" #include "client-types.h"
#include "object-types.h"
#include "protocol-types.h" #include "protocol-types.h"
#include "stream-types.h" #include "stream-types.h"
@ -92,6 +93,18 @@ typedef int guac_client_ack_handler(guac_client* client, guac_stream* stream,
*/ */
typedef int guac_client_end_handler(guac_client* client, guac_stream* stream); typedef int guac_client_end_handler(guac_client* client, guac_stream* stream);
/**
* Handler for Guacamole object get events.
*/
typedef int guac_client_get_handler(guac_client* client, guac_object* object,
char* name);
/**
* Handler for Guacamole object put events.
*/
typedef int guac_client_put_handler(guac_client* client, guac_object* object,
guac_stream* stream, char* mimetype, char* name);
/** /**
* Handler for Guacamole audio format events. * Handler for Guacamole audio format events.
*/ */

View File

@ -34,6 +34,7 @@
#include "client-constants.h" #include "client-constants.h"
#include "instruction-types.h" #include "instruction-types.h"
#include "layer-types.h" #include "layer-types.h"
#include "object-types.h"
#include "pool-types.h" #include "pool-types.h"
#include "socket-types.h" #include "socket-types.h"
#include "stream-types.h" #include "stream-types.h"
@ -366,6 +367,46 @@ struct guac_client {
*/ */
guac_client_log_handler* log_handler; guac_client_log_handler* log_handler;
/**
* Handler for get events sent by the Guacamole web-client.
*
* The handler takes a guac_object, containing the object index which will
* persist through the duration of the transfer, and the name of the stream
* being requested. It is up to the get handler to create the required body
* stream.
*
* Example:
* @code
* int get_handler(guac_client* client, guac_object* object,
* char* name);
*
* int guac_client_init(guac_client* client, int argc, char** argv) {
* client->get_handler = get_handler;
* }
* @endcode
*/
guac_client_get_handler* get_handler;
/**
* Handler for put events sent by the Guacamole web-client.
*
* The handler takes a guac_object and guac_stream, which each contain their
* respective indices which will persist through the duration of the
* transfer, the mimetype of the data being transferred, and the name of
* the stream within the object being written to.
*
* Example:
* @code
* int put_handler(guac_client* client, guac_object* object,
* guac_stream* stream, char* mimetype, char* name);
*
* int guac_client_init(guac_client* client, int argc, char** argv) {
* client->put_handler = put_handler;
* }
* @endcode
*/
guac_client_put_handler* put_handler;
/** /**
* Pool of buffer indices. Buffers are simply layers with negative indices. * Pool of buffer indices. Buffers are simply layers with negative indices.
* Note that because guac_pool always gives non-negative indices starting * Note that because guac_pool always gives non-negative indices starting
@ -395,6 +436,11 @@ struct guac_client {
*/ */
guac_stream* __input_streams; guac_stream* __input_streams;
/**
* All available objects (arbitrary sets of named streams).
*/
guac_object* __objects;
/** /**
* The unique identifier allocated for the connection, which may * The unique identifier allocated for the connection, which may
* be used within the Guacamole protocol to refer to this connection. * be used within the Guacamole protocol to refer to this connection.

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef GUAC_OBJECT_TYPES_H
#define GUAC_OBJECT_TYPES_H
/**
* Type definitions related to Guacamole protocol objects.
*
* @file object-types.h
*/
/**
* Represents a single object within the Guacamole protocol.
*/
typedef struct guac_object guac_object;
#endif

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef GUAC_OBJECT_H
#define GUAC_OBJECT_H
/**
* Provides functions and structures required for allocating and using objects.
*
* @file object.h
*/
#include "client-fntypes.h"
#include "object-types.h"
struct guac_object {
/**
* The index of this object.
*/
int index;
/**
* Arbitrary data associated with this object.
*/
void* data;
/**
* Handler for get events sent by the Guacamole web-client.
*
* The handler takes a guac_object, containing the object index which will
* persist through the duration of the transfer, and the name of the stream
* being requested. It is up to the get handler to create the required body
* stream.
*
* Example:
* @code
* int get_handler(guac_client* client, guac_object* object,
* char* name);
*
* int some_function(guac_client* client) {
*
* guac_object* object = guac_client_alloc_object(client);
* object->get_handler = get_handler;
*
* }
* @endcode
*/
guac_client_get_handler* get_handler;
/**
* Handler for put events sent by the Guacamole web-client.
*
* The handler takes a guac_object and guac_stream, which each contain their
* respective indices which will persist through the duration of the
* transfer, the mimetype of the data being transferred, and the name of
* the stream within the object being written to.
*
* Example:
* @code
* int put_handler(guac_client* client, guac_object* object,
* guac_stream* stream, char* mimetype, char* name);
*
* int some_function(guac_client* client) {
*
* guac_object* object = guac_client_alloc_object(client);
* object->put_handler = put_handler;
*
* }
* @endcode
*/
guac_client_put_handler* put_handler;
};
#endif