GUACAMOLE-25: Abstract DVC management away from FreeRDP for sake of API compatibility.
This commit is contained in:
parent
46bdf0692f
commit
1393358469
@ -26,6 +26,7 @@ libguac_client_rdp_la_SOURCES = \
|
||||
_generated_keymaps.c \
|
||||
audio_input.c \
|
||||
client.c \
|
||||
dvc.c \
|
||||
input.c \
|
||||
ptr_string.c \
|
||||
rdp.c \
|
||||
@ -91,6 +92,7 @@ noinst_HEADERS = \
|
||||
guac_svc/svc_service.h \
|
||||
audio_input.h \
|
||||
client.h \
|
||||
dvc.h \
|
||||
input.h \
|
||||
ptr_string.h \
|
||||
rdp.h \
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "audio_input.h"
|
||||
#include "dvc.h"
|
||||
#include "ptr_string.h"
|
||||
#include "rdp.h"
|
||||
|
||||
@ -71,17 +72,12 @@ int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) {
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_audio_load_plugin(rdpContext* context) {
|
||||
void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
|
||||
/* Add "AUDIO_INPUT" channel */
|
||||
ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV));
|
||||
args->argc = 2;
|
||||
args->argv = malloc(sizeof(char**) * 2);
|
||||
args->argv[0] = strdup("guacai");
|
||||
args->argv[1] = guac_rdp_ptr_to_string(client);
|
||||
freerdp_dynamic_channel_collection_add(context->settings, args);
|
||||
guac_rdp_dvc_list_add(list, "guacai", guac_rdp_ptr_to_string(client), NULL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define GUAC_RDP_AUDIO_INPUT_H
|
||||
|
||||
#include "config.h"
|
||||
#include "dvc.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/stream.h>
|
||||
@ -213,7 +214,7 @@ guac_user_end_handler guac_rdp_audio_end_handler;
|
||||
* @param context
|
||||
* The rdpContext associated with the active RDP session.
|
||||
*/
|
||||
void guac_rdp_audio_load_plugin(rdpContext* context);
|
||||
void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list);
|
||||
|
||||
#endif
|
||||
|
||||
|
154
src/protocols/rdp/dvc.c
Normal file
154
src/protocols/rdp/dvc.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "dvc.h"
|
||||
#include "guac_list.h"
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
guac_rdp_dvc_list* guac_rdp_dvc_list_alloc() {
|
||||
|
||||
guac_rdp_dvc_list* list = malloc(sizeof(guac_rdp_dvc_list));
|
||||
|
||||
/* Initialize with empty backing list */
|
||||
list->channels = guac_common_list_alloc();
|
||||
list->channel_count = 0;
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_dvc_list_add(guac_rdp_dvc_list* list, const char* name, ...) {
|
||||
|
||||
va_list args;
|
||||
|
||||
guac_rdp_dvc* dvc = malloc(sizeof(guac_rdp_dvc));
|
||||
|
||||
va_start(args, name);
|
||||
|
||||
/* Count number of arguments (excluding terminating NULL) */
|
||||
dvc->argc = 1;
|
||||
while (va_arg(args, char*) != NULL)
|
||||
dvc->argc++;
|
||||
|
||||
/* Reset va_list */
|
||||
va_end(args);
|
||||
va_start(args, name);
|
||||
|
||||
/* Copy argument values into DVC entry */
|
||||
dvc->argv = malloc(sizeof(char*) * dvc->argc);
|
||||
dvc->argv[0] = strdup(name);
|
||||
int i;
|
||||
for (i = 1; i < dvc->argc; i++)
|
||||
dvc->argv[i] = strdup(va_arg(args, char*));
|
||||
|
||||
va_end(args);
|
||||
|
||||
/* Add entry to DVC list */
|
||||
guac_common_list_add(list->channels, dvc);
|
||||
|
||||
/* Update channel count */
|
||||
list->channel_count++;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_dvc_list_free(guac_rdp_dvc_list* list) {
|
||||
|
||||
/* For each channel */
|
||||
guac_common_list_element* current = list->channels->head;
|
||||
while (current != NULL) {
|
||||
|
||||
/* Free arguments declaration for current channel */
|
||||
guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data;
|
||||
|
||||
/* Free the underlying arguments list if not delegated to FreeRDP */
|
||||
if (dvc->argv != NULL) {
|
||||
|
||||
/* Free each argument value */
|
||||
for (int i = 0; i < dvc->argc; i++)
|
||||
free(dvc->argv[i]);
|
||||
|
||||
free(dvc->argv);
|
||||
}
|
||||
|
||||
free(dvc);
|
||||
|
||||
current = current->next;
|
||||
|
||||
}
|
||||
|
||||
/* Free underlying list */
|
||||
guac_common_list_free(list->channels);
|
||||
|
||||
/* Free the DVC list itself */
|
||||
free(list);
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdpChannels* channels = context->channels;
|
||||
|
||||
/* Skip if no channels will be loaded */
|
||||
if (list->channel_count == 0)
|
||||
return 0;
|
||||
|
||||
/* For each channel */
|
||||
guac_common_list_element* current = list->channels->head;
|
||||
while (current != NULL) {
|
||||
|
||||
/* Get channel arguments */
|
||||
guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data;
|
||||
current = current->next;
|
||||
|
||||
/* guac_rdp_dvc_list_add() guarantees at one argument */
|
||||
assert(dvc->argc >= 1);
|
||||
|
||||
/* guac_rdp_load_drdynvc() MUST only be invoked once */
|
||||
assert(dvc->argv != NULL);
|
||||
|
||||
/* Log registration of plugin for current channel */
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Registering DVC plugin \"%s\"", dvc->argv[0]);
|
||||
|
||||
/* Register plugin with FreeRDP */
|
||||
ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV));
|
||||
args->argc = dvc->argc;
|
||||
args->argv = dvc->argv;
|
||||
freerdp_dynamic_channel_collection_add(context->settings, args);
|
||||
|
||||
/* Rely on FreeRDP to free argv storage */
|
||||
dvc->argv = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Load virtual channel management plugin */
|
||||
return freerdp_channels_load_plugin(channels, context->settings,
|
||||
"drdynvc", context->settings);
|
||||
|
||||
}
|
||||
|
138
src/protocols/rdp/dvc.h
Normal file
138
src/protocols/rdp/dvc.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_RDP_DVC_H
|
||||
#define GUAC_RDP_DVC_H
|
||||
|
||||
#include "config.h"
|
||||
#include "guac_list.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
/**
|
||||
* The set of all arguments that should be passed to a given dynamic virtual
|
||||
* channel plugin, including the name of that plugin.
|
||||
*/
|
||||
typedef struct guac_rdp_dvc {
|
||||
|
||||
/**
|
||||
* The number of arguments in the argv array. This MUST be at least 1.
|
||||
*/
|
||||
int argc;
|
||||
|
||||
/**
|
||||
* The argument values being passed to the dynamic virtual channel plugin.
|
||||
* The first entry in this array is always the name of the plugin. If
|
||||
* guac_rdp_load_drdynvc() has been invoked, and freeing the argument
|
||||
* values is being delegated to FreeRDP, this will be NULL.
|
||||
*/
|
||||
char** argv;
|
||||
|
||||
} guac_rdp_dvc;
|
||||
|
||||
/**
|
||||
* A list of dynamic virtual channels which should be provided to the DRDYNVC
|
||||
* plugin once loaded via guac_rdp_load_drdynvc(). This interface exists purely
|
||||
* to bridge incompatibilities between differing versions of FreeRDP and its
|
||||
* DRDYNVC plugin. Any allocated guac_rdp_dvc_list is unlikely to be needed
|
||||
* after the DRDYNVC plugin has been loaded.
|
||||
*/
|
||||
typedef struct guac_rdp_dvc_list {
|
||||
|
||||
/**
|
||||
* Array of all dynamic virtual channels which should be registered with
|
||||
* the DRDYNVC plugin once loaded. Each list element will point to a
|
||||
* guac_rdp_dvc structure which must eventually be freed.
|
||||
*/
|
||||
guac_common_list* channels;
|
||||
|
||||
/**
|
||||
* The number of channels within the list.
|
||||
*/
|
||||
int channel_count;
|
||||
|
||||
} guac_rdp_dvc_list;
|
||||
|
||||
/**
|
||||
* Allocates a new, empty list of dynamic virtual channels. New channels may
|
||||
* be added via guac_rdp_dvc_list_add(). The loading of those channels'
|
||||
* associated plugins will be deferred until guac_rdp_load_drdynvc() is
|
||||
* invoked.
|
||||
*
|
||||
* @return
|
||||
* A newly-allocated, empty list of dynamic virtual channels.
|
||||
*/
|
||||
guac_rdp_dvc_list* guac_rdp_dvc_list_alloc();
|
||||
|
||||
/**
|
||||
* Adds the given dynamic virtual channel plugin name and associated arguments
|
||||
* to the list. The provied arguments list is NOT optional and MUST be
|
||||
* NULL-terminated, even if there are no arguments for the named dynamic
|
||||
* virtual channel plugin. Though FreeRDP requires that the arguments for a
|
||||
* dynamic virtual channel plugin contain the name of the plugin itself as the
|
||||
* first argument, the name must be excluded from the arguments provided here.
|
||||
* This function will automatically take care of adding the plugin name to
|
||||
* the arguments.
|
||||
*
|
||||
* @param list
|
||||
* The guac_rdp_dvc_list to which the given plugin name and arguments
|
||||
* should be added, for later bulk registration via
|
||||
* guac_rdp_load_drdynvc().
|
||||
*
|
||||
* @param name
|
||||
* The name of the dynamic virtual channel plugin that should be given
|
||||
* the provided arguments when guac_rdp_load_drdynvc() is invoked.
|
||||
*
|
||||
* @param ...
|
||||
* The string (char*) arguments which should be passed to the dynamic
|
||||
* virtual channel plugin when it is loaded via guac_rdp_load_drdynvc(),
|
||||
* excluding the plugin name itself.
|
||||
*/
|
||||
void guac_rdp_dvc_list_add(guac_rdp_dvc_list* list, const char* name, ...);
|
||||
|
||||
/**
|
||||
* Frees the given list of dynamic virtual channels. Note that, while each
|
||||
* individual entry within this list will be freed, it is partially up to
|
||||
* FreeRDP to free the storage associated with the arguments passed to the
|
||||
* virtual channels.
|
||||
*
|
||||
* @param list
|
||||
* The list to free.
|
||||
*/
|
||||
void guac_rdp_dvc_list_free(guac_rdp_dvc_list* list);
|
||||
|
||||
/**
|
||||
* Loads FreeRDP's DRDYNVC plugin and registers the dynamic virtual channel
|
||||
* plugins described by the given guac_rdp_dvc_list. This function MUST be
|
||||
* invoked no more than once per RDP connection. Invoking this function
|
||||
* multiple times, even if the guac_rdp_dvc_list is different each time, will
|
||||
* result in undefined behavior.
|
||||
*
|
||||
* @param context
|
||||
* The rdpContext associated with the RDP connection for which the DRDYNVC
|
||||
* plugin should be loaded.
|
||||
*
|
||||
* @param list
|
||||
* A guac_rdp_dvc_list describing the dynamic virtual channel plugins that
|
||||
* should be registered with the DRDYNVC plugin, along with any arguments.
|
||||
*/
|
||||
int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list);
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "audio_input.h"
|
||||
#include "client.h"
|
||||
#include "dvc.h"
|
||||
#include "guac_cursor.h"
|
||||
#include "guac_display.h"
|
||||
#include "guac_recording.h"
|
||||
@ -212,6 +213,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
rdpPrimaryUpdate* primary;
|
||||
CLRCONV* clrconv;
|
||||
|
||||
guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc();
|
||||
|
||||
#ifdef HAVE_FREERDP_REGISTER_ADDIN_PROVIDER
|
||||
/* Init FreeRDP add-in provider */
|
||||
@ -224,34 +226,17 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
(pChannelConnectedEventHandler) guac_rdp_channel_connected);
|
||||
#endif
|
||||
|
||||
/* Load DRDYNVC plugin if required */
|
||||
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE
|
||||
|| settings->enable_audio_input) {
|
||||
|
||||
/* Load virtual channel management plugin */
|
||||
if (freerdp_channels_load_plugin(channels, instance->settings,
|
||||
"drdynvc", instance->settings))
|
||||
guac_client_log(client, GUAC_LOG_WARNING,
|
||||
"Failed to load drdynvc plugin. Display update and audio "
|
||||
"input support will be disabled.");
|
||||
|
||||
/* Init display update plugin if "drdynvc" was loaded successfully */
|
||||
else {
|
||||
#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT
|
||||
/* Load "disp" plugin for display update */
|
||||
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE)
|
||||
guac_rdp_disp_load_plugin(instance->context);
|
||||
/* Load "disp" plugin for display update */
|
||||
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE)
|
||||
guac_rdp_disp_load_plugin(instance->context, dvc_list);
|
||||
#endif
|
||||
|
||||
/* Load "AUDIO_INPUT" plugin for audio input*/
|
||||
if (settings->enable_audio_input) {
|
||||
rdp_client->audio_input = guac_rdp_audio_buffer_alloc();
|
||||
guac_rdp_audio_load_plugin(instance->context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} /* end if drdynvc required */
|
||||
/* Load "AUDIO_INPUT" plugin for audio input*/
|
||||
if (settings->enable_audio_input) {
|
||||
rdp_client->audio_input = guac_rdp_audio_buffer_alloc();
|
||||
guac_rdp_audio_load_plugin(instance->context, dvc_list);
|
||||
}
|
||||
|
||||
/* Load clipboard plugin */
|
||||
if (freerdp_channels_load_plugin(channels, instance->settings,
|
||||
@ -338,6 +323,15 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
|
||||
}
|
||||
|
||||
/* Load DRDYNVC plugin if required */
|
||||
if (guac_rdp_load_drdynvc(instance->context, dvc_list))
|
||||
guac_client_log(client, GUAC_LOG_WARNING,
|
||||
"Failed to load drdynvc plugin. Display update and audio "
|
||||
"input support will be disabled.");
|
||||
|
||||
/* Dynamic virtual channel list is no longer needed */
|
||||
guac_rdp_dvc_list_free(dvc_list);
|
||||
|
||||
/* Init color conversion structure */
|
||||
clrconv = calloc(1, sizeof(CLRCONV));
|
||||
clrconv->alpha = 1;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
#include "dvc.h"
|
||||
#include "rdp.h"
|
||||
#include "rdp_disp.h"
|
||||
#include "rdp_settings.h"
|
||||
@ -54,20 +55,14 @@ void guac_rdp_disp_free(guac_rdp_disp* disp) {
|
||||
free(disp);
|
||||
}
|
||||
|
||||
void guac_rdp_disp_load_plugin(rdpContext* context) {
|
||||
void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) {
|
||||
|
||||
#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT
|
||||
#ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL
|
||||
context->settings->SupportDisplayControl = TRUE;
|
||||
#endif
|
||||
|
||||
/* Add "disp" channel */
|
||||
ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV));
|
||||
args->argc = 1;
|
||||
args->argv = malloc(sizeof(char**) * 1);
|
||||
args->argv[0] = strdup("disp");
|
||||
freerdp_dynamic_channel_collection_add(context->settings, args);
|
||||
#endif
|
||||
guac_rdp_dvc_list_add(list, "disp", NULL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#ifndef GUAC_RDP_DISP_H
|
||||
#define GUAC_RDP_DISP_H
|
||||
|
||||
#include "dvc.h"
|
||||
#include "rdp_settings.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
@ -102,7 +103,7 @@ void guac_rdp_disp_free(guac_rdp_disp* disp);
|
||||
*
|
||||
* @param context The rdpContext associated with the active RDP session.
|
||||
*/
|
||||
void guac_rdp_disp_load_plugin(rdpContext* context);
|
||||
void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list);
|
||||
|
||||
#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user