GUACAMOLE-249: Update RAIL (RemoteApp) support to FreeRDP 2.0.0 API.

This commit is contained in:
Michael Jumper 2019-10-14 11:12:53 -07:00
parent 07f6e6afc2
commit 6dc8b57ca4
5 changed files with 151 additions and 149 deletions

View File

@ -43,6 +43,7 @@ libguac_client_rdp_la_SOURCES = \
input.c \ input.c \
keyboard.c \ keyboard.c \
ptr_string.c \ ptr_string.c \
rail.c \
rdp.c \ rdp.c \
rdp_bitmap.c \ rdp_bitmap.c \
rdp_color.c \ rdp_color.c \
@ -52,7 +53,6 @@ libguac_client_rdp_la_SOURCES = \
rdp_keymap.c \ rdp_keymap.c \
rdp_print_job.c \ rdp_print_job.c \
rdp_pointer.c \ rdp_pointer.c \
rdp_rail.c \
rdp_settings.c \ rdp_settings.c \
rdp_stream.c \ rdp_stream.c \
resolution.c \ resolution.c \
@ -111,6 +111,7 @@ noinst_HEADERS = \
input.h \ input.h \
keyboard.h \ keyboard.h \
ptr_string.h \ ptr_string.h \
rail.h \
rdp.h \ rdp.h \
rdp_bitmap.h \ rdp_bitmap.h \
rdp_color.h \ rdp_color.h \
@ -120,7 +121,6 @@ noinst_HEADERS = \
rdp_keymap.h \ rdp_keymap.h \
rdp_pointer.h \ rdp_pointer.h \
rdp_print_job.h \ rdp_print_job.h \
rdp_rail.h \
rdp_settings.h \ rdp_settings.h \
rdp_status.h \ rdp_status.h \
rdp_stream.h \ rdp_stream.h \

136
src/protocols/rdp/rail.c Normal file
View File

@ -0,0 +1,136 @@
/*
* 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 "channels.h"
#include "client.h"
#include "rail.h"
#include "rdp.h"
#include "rdp_settings.h"
#include <freerdp/client/rail.h>
#include <freerdp/freerdp.h>
#include <guacamole/client.h>
#include <winpr/wtypes.h>
#include <stddef.h>
/**
* Callback which is invoked when a Server System Parameters Update PDU is
* received from the RDP server. The Server System Parameters Update PDU, also
* referred to as a "sysparam order", is used by the server to update system
* parameters for RemoteApp.
*
* @param rail
* The RailClientContext structure used by FreeRDP to handle the RAIL
* channel for the current RDP session.
*
* @param sysparam
* The RAIL_SYSPARAM_ORDER structure representing the Server System
* Parameters Update PDU that was received.
*
* @return
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
* (non-zero) otherwise.
*/
static UINT guac_rdp_rail_sysparam(RailClientContext* rail,
const RAIL_SYSPARAM_ORDER* sysparam) {
guac_client* client = (guac_client*) rail->custom;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
RAIL_SYSPARAM_ORDER response = {
.workArea = {
.left = 0,
.top = 0,
.right = rdp_client->settings->width,
.bottom = rdp_client->settings->height
},
.dragFullWindows = FALSE
};
return rail->ClientSystemParam(rail, &response);
}
/**
* Callback which associates handlers specific to Guacamole with the
* RailClientContext instance allocated by FreeRDP to deal with received
* RAIL (RemoteApp) messages.
*
* 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 RAIL channel. This specific callback is registered with the PubSub
* system of the relevant rdpContext when guac_rdp_rail_load_plugin() is
* called.
*
* @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_rail_channel_connected(rdpContext* context,
ChannelConnectedEventArgs* e) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
/* Ignore connection event if it's not for the RAIL channel */
if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) != 0)
return;
/* The structure pointed to by pInterface is guaranteed to be a
* RailClientContext if the channel is RAIL */
RailClientContext* rail = (RailClientContext*) e->pInterface;
/* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from
* within any RAIL-specific callbacks */
rail->custom = client;
rail->ServerSystemParam = guac_rdp_rail_sysparam;
guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel "
"connected.");
}
void guac_rdp_rail_load_plugin(rdpContext* context) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
/* Attempt to load FreeRDP support for the RAIL channel */
if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "rail", context->settings)) {
guac_client_log(client, GUAC_LOG_WARNING,
"Support for the RAIL channel (RemoteApp) could not be "
"loaded. This support normally takes the form of a plugin "
"which is built into FreeRDP. Lacking this support, "
"RemoteApp will not work.");
return;
}
/* Complete RDP side of initialization when channel is connected */
PubSub_SubscribeChannelConnected(context->pubSub,
(pChannelConnectedEventHandler) guac_rdp_rail_channel_connected);
guac_client_log(client, GUAC_LOG_DEBUG, "Support for RAIL (RemoteApp) "
"registered. Awaiting channel connection.");
}

View File

@ -17,37 +17,23 @@
* under the License. * under the License.
*/ */
#ifndef GUAC_RDP_RAIL_H
#ifndef __GUAC_RDP_RDP_RAIL_H #define GUAC_RDP_RAIL_H
#define __GUAC_RDP_RDP_RAIL_H
#include "config.h" #include "config.h"
#include <guacamole/client.h>
#include <winpr/stream.h>
/** /**
* Dispatches a given RAIL event to the appropriate handler. * Initializes RemoteApp support for RDP and handling of the RAIL channel. If
* failures occur, messages noting the specifics of those failures will be
* logged, and RemoteApp support will not be functional.
* *
* @param client * This MUST be called within the PreConnect callback of the freerdp instance
* The guac_client associated with the current RDP session. * for RAIL support to be loaded.
* *
* @param event * @param rdpContext
* The RAIL event to process. * The rdpContext associated with the FreeRDP side of the RDP connection.
*/ */
void guac_rdp_process_rail_event(guac_client* client, wMessage* event); void guac_rdp_rail_load_plugin(rdpContext* context);
/**
* Handles the event sent when updating system parameters. The event given
* MUST be a SYSPARAM event.
*
* @param client
* The guac_client associated with the current RDP session.
*
* @param event
* The system parameter event to process.
*/
void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event);
#endif #endif

View File

@ -29,6 +29,7 @@
#include "disp.h" #include "disp.h"
#include "error.h" #include "error.h"
#include "keyboard.h" #include "keyboard.h"
#include "rail.h"
#include "rdp.h" #include "rdp.h"
#include "rdp_bitmap.h" #include "rdp_bitmap.h"
#include "rdp_fs.h" #include "rdp_fs.h"
@ -36,7 +37,6 @@
#include "rdp_gdi.h" #include "rdp_gdi.h"
#include "rdp_glyph.h" #include "rdp_glyph.h"
#include "rdp_pointer.h" #include "rdp_pointer.h"
#include "rdp_rail.h"
#include "rdp_stream.h" #include "rdp_stream.h"
#if 0 #if 0
#include "rdp_svc.h" #include "rdp_svc.h"
@ -128,15 +128,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
} }
/* Load RAIL plugin if RemoteApp in use */ /* Load RAIL plugin if RemoteApp in use */
if (settings->remote_app != NULL) { if (settings->remote_app != NULL)
guac_rdp_rail_load_plugin(context);
/* Attempt to load rail */
if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"rail", instance->settings))
guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load rail plugin. RemoteApp will not work.");
}
#if 0 #if 0
/* Load SVC plugin instances for all static channels */ /* Load SVC plugin instances for all static channels */
@ -476,22 +469,6 @@ static int guac_rdp_handle_connection(guac_client* client) {
} }
/* Check for channel events */
#if 0
wMessage* event = freerdp_channels_pop_event(channels);
if (event) {
/* Handle channel events (clipboard and RAIL) */
if (GetMessageClass(event->id) == CliprdrChannel_Class)
guac_rdp_process_cliprdr_event(client, event);
else if (GetMessageClass(event->id) == RailChannel_Class)
guac_rdp_process_rail_event(client, event);
freerdp_event_free(event);
}
#endif
pthread_mutex_unlock(&(rdp_client->rdp_lock)); pthread_mutex_unlock(&(rdp_client->rdp_lock));
/* Calculate time remaining in frame */ /* Calculate time remaining in frame */

View File

@ -1,97 +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 "client.h"
#include "rdp.h"
#include "rdp_rail.h"
#include "rdp_settings.h"
#include <freerdp/channels/channels.h>
#include <freerdp/freerdp.h>
#include <freerdp/rail.h>
#include <guacamole/client.h>
#include <winpr/wtypes.h>
#include <stddef.h>
void guac_rdp_process_rail_event(guac_client* client, wMessage* event) {
switch (GetMessageType(event->id)) {
/* Get system parameters */
case RailChannel_GetSystemParam:
guac_rdp_process_rail_get_sysparam(client, event);
break;
/* Currently ignored events */
case RailChannel_ServerSystemParam:
case RailChannel_ServerExecuteResult:
case RailChannel_ServerMinMaxInfo:
case RailChannel_ServerLocalMoveSize:
case RailChannel_ServerGetAppIdResponse:
case RailChannel_ServerLanguageBarInfo:
break;
default:
guac_client_log(client, GUAC_LOG_INFO,
"Unknown rail event type: 0x%x",
GetMessageType(event->id));
}
}
void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event) {
#if 0
wMessage* response;
RAIL_SYSPARAM_ORDER* sysparam;
/* Get channels */
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
rdpChannels* channels = rdp_client->rdp_inst->context->channels;
/* Get sysparam structure */
sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam;
response = freerdp_event_new(RailChannel_Class,
RailChannel_ClientSystemParam,
NULL,
sysparam);
/* Work area */
sysparam->workArea.left = 0;
sysparam->workArea.top = 0;
sysparam->workArea.right = rdp_client->settings->width;
sysparam->workArea.bottom = rdp_client->settings->height;
/* Taskbar */
sysparam->taskbarPos.left = 0;
sysparam->taskbarPos.top = 0;
sysparam->taskbarPos.right = 0;
sysparam->taskbarPos.bottom = 0;
sysparam->dragFullWindows = FALSE;
/* Send response */
freerdp_channels_send_event(channels, response);
#endif
}