GUACAMOLE-249: Remove guac_rdp_dvc_list, relying instead on the DVC channel collection within rdpSettings.

This commit is contained in:
Michael Jumper 2019-10-13 15:30:02 -07:00
parent eab07b4a61
commit 07f6e6afc2
14 changed files with 166 additions and 411 deletions

View File

@ -38,7 +38,7 @@ libguac_client_rdp_la_SOURCES = \
client.c \ client.c \
clipboard.c \ clipboard.c \
decompose.c \ decompose.c \
dvc.c \ disp.c \
error.c \ error.c \
input.c \ input.c \
keyboard.c \ keyboard.c \
@ -46,7 +46,6 @@ libguac_client_rdp_la_SOURCES = \
rdp.c \ rdp.c \
rdp_bitmap.c \ rdp_bitmap.c \
rdp_color.c \ rdp_color.c \
rdp_disp.c \
rdp_fs.c \ rdp_fs.c \
rdp_gdi.c \ rdp_gdi.c \
rdp_glyph.c \ rdp_glyph.c \
@ -107,7 +106,7 @@ noinst_HEADERS = \
clipboard.h \ clipboard.h \
channels.h \ channels.h \
decompose.h \ decompose.h \
dvc.h \ disp.h \
error.h \ error.h \
input.h \ input.h \
keyboard.h \ keyboard.h \
@ -115,7 +114,6 @@ noinst_HEADERS = \
rdp.h \ rdp.h \
rdp_bitmap.h \ rdp_bitmap.h \
rdp_color.h \ rdp_color.h \
rdp_disp.h \
rdp_fs.h \ rdp_fs.h \
rdp_gdi.h \ rdp_gdi.h \
rdp_glyph.h \ rdp_glyph.h \

View File

@ -19,7 +19,7 @@
#include "config.h" #include "config.h"
#include "audio_input.h" #include "audio_input.h"
#include "dvc.h" #include "channels.h"
#include "ptr_string.h" #include "ptr_string.h"
#include "rdp.h" #include "rdp.h"
@ -182,14 +182,14 @@ int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) {
} }
void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { void guac_rdp_audio_load_plugin(rdpContext* context) {
guac_client* client = ((rdp_freerdp_context*) context)->client; guac_client* client = ((rdp_freerdp_context*) context)->client;
char client_ref[GUAC_RDP_PTR_STRING_LENGTH]; char client_ref[GUAC_RDP_PTR_STRING_LENGTH];
/* Add "AUDIO_INPUT" channel */ /* Add "AUDIO_INPUT" channel */
guac_rdp_ptr_to_string(client, client_ref); guac_rdp_ptr_to_string(client, client_ref);
guac_rdp_dvc_list_add(list, "guacai", client_ref, NULL); guac_freerdp_dynamic_channel_collection_add(context->settings, "guacai", client_ref, NULL);
} }

View File

@ -21,7 +21,6 @@
#define GUAC_RDP_AUDIO_INPUT_H #define GUAC_RDP_AUDIO_INPUT_H
#include "config.h" #include "config.h"
#include "dvc.h"
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <guacamole/stream.h> #include <guacamole/stream.h>
@ -296,18 +295,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
/** /**
* Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
* plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
* be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
* passed to this function. The "guacai" plugin ultimately adds support for the * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel.
* "AUDIO_INPUT" dynamic virtual channel.
* *
* @param context * @param context
* The rdpContext associated with the active RDP session. * The rdpContext associated with the active RDP session.
*
* @param list
* The guac_rdp_dvc_list to which the "guacai" plugin should be added, such
* that it may later be loaded by guac_rdp_load_drdynvc().
*/ */
void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); void guac_rdp_audio_load_plugin(rdpContext* context);
#endif #endif

View File

@ -24,22 +24,6 @@
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <guacamole/client.h> #include <guacamole/client.h>
void guac_rdp_channel_connected(rdpContext* context,
ChannelConnectedEventArgs* e) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_client_log(client, GUAC_LOG_DEBUG, "Channel \"%s\" connected.", e->name);
/* Display update channel */
if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) {
DispClientContext* disp = (DispClientContext*) e->pInterface;
guac_rdp_disp_connect(rdp_client->disp, context, disp);
}
}
int guac_freerdp_channels_load_plugin(rdpChannels* channels, int guac_freerdp_channels_load_plugin(rdpChannels* channels,
rdpSettings* settings, const char* name, void* data) { rdpSettings* settings, const char* name, void* data) {
@ -62,3 +46,36 @@ int guac_freerdp_channels_load_plugin(rdpChannels* channels,
} }
void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings,
const char* name, ...) {
va_list args;
ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV));
va_start(args, name);
/* Count number of arguments (excluding terminating NULL) */
freerdp_args->argc = 1;
while (va_arg(args, char*) != NULL)
freerdp_args->argc++;
/* Reset va_list */
va_end(args);
va_start(args, name);
/* Copy argument values into DVC entry */
freerdp_args->argv = malloc(sizeof(char*) * freerdp_args->argc);
freerdp_args->argv[0] = strdup(name);
int i;
for (i = 1; i < freerdp_args->argc; i++)
freerdp_args->argv[i] = strdup(va_arg(args, char*));
va_end(args);
/* Register plugin with FreeRDP */
settings->SupportDynamicChannels = TRUE;
freerdp_dynamic_channel_collection_add(settings, freerdp_args);
}

View File

@ -25,20 +25,6 @@
#include <freerdp/channels/channels.h> #include <freerdp/channels/channels.h>
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
/**
* Called whenever a channel connects via the PubSub event system within
* FreeRDP.
*
* @param context
* The rdpContext associated with the active RDP session.
*
* @param e
* Event-specific arguments, mainly the name of the channel, and a
* reference to the associated plugin loaded for that channel by FreeRDP.
*/
void guac_rdp_channel_connected(rdpContext* context,
ChannelConnectedEventArgs* e);
/** /**
* Loads the FreeRDP plugin having the given name. This function is a drop-in * Loads the FreeRDP plugin having the given name. This function is a drop-in
* replacement for freerdp_channels_load_plugin() which additionally loads * replacement for freerdp_channels_load_plugin() which additionally loads
@ -47,6 +33,9 @@ void guac_rdp_channel_connected(rdpContext* context,
* part of FreeRDP can load only plugins which implement the * part of FreeRDP can load only plugins which implement the
* PVIRTUALCHANNELENTRY version of the entry point. * PVIRTUALCHANNELENTRY version of the entry point.
* *
* This MUST be called within the PreConnect callback of the freerdp instance
* for the referenced plugin to be loaded correctly.
*
* @param channels * @param channels
* The rdpChannels structure with which the plugin should be registered * The rdpChannels structure with which the plugin should be registered
* once loaded. This structure should be retrieved directly from the * once loaded. This structure should be retrieved directly from the
@ -76,5 +65,45 @@ void guac_rdp_channel_connected(rdpContext* context,
int guac_freerdp_channels_load_plugin(rdpChannels* channels, int guac_freerdp_channels_load_plugin(rdpChannels* channels,
rdpSettings* settings, const char* name, void* data); rdpSettings* settings, const char* name, void* data);
/**
* Schedules loading of the FreeRDP dynamic virtual channel plugin having the
* given name. This function is essentially a wrapper for
* freerdp_dynamic_channel_collection_add() which additionally takes care of
* housekeeping tasks which would otherwise need to be performed manually:
*
* - The ADDIN_ARGV structure used to pass arguments to dynamic virtual
* channel plugins is automatically allocated and populated with any given
* arguments.
* - The SupportDynamicChannels member of the rdpSettings structure is
* automatically set to TRUE.
*
* The "drdynvc" plugin must still eventually be loaded for this function to
* have any effect, as it is the "drdynvc" plugin which processes the
* collection this function manipulates.
*
* This MUST be called within the PreConnect callback of the freerdp instance
* and the "drdynvc" plugin MUST be loaded at some point after this function is
* called for the referenced dynamic channel plugin to be loaded correctly.
*
* @param settings
* The rdpSettings structure associated with the FreeRDP instance, already
* populated with any settings applicable to the plugin being loaded.
*
* @param name
* The name of the plugin to load. If the plugin is not statically built
* into FreeRDP, this name will determine the filename of the library to be
* loaded dynamically. For a plugin named "NAME", the library called
* "libNAME-client" will be loaded from the "freerdp2" subdirectory of the
* main directory containing the FreeRDP libraries.
*
* @param ...
* Arbitrary arguments to be passed to the plugin entry point. For most
* plugins which are built into FreeRDP, this will be another reference to
* the rdpSettings struct or NULL. The source of the relevant plugin must
* be consulted to determine the proper value(s) to pass here.
*/
void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings,
const char* name, ...);
#endif #endif

View File

@ -22,8 +22,8 @@
#include "audio_input.h" #include "audio_input.h"
#include "common/recording.h" #include "common/recording.h"
#include "client.h" #include "client.h"
#include "disp.h"
#include "rdp.h" #include "rdp.h"
#include "rdp_disp.h"
#include "rdp_fs.h" #include "rdp_fs.h"
#include "user.h" #include "user.h"

View File

@ -18,16 +18,17 @@
*/ */
#include "config.h" #include "config.h"
#include "channels.h"
#include "client.h" #include "client.h"
#include "dvc.h" #include "disp.h"
#include "rdp.h" #include "rdp.h"
#include "rdp_disp.h"
#include "rdp_settings.h" #include "rdp_settings.h"
#include <freerdp/client/disp.h> #include <freerdp/client/disp.h>
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/timestamp.h> #include <guacamole/timestamp.h>
#include <winpr/wtypes.h>
guac_rdp_disp* guac_rdp_disp_alloc() { guac_rdp_disp* guac_rdp_disp_alloc() {
@ -50,33 +51,42 @@ void guac_rdp_disp_free(guac_rdp_disp* disp) {
free(disp); free(disp);
} }
void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { /**
* Callback which associates handlers specific to Guacamole with the
context->settings->SupportDisplayControl = TRUE; * DispClientContext instance allocated by FreeRDP to deal with received
* Display Update (client-initiated dynamic display resizing) messages.
/* Add "disp" channel */ *
guac_rdp_dvc_list_add(list, "disp", NULL); * This function is called whenever a channel connects via the PubSub event
* system within FreeRDP, but only has any effect if the connected channel is
} * the Display Update channel. This specific callback is registered with the
* PubSub system of the relevant rdpContext when guac_rdp_disp_load_plugin() is
void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, * called.
DispClientContext* disp) { *
* @param context
* The rdpContext associated with the active RDP session.
*
* @param e
* Event-specific arguments, mainly the name of the channel, and a
* reference to the associated plugin loaded for that channel by FreeRDP.
*/
static void guac_rdp_disp_channel_connected(rdpContext* context,
ChannelConnectedEventArgs* e) {
guac_client* client = ((rdp_freerdp_context*) context)->client; guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings; guac_rdp_disp* guac_disp = rdp_client->disp;
/* Ignore connected channel if not configured to use the display update /* Ignore connection event if it's not for the Display Update channel */
* channel for resize */ if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) != 0)
if (settings->resize_method != GUAC_RESIZE_DISPLAY_UPDATE)
return; return;
/* Init module with current display size */ /* Init module with current display size */
guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, guac_rdp_disp_set_size(guac_disp, rdp_client->settings,
context->instance, guac_rdp_get_width(context->instance), context->instance, guac_rdp_get_width(context->instance),
guac_rdp_get_height(context->instance)); guac_rdp_get_height(context->instance));
/* Store reference to the display update plugin once it's connected */ /* Store reference to the display update plugin once it's connected */
DispClientContext* disp = (DispClientContext*) e->pInterface;
guac_disp->disp = disp; guac_disp->disp = disp;
guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel " guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel "
@ -84,6 +94,17 @@ void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context,
} }
void guac_rdp_disp_load_plugin(rdpContext* context) {
/* Subscribe to and handle channel connected events */
PubSub_SubscribeChannelConnected(context->pubSub,
(pChannelConnectedEventHandler) guac_rdp_disp_channel_connected);
/* Add "disp" channel */
guac_freerdp_dynamic_channel_collection_add(context->settings, "disp", NULL);
}
/** /**
* Fits a given dimension within the allowed bounds for Display Update * Fits a given dimension within the allowed bounds for Display Update
* messages, adjusting the other dimension such that aspect ratio is * messages, adjusting the other dimension such that aspect ratio is

View File

@ -20,11 +20,12 @@
#ifndef GUAC_RDP_DISP_H #ifndef GUAC_RDP_DISP_H
#define GUAC_RDP_DISP_H #define GUAC_RDP_DISP_H
#include "dvc.h"
#include "rdp_settings.h" #include "rdp_settings.h"
#include <freerdp/client/disp.h> #include <freerdp/client/disp.h>
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <guacamole/client.h>
#include <guacamole/timestamp.h>
/** /**
* The minimum value for width or height, in pixels. * The minimum value for width or height, in pixels.
@ -78,55 +79,43 @@ typedef struct guac_rdp_disp {
/** /**
* Allocates a new display update module, which will ultimately control the * Allocates a new display update module, which will ultimately control the
* display update channel once conected. * display update channel once connected.
* *
* @return A new display update module. * @return
* A newly-allocated display update module.
*/ */
guac_rdp_disp* guac_rdp_disp_alloc(); guac_rdp_disp* guac_rdp_disp_alloc();
/** /**
* Frees the given display update module. * Frees the resources associated with support for the RDP Display Update
* channel. Only resources specific to Guacamole are freed. Resources specific
* to FreeRDP's handling of the Display Update channel will be freed by
* FreeRDP. If no resources are currently allocated for Display Update support,
* this function has no effect.
* *
* @param disp The display update module to free. * @param disp
* The display update module to free.
*/ */
void guac_rdp_disp_free(guac_rdp_disp* disp); void guac_rdp_disp_free(guac_rdp_disp* disp);
/** /**
* Adds FreeRDP's "disp" plugin to the list of dynamic virtual channel plugins * Adds FreeRDP's "disp" plugin to the list of dynamic virtual channel plugins
* to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only be loaded * to be loaded by FreeRDP's "drdynvc" plugin. The context of the plugin will
* once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list passed to * automatically be assicated with the guac_rdp_disp instance pointed to by the
* this function. The "disp" plugin ultimately adds support for the Display * current guac_rdp_client. The plugin will only be loaded once the "drdynvc"
* Update channel. NOTE: It is still up to external code to detect when the * plugin is loaded. The "disp" plugin ultimately adds support for the Display
* "disp" channel is connected, and update the guac_rdp_disp with a call to * Update channel.
* guac_rdp_disp_connect(). *
* If failures occur, messages noting the specifics of those failures will be
* logged, and the RDP side of Display Update support will not be functional.
*
* This MUST be called within the PreConnect callback of the freerdp instance
* for Display Update support to be loaded.
* *
* @param context * @param context
* The rdpContext associated with the active RDP session. * The rdpContext associated with the active RDP session.
*
* @param list
* The guac_rdp_dvc_list to which the "disp" plugin should be added, such
* that it may later be loaded by guac_rdp_load_drdynvc().
*/ */
void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); void guac_rdp_disp_load_plugin(rdpContext* context);
/**
* Stores the given DispClientContext within the given guac_rdp_disp, such that
* display updates can be properly sent. Until this is called, changes to the
* display size will be deferred.
*
* @param guac_disp
* The display update module to associate with the connected display update
* channel.
*
* @param context
* The rdpContext associated with the active RDP session.
*
* @param disp
* The DispClientContext associated by FreeRDP with the connected display
* update channel.
*/
void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context,
DispClientContext* disp);
/** /**
* Requests a display size update, which may then be sent immediately to the * Requests a display size update, which may then be sent immediately to the
@ -197,6 +186,10 @@ void guac_rdp_disp_reconnect_complete(guac_rdp_disp* disp);
* Returns whether a full RDP reconnect is required for display update changes * Returns whether a full RDP reconnect is required for display update changes
* to take effect. * to take effect.
* *
* @param client
* The guac_client associated with the Guacamole side of the RDP
* connection.
*
* @return * @return
* Non-zero if a reconnect is needed, zero otherwise. * Non-zero if a reconnect is needed, zero otherwise.
*/ */

View File

@ -1,156 +0,0 @@
/*
* 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 "common/list.h"
#include "channels.h"
#include "dvc.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 guac_freerdp_channels_load_plugin(channels,
context->instance->settings, "drdynvc",
context->instance->settings);
}

View File

@ -1,138 +0,0 @@
/*
* 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 "common/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

View File

@ -21,10 +21,10 @@
#include "client.h" #include "client.h"
#include "common/recording.h" #include "common/recording.h"
#include "disp.h"
#include "input.h" #include "input.h"
#include "keyboard.h" #include "keyboard.h"
#include "rdp.h" #include "rdp.h"
#include "rdp_disp.h"
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <freerdp/input.h> #include <freerdp/input.h>

View File

@ -26,12 +26,11 @@
#include "common/cursor.h" #include "common/cursor.h"
#include "common/display.h" #include "common/display.h"
#include "common/recording.h" #include "common/recording.h"
#include "dvc.h" #include "disp.h"
#include "error.h" #include "error.h"
#include "keyboard.h" #include "keyboard.h"
#include "rdp.h" #include "rdp.h"
#include "rdp_bitmap.h" #include "rdp_bitmap.h"
#include "rdp_disp.h"
#include "rdp_fs.h" #include "rdp_fs.h"
#include "rdp_print_job.h" #include "rdp_print_job.h"
#include "rdp_gdi.h" #include "rdp_gdi.h"
@ -90,23 +89,17 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings; guac_rdp_settings* settings = rdp_client->settings;
guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc();
/* Init FreeRDP add-in provider */ /* Init FreeRDP add-in provider */
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
/* Subscribe to and handle channel connected events */
PubSub_SubscribeChannelConnected(context->pubSub,
(pChannelConnectedEventHandler) guac_rdp_channel_connected);
/* Load "disp" plugin for display update */ /* Load "disp" plugin for display update */
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE)
guac_rdp_disp_load_plugin(instance->context, dvc_list); guac_rdp_disp_load_plugin(context);
/* Load "AUDIO_INPUT" plugin for audio input*/ /* Load "AUDIO_INPUT" plugin for audio input*/
if (settings->enable_audio_input) { if (settings->enable_audio_input) {
rdp_client->audio_input = guac_rdp_audio_buffer_alloc(); rdp_client->audio_input = guac_rdp_audio_buffer_alloc();
guac_rdp_audio_load_plugin(instance->context, dvc_list); guac_rdp_audio_load_plugin(instance->context);
} }
/* Load "cliprdr" plugin for clipboard support */ /* Load "cliprdr" plugin for clipboard support */
@ -175,14 +168,14 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
} }
#endif #endif
/* Load DRDYNVC plugin if required */ /* Load plugin providing Dynamic Virtual Channel support, if required */
if (guac_rdp_load_drdynvc(instance->context, dvc_list)) if (instance->settings->SupportDynamicChannels &&
guac_freerdp_channels_load_plugin(channels, instance->settings,
"drdynvc", instance->settings)) {
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load drdynvc plugin. Display update and audio " "Failed to load drdynvc plugin. Display update and audio "
"input support will be disabled."); "input support will be disabled.");
}
/* Dynamic virtual channel list is no longer needed */
guac_rdp_dvc_list_free(dvc_list);
/* Init FreeRDP internal GDI implementation */ /* Init FreeRDP internal GDI implementation */
if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) if (!gdi_init(instance, PIXEL_FORMAT_BGRX32))

View File

@ -29,8 +29,8 @@
#include "common/list.h" #include "common/list.h"
#include "common/recording.h" #include "common/recording.h"
#include "common/surface.h" #include "common/surface.h"
#include "disp.h"
#include "keyboard.h" #include "keyboard.h"
#include "rdp_disp.h"
#include "rdp_fs.h" #include "rdp_fs.h"
#include "rdp_print_job.h" #include "rdp_print_job.h"
#include "rdp_settings.h" #include "rdp_settings.h"

View File

@ -1192,6 +1192,10 @@ void guac_rdp_push_settings(guac_client* client,
/* Audio capture */ /* Audio capture */
rdp_settings->AudioCapture = guac_settings->enable_audio_input; rdp_settings->AudioCapture = guac_settings->enable_audio_input;
/* Display Update channel */
rdp_settings->SupportDisplayControl =
(guac_settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE);
/* Timezone redirection */ /* Timezone redirection */
if (guac_settings->timezone) { if (guac_settings->timezone) {
if (setenv("TZ", guac_settings->timezone, 1)) { if (setenv("TZ", guac_settings->timezone, 1)) {