diff --git a/guacamole/libguac/include/protocol.h b/guacamole/libguac/include/protocol.h index 47f3ba3be..685a112bb 100644 --- a/guacamole/libguac/include/protocol.h +++ b/guacamole/libguac/include/protocol.h @@ -58,7 +58,19 @@ typedef struct guac_instruction { /** - * Frees all memory allocated to the given instruction. + * Frees all memory allocated to the given instruction opcode + * and arguments. The instruction structure itself will not + * be freed. + * + * @param instruction The instruction to free. + */ +void guac_free_instruction_data(guac_instruction* instruction); + + +/** + * Frees all memory allocated to the given instruction. This + * includes freeing memory allocated for the structure + * itself. * * @param instruction The instruction to free. */ diff --git a/guacamole/libguac/src/client.c b/guacamole/libguac/src/client.c index 375e00bd7..ee4ee0158 100644 --- a/guacamole/libguac/src/client.c +++ b/guacamole/libguac/src/client.c @@ -76,7 +76,6 @@ guac_client* guac_get_client(int client_fd) { GUACIO* io = guac_open(client_fd); /* Pluggable client */ - char* protocol; char protocol_lib[256] = "libguac_client_"; union { @@ -86,33 +85,65 @@ guac_client* guac_get_client(int client_fd) { char* error; - strcat(protocol_lib, protocol); - strcat(protocol_lib, ".so"); + /* Client arguments */ + int argc; + char** argv; + + /* Connect instruction */ + guac_instruction instruction; + + /* Wait for connect instruction */ + for (;;) { + + int result = guac_read_instruction(io, &instruction); + if (result < 0) { + syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + return NULL; + } + + /* Connect instruction read */ + if (result > 0 && strcmp(instruction.opcode, "connect") == 0) { + + /* Get protocol from message */ + char* protocol = instruction.argv[0]; + + strcat(protocol_lib, protocol); + strcat(protocol_lib, ".so"); + + /* Create new client */ + client = __guac_alloc_client(io); + + /* Load client plugin */ + client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); + if (!(client->client_plugin_handle)) { + fprintf(stderr, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + exit(EXIT_FAILURE); + } + + dlerror(); /* Clear errors */ + + /* Get init function */ + alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); + + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not get guac_client_init in plugin: %s\n", error); + exit(EXIT_FAILURE); + } + + /* Initialize client arguments */ + argc = instruction.argc; + argv = instruction.argv; + + break; + } - /* Load client plugin */ - client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); - if (!(client->client_plugin_handle)) { - fprintf(stderr, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); - exit(EXIT_FAILURE); } - dlerror(); /* Clear errors */ - - /* Get init function */ - alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); - - if ((error = dlerror()) != NULL) { - fprintf(stderr, "Could not get guac_client_init in plugin: %s\n", error); - exit(EXIT_FAILURE); - } - - - /* Create new client */ - client = __guac_alloc_client(io); - if (alias.client_init(client, argc, argv) != 0) return NULL; + guac_free_instruction_data(&instruction); + return client; } @@ -179,6 +210,7 @@ void guac_start_client(guac_client* client) { ) { syslog(LOG_ERR, "Error handling mouse instruction"); + guac_free_instruction_data(&instruction); return; } @@ -195,6 +227,7 @@ void guac_start_client(guac_client* client) { ) { syslog(LOG_ERR, "Error handling key instruction"); + guac_free_instruction_data(&instruction); return; } @@ -210,6 +243,7 @@ void guac_start_client(guac_client* client) { ) { syslog(LOG_ERR, "Error handling clipboard instruction"); + guac_free_instruction_data(&instruction); return; } @@ -217,9 +251,12 @@ void guac_start_client(guac_client* client) { else if (strcmp(instruction.opcode, "disconnect") == 0) { syslog(LOG_INFO, "Client requested disconnect"); + guac_free_instruction_data(&instruction); return; } + guac_free_instruction_data(&instruction); + } while ((retval = guac_read_instruction(io, &instruction)) > 0); if (retval < 0) { diff --git a/guacamole/libguac/src/protocol.c b/guacamole/libguac/src/protocol.c index e0bb9096d..a084d7b74 100644 --- a/guacamole/libguac/src/protocol.c +++ b/guacamole/libguac/src/protocol.c @@ -441,12 +441,15 @@ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { } -void guac_free_instruction(guac_instruction* instruction) { +void guac_free_instruction_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); free(instruction); }