Merge pull request #88 from glyptodon/copy-mimetypes
GUAC-1305: Copy mimetypes - do not just point instruction storage
This commit is contained in:
commit
6a7b397110
@ -79,6 +79,64 @@ static void guacd_log_handshake_failure() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the given array of mimetypes (strings) into a newly-allocated NULL-
|
||||||
|
* terminated array of strings. Both the array and the strings within the array
|
||||||
|
* are newly-allocated and must be later freed via guacd_free_mimetypes().
|
||||||
|
*
|
||||||
|
* @param mimetypes
|
||||||
|
* The array of mimetypes to copy.
|
||||||
|
*
|
||||||
|
* @param count
|
||||||
|
* The number of mimetypes in the given array.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A newly-allocated, NULL-terminated array containing newly-allocated
|
||||||
|
* copies of each of the mimetypes provided in the original mimetypes
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
static char** guacd_copy_mimetypes(char** mimetypes, int count) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Allocate sufficient space for NULL-terminated array of mimetypes */
|
||||||
|
char** mimetypes_copy = malloc(sizeof(char*) * (count+1));
|
||||||
|
|
||||||
|
/* Copy each provided mimetype */
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
mimetypes_copy[i] = strdup(mimetypes[i]);
|
||||||
|
|
||||||
|
/* Terminate with NULL */
|
||||||
|
mimetypes_copy[count] = NULL;
|
||||||
|
|
||||||
|
return mimetypes_copy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the given array of mimetypes, including the space allocated to each
|
||||||
|
* mimetype string within the array. The provided array of mimetypes MUST have
|
||||||
|
* been allocated with guacd_copy_mimetypes().
|
||||||
|
*
|
||||||
|
* @param mimetypes
|
||||||
|
* The NULL-terminated array of mimetypes to free. This array MUST have
|
||||||
|
* been previously allocated with guacd_copy_mimetypes().
|
||||||
|
*/
|
||||||
|
static void guacd_free_mimetypes(char** mimetypes) {
|
||||||
|
|
||||||
|
char** current_mimetype = mimetypes;
|
||||||
|
|
||||||
|
/* Free all strings within NULL-terminated mimetype array */
|
||||||
|
while (*current_mimetype != NULL) {
|
||||||
|
free(*current_mimetype);
|
||||||
|
current_mimetype++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the array itself, now that its contents have been freed */
|
||||||
|
free(mimetypes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new guac_client for the connection on the given socket, adding
|
* Creates a new guac_client for the connection on the given socket, adding
|
||||||
* it to the client map based on its ID.
|
* it to the client map based on its ID.
|
||||||
@ -164,6 +222,14 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get client */
|
||||||
|
client = guac_client_alloc();
|
||||||
|
if (client == NULL) {
|
||||||
|
guacd_log_guac_error(GUAC_LOG_ERROR, "Unable to create client");
|
||||||
|
guac_socket_free(socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get optimal screen size */
|
/* Get optimal screen size */
|
||||||
size = guac_instruction_expect(
|
size = guac_instruction_expect(
|
||||||
socket, GUACD_USEC_TIMEOUT, "size");
|
socket, GUACD_USEC_TIMEOUT, "size");
|
||||||
@ -174,10 +240,25 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"size\"");
|
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"size\"");
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
|
guac_client_free(client);
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse optimal screen dimensions from size instruction */
|
||||||
|
client->info.optimal_width = atoi(size->argv[0]);
|
||||||
|
client->info.optimal_height = atoi(size->argv[1]);
|
||||||
|
|
||||||
|
/* If DPI given, set the client resolution */
|
||||||
|
if (size->argc >= 3)
|
||||||
|
client->info.optimal_resolution = atoi(size->argv[2]);
|
||||||
|
|
||||||
|
/* Otherwise, use a safe default for rough backwards compatibility */
|
||||||
|
else
|
||||||
|
client->info.optimal_resolution = 96;
|
||||||
|
|
||||||
|
guac_instruction_free(size);
|
||||||
|
|
||||||
/* Get supported audio formats */
|
/* Get supported audio formats */
|
||||||
audio = guac_instruction_expect(
|
audio = guac_instruction_expect(
|
||||||
socket, GUACD_USEC_TIMEOUT, "audio");
|
socket, GUACD_USEC_TIMEOUT, "audio");
|
||||||
@ -188,10 +269,17 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"audio\"");
|
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"audio\"");
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
|
guac_client_free(client);
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store audio mimetypes */
|
||||||
|
client->info.audio_mimetypes =
|
||||||
|
guacd_copy_mimetypes(audio->argv, audio->argc);
|
||||||
|
|
||||||
|
guac_instruction_free(audio);
|
||||||
|
|
||||||
/* Get supported video formats */
|
/* Get supported video formats */
|
||||||
video = guac_instruction_expect(
|
video = guac_instruction_expect(
|
||||||
socket, GUACD_USEC_TIMEOUT, "video");
|
socket, GUACD_USEC_TIMEOUT, "video");
|
||||||
@ -202,10 +290,17 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"video\"");
|
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"video\"");
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
|
guac_client_free(client);
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store video mimetypes */
|
||||||
|
client->info.video_mimetypes =
|
||||||
|
guacd_copy_mimetypes(video->argv, video->argc);
|
||||||
|
|
||||||
|
guac_instruction_free(video);
|
||||||
|
|
||||||
/* Get supported image formats */
|
/* Get supported image formats */
|
||||||
image = guac_instruction_expect(
|
image = guac_instruction_expect(
|
||||||
socket, GUACD_USEC_TIMEOUT, "image");
|
socket, GUACD_USEC_TIMEOUT, "image");
|
||||||
@ -216,10 +311,17 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"image\"");
|
guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"image\"");
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
|
guac_client_free(client);
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store image mimetypes */
|
||||||
|
client->info.image_mimetypes =
|
||||||
|
guacd_copy_mimetypes(image->argv, image->argc);
|
||||||
|
|
||||||
|
guac_instruction_free(image);
|
||||||
|
|
||||||
/* Get args from connect instruction */
|
/* Get args from connect instruction */
|
||||||
connect = guac_instruction_expect(
|
connect = guac_instruction_expect(
|
||||||
socket, GUACD_USEC_TIMEOUT, "connect");
|
socket, GUACD_USEC_TIMEOUT, "connect");
|
||||||
@ -233,14 +335,7 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log_guac_error(GUAC_LOG_WARNING,
|
guacd_log_guac_error(GUAC_LOG_WARNING,
|
||||||
"Unable to close client plugin");
|
"Unable to close client plugin");
|
||||||
|
|
||||||
guac_socket_free(socket);
|
guac_client_free(client);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get client */
|
|
||||||
client = guac_client_alloc();
|
|
||||||
if (client == NULL) {
|
|
||||||
guacd_log_guac_error(GUAC_LOG_ERROR, "Unable to create client");
|
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -248,36 +343,6 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
client->socket = socket;
|
client->socket = socket;
|
||||||
client->log_handler = guacd_client_log;
|
client->log_handler = guacd_client_log;
|
||||||
|
|
||||||
/* Parse optimal screen dimensions from size instruction */
|
|
||||||
client->info.optimal_width = atoi(size->argv[0]);
|
|
||||||
client->info.optimal_height = atoi(size->argv[1]);
|
|
||||||
|
|
||||||
/* If DPI given, set the client resolution */
|
|
||||||
if (size->argc >= 3)
|
|
||||||
client->info.optimal_resolution = atoi(size->argv[2]);
|
|
||||||
|
|
||||||
/* Otherwise, use a safe default for rough backwards compatibility */
|
|
||||||
else
|
|
||||||
client->info.optimal_resolution = 96;
|
|
||||||
|
|
||||||
/* Store audio mimetypes */
|
|
||||||
client->info.audio_mimetypes = malloc(sizeof(char*) * (audio->argc+1));
|
|
||||||
memcpy(client->info.audio_mimetypes, audio->argv,
|
|
||||||
sizeof(char*) * audio->argc);
|
|
||||||
client->info.audio_mimetypes[audio->argc] = NULL;
|
|
||||||
|
|
||||||
/* Store video mimetypes */
|
|
||||||
client->info.video_mimetypes = malloc(sizeof(char*) * (video->argc+1));
|
|
||||||
memcpy(client->info.video_mimetypes, video->argv,
|
|
||||||
sizeof(char*) * video->argc);
|
|
||||||
client->info.video_mimetypes[video->argc] = NULL;
|
|
||||||
|
|
||||||
/* Store image mimetypes */
|
|
||||||
client->info.image_mimetypes = malloc(sizeof(char*) * (image->argc+1));
|
|
||||||
memcpy(client->info.image_mimetypes, image->argv,
|
|
||||||
sizeof(char*) * image->argc);
|
|
||||||
client->info.image_mimetypes[image->argc] = NULL;
|
|
||||||
|
|
||||||
/* Store client */
|
/* Store client */
|
||||||
if (guacd_client_map_add(map, client))
|
if (guacd_client_map_add(map, client))
|
||||||
guacd_log(GUAC_LOG_ERROR, "Unable to add client. Internal client storage has failed");
|
guacd_log(GUAC_LOG_ERROR, "Unable to add client. Internal client storage has failed");
|
||||||
@ -319,15 +384,9 @@ static void guacd_handle_connection(guacd_client_map* map, guac_socket* socket)
|
|||||||
guacd_log(GUAC_LOG_ERROR, "Unable to remove client. Internal client storage has failed");
|
guacd_log(GUAC_LOG_ERROR, "Unable to remove client. Internal client storage has failed");
|
||||||
|
|
||||||
/* Free mimetype lists */
|
/* Free mimetype lists */
|
||||||
free(client->info.audio_mimetypes);
|
guacd_free_mimetypes(client->info.audio_mimetypes);
|
||||||
free(client->info.video_mimetypes);
|
guacd_free_mimetypes(client->info.video_mimetypes);
|
||||||
free(client->info.image_mimetypes);
|
guacd_free_mimetypes(client->info.image_mimetypes);
|
||||||
|
|
||||||
/* Free remaining instructions */
|
|
||||||
guac_instruction_free(audio);
|
|
||||||
guac_instruction_free(video);
|
|
||||||
guac_instruction_free(image);
|
|
||||||
guac_instruction_free(size);
|
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
guac_client_free(client);
|
guac_client_free(client);
|
||||||
|
@ -451,7 +451,7 @@ void guac_client_stream_webp(guac_client* client, guac_socket* socket,
|
|||||||
int guac_client_supports_webp(guac_client* client) {
|
int guac_client_supports_webp(guac_client* client) {
|
||||||
|
|
||||||
#ifdef ENABLE_WEBP
|
#ifdef ENABLE_WEBP
|
||||||
const char** mimetype = client->info.image_mimetypes;
|
char** mimetype = client->info.image_mimetypes;
|
||||||
|
|
||||||
/* Search for WebP mimetype in list of supported image mimetypes */
|
/* Search for WebP mimetype in list of supported image mimetypes */
|
||||||
while (*mimetype != NULL) {
|
while (*mimetype != NULL) {
|
||||||
|
@ -65,20 +65,20 @@ struct guac_client_info {
|
|||||||
* NULL-terminated array of client-supported audio mimetypes. If the client
|
* NULL-terminated array of client-supported audio mimetypes. If the client
|
||||||
* does not support audio at all, this will be NULL.
|
* does not support audio at all, this will be NULL.
|
||||||
*/
|
*/
|
||||||
const char** audio_mimetypes;
|
char** audio_mimetypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NULL-terminated array of client-supported video mimetypes. If the client
|
* NULL-terminated array of client-supported video mimetypes. If the client
|
||||||
* does not support video at all, this will be NULL.
|
* does not support video at all, this will be NULL.
|
||||||
*/
|
*/
|
||||||
const char** video_mimetypes;
|
char** video_mimetypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NULL-terminated array of client-supported image mimetypes. Though all
|
* NULL-terminated array of client-supported image mimetypes. Though all
|
||||||
* supported image mimetypes will be listed here, it can be safely assumed
|
* supported image mimetypes will be listed here, it can be safely assumed
|
||||||
* that all clients will support at least "image/png" and "image/jpeg".
|
* that all clients will support at least "image/png" and "image/jpeg".
|
||||||
*/
|
*/
|
||||||
const char** image_mimetypes;
|
char** image_mimetypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DPI of the physical remote display if configured for the optimal
|
* The DPI of the physical remote display if configured for the optimal
|
||||||
|
Loading…
Reference in New Issue
Block a user