Skip to content

Commit

Permalink
Merge patch branch changes to main.
Browse files Browse the repository at this point in the history
  • Loading branch information
necouchman committed Sep 10, 2024
2 parents 98f3c8b + 9c841a6 commit 09c2d4e
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 30 deletions.
24 changes: 24 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,30 @@ then
[AC_MSG_RESULT([no])])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_MSG_CHECKING([whether freerdp instance supports LoadChannels])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/freerdp.h>
/* Mock LoadChannels function with the expected signature */
BOOL load_channels(freerdp* instance) {
return TRUE;
}
int main() {
freerdp* instance = freerdp_new();
instance->LoadChannels = load_channels;
freerdp_free(instance);
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([RDP_INST_HAS_LOAD_CHANNELS],,
[Defined if freerdp instance supports LoadChannels])],
[AC_MSG_RESULT([no])])
fi

# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing
CPPFLAGS="$OLDCPPFLAGS"

Expand Down
103 changes: 80 additions & 23 deletions src/protocols/rdp/rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,29 @@
#include <stdlib.h>
#include <time.h>

BOOL rdp_freerdp_pre_connect(freerdp* instance) {

/**
* Initializes and loads the necessary FreeRDP plugins based on the current
* RDP session settings. This function is designed to work in environments
* where the FreeRDP instance expects a LoadChannels callback to be set
* otherwise it can becalled directly from our pre_connect callback. It
* configures various features such as display resizing, multi-touch support,
* audio input, clipboard synchronization, device redirection, and graphics
* pipeline, by loading their corresponding plugins if they are enabled in the
* session settings.
*
* @param instance
* The FreeRDP instance to be prepared, containing all context and
* settings for the session.
*
* @return
* Always TRUE.
*/
static BOOL rdp_freerdp_load_channels(freerdp* instance) {
rdpContext* context = GUAC_RDP_CONTEXT(instance);
rdpGraphics* graphics = context->graphics;

guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings;

/* Push desired settings to FreeRDP */
guac_rdp_push_settings(client, settings, instance);

/* Init FreeRDP add-in provider */
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);

/* Load "disp" plugin for display update */
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE)
guac_rdp_disp_load_plugin(context);
Expand Down Expand Up @@ -125,6 +133,53 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
guac_rdpsnd_load_plugin(context);
}

/* Load "rdpgfx" plugin for Graphics Pipeline Extension */
if (settings->enable_gfx)
guac_rdp_rdpgfx_load_plugin(context);

/* Load plugin providing Dynamic Virtual Channel support, if required */
if (freerdp_settings_get_bool(GUAC_RDP_CONTEXT(instance)->settings, FreeRDP_SupportDynamicChannels) &&
guac_freerdp_channels_load_plugin(context, "drdynvc",
GUAC_RDP_CONTEXT(instance)->settings)) {
guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load drdynvc plugin. Display update and audio "
"input support will be disabled.");
}

return TRUE;
}

/**
* Prepares the FreeRDP instance for connection by setting up session-specific
* configurations like graphics, plugins, and RDP settings. This involves
* integrating Guacamole's custom rendering handlers (for bitmaps, glyphs,
* and pointers). If using a freerdp instance that does not expect a
* LoadChannels callback then this function manually loads RDP channels.
*
* @param instance
* The FreeRDP instance to be prepared, containing all context and
* settings for the session.
*
* @return
* Returns TRUE if the pre-connection process completes successfully.
* Returns FALSE if an error occurs during the initialization of the
* FreeRDP GDI system.
*/
static BOOL rdp_freerdp_pre_connect(freerdp* instance) {

rdpContext* context = GUAC_RDP_CONTEXT(instance);
rdpGraphics* graphics = context->graphics;

guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings;

/* Push desired settings to FreeRDP */
guac_rdp_push_settings(client, settings, instance);

/* Init FreeRDP add-in provider */
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);

/* Load RAIL plugin if RemoteApp in use */
if (settings->remote_app != NULL)
guac_rdp_rail_load_plugin(context);
Expand Down Expand Up @@ -194,21 +249,15 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
primary->MemBlt = guac_rdp_gdi_memblt;
primary->OpaqueRect = guac_rdp_gdi_opaquerect;

/* Load "rdpgfx" plugin for Graphics Pipeline Extension */
if (settings->enable_gfx)
guac_rdp_rdpgfx_load_plugin(context);

/* Load plugin providing Dynamic Virtual Channel support, if required */
if (freerdp_settings_get_bool(GUAC_RDP_CONTEXT(instance)->settings, FreeRDP_SupportDynamicChannels) &&
guac_freerdp_channels_load_plugin(context, "drdynvc",
GUAC_RDP_CONTEXT(instance)->settings)) {
guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load drdynvc plugin. Display update and audio "
"input support will be disabled.");
}
/*
* If the freerdp instance does not have a LoadChannels callback for
* loading plugins we use the PreConnect callback to load plugins instead.
*/
#ifndef RDP_INST_HAS_LOAD_CHANNELS
rdp_freerdp_load_channels(instance);
#endif

return TRUE;

}

/**
Expand Down Expand Up @@ -489,6 +538,14 @@ static int guac_rdp_handle_connection(guac_client* client) {

/* Init client */
freerdp* rdp_inst = freerdp_new();

/*
* If the freerdp instance has a LoadChannels callback for loading plugins
* we use that instead of the PreConnect callback to load plugins.
*/
#ifdef RDP_INST_HAS_LOAD_CHANNELS
rdp_inst->LoadChannels = rdp_freerdp_load_channels;
#endif
rdp_inst->PreConnect = rdp_freerdp_pre_connect;
rdp_inst->Authenticate = rdp_freerdp_authenticate;

Expand Down
27 changes: 20 additions & 7 deletions src/protocols/vnc/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) {
guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;

#ifdef LIBVNC_CLIENT_HAS_SCREEN
int new_height = rfbClientSwap16IfLE(client->screen.height);
int new_width = rfbClientSwap16IfLE(client->screen.width);
#else
int new_height = rfbClientSwap16IfLE(client->height);
int new_width = rfbClientSwap16IfLE(client->width);
#endif

/* Resize the surface if VNC screen size has changed */
int old_height = vnc_client->display->default_surface->height;
int old_width = vnc_client->display->default_surface->width;
if (
new_height > 0 && new_width > 0
&& (new_height != old_height || new_width != old_width)
) {
guac_common_surface_resize(vnc_client->display->default_surface,
new_width, new_height);
}

int dx, dy;

/* Cairo image buffer */
Expand Down Expand Up @@ -309,15 +328,9 @@ void guac_vnc_display_set_size(rfbClient* client, int width, int height) {

/* Send the display size update. */
guac_client_log(gc, GUAC_LOG_TRACE, "Setting VNC display size.");
if (guac_vnc_send_desktop_size(client, width, height)) {
if (guac_vnc_send_desktop_size(client, width, height))
guac_client_log(gc, GUAC_LOG_TRACE, "Successfully sent desktop size message.");

/* Resize the surface now that the VNC size update has completed */
if (vnc_client->display != NULL)
guac_common_surface_resize(vnc_client->display->default_surface,
width, height);
}

else
guac_client_log(gc, GUAC_LOG_TRACE, "Failed to send desktop size message.");

Expand Down

0 comments on commit 09c2d4e

Please sign in to comment.