rdp: add virtual channel support

RDP exposes certain features (audio, clipboard, RAIL) through a facility
called "virtual channels". Set up the communications framework for using
these.

Co-authored-by: Steve Pronovost <spronovo@microsoft.com>
Co-authored-by: Brenton DeGeer <brdegeer@microsoft.com>
Signed-off-by: Hideyuki Nagase <hideyukn@microsoft.com>
Signed-off-by: Steve Pronovost <spronovo@microsoft.com>
Signed-off-by: Brenton DeGeer <brdegeer@microsoft.com>
This commit is contained in:
Hideyuki Nagase 2022-05-10 12:28:58 -05:00 committed by Derek Foreman
parent 3bdc29b934
commit 252771d9aa
3 changed files with 52 additions and 6 deletions

View File

@ -13,6 +13,11 @@ if not dep_frdp.found()
error('RDP-backend requires freerdp >= 2.2.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
dep_frdp_server = dependency('freerdp-server2', version: '>= 2.2.0', required: false)
if not dep_frdp_server.found()
error('RDP-backend requires freerdp-server2 >= 2.2.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
dep_wpr = dependency('winpr2', version: '>= 2.2.0', required: false)
if not dep_wpr.found()
error('RDP-backend requires winpr >= 2.2.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
@ -21,6 +26,7 @@ endif
deps_rdp = [
dep_libweston_private,
dep_frdp,
dep_frdp_server,
dep_wpr,
]
srcs_rdp = [

View File

@ -51,6 +51,8 @@
#define KBD_HEBREW_STANDARD 0x2040D
#endif
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
static void
rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
{
@ -656,16 +658,20 @@ out_error_stream:
static void
rdp_peer_context_free(freerdp_peer* client, RdpPeerContext* context)
{
int i;
unsigned i;
if (!context)
return;
wl_list_remove(&context->item.link);
for (i = 0; i < MAX_FREERDP_FDS; i++) {
for (i = 0; i < ARRAY_LENGTH(context->events); i++) {
if (context->events[i])
wl_event_source_remove(context->events[i]);
}
if (context->vcm)
WTSCloseServer(context->vcm);
rdp_destroy_dispatch_task_event_source(context);
if (context->item.flags & RDP_PEER_ACTIVATED) {
@ -686,11 +692,21 @@ static int
rdp_client_activity(int fd, uint32_t mask, void *data)
{
freerdp_peer* client = (freerdp_peer *)data;
RdpPeerContext *peerCtx = (RdpPeerContext *)client->context;
if (!client->CheckFileDescriptor(client)) {
weston_log("unable to checkDescriptor for %p\n", client);
goto out_clean;
}
if (peerCtx && peerCtx->vcm)
{
if (!WTSVirtualChannelManagerCheckFileDescriptor(peerCtx->vcm)) {
weston_log("failed to check FreeRDP WTS VC file descriptor for %p\n", client);
goto out_clean;
}
}
return 0;
out_clean:
@ -1394,7 +1410,7 @@ static int
rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
{
int rcount = 0;
void *rfds[MAX_FREERDP_FDS];
void *rfds[MAX_FREERDP_FDS + 1]; /* +1 for WTSVirtualChannelManagerGetFileDescriptor. */
int i, fd;
struct wl_event_loop *loop;
rdpSettings *settings;
@ -1455,6 +1471,15 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
goto error_initialize;
}
PWtsApiFunctionTable fn = FreeRDP_InitWtsApi();
WTSRegisterWtsApiFunctionTable(fn);
peerCtx->vcm = WTSOpenServerA((LPSTR)peerCtx);
if (peerCtx->vcm) {
WTSVirtualChannelManagerGetFileDescriptor(peerCtx->vcm, rfds, &rcount);
} else {
weston_log("WTSOpenServer is failed! continue without virtual channel.\n");
}
loop = wl_display_get_event_loop(b->compositor->wl_display);
for (i = 0; i < rcount; i++) {
fd = (int)(long)(rfds[i]);
@ -1462,16 +1487,28 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
peerCtx->events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
rdp_client_activity, client);
}
for ( ; i < MAX_FREERDP_FDS; i++)
for ( ; i < (int)ARRAY_LENGTH(peerCtx->events); i++)
peerCtx->events[i] = 0;
wl_list_insert(&b->output->peers, &peerCtx->item.link);
if (!rdp_initialize_dispatch_task_event_source(peerCtx))
goto error_initialize;
goto error_dispatch_initialize;
return 0;
error_dispatch_initialize:
for (i = 0; i < (int)ARRAY_LENGTH(peerCtx->events); i++) {
if (peerCtx->events[i]) {
wl_event_source_remove(peerCtx->events[i]);
peerCtx->events[i] = NULL;
}
}
if (peerCtx->vcm) {
WTSCloseServer(peerCtx->vcm);
peerCtx->vcm = NULL;
}
error_initialize:
client->Close(client);
return -1;

View File

@ -37,6 +37,7 @@
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/locale/keyboard.h>
#include <freerdp/channels/wtsvc.h>
#include <libweston/libweston.h>
#include <libweston/backend-rdp.h>
@ -118,7 +119,7 @@ struct rdp_peer_context {
rdpContext _p;
struct rdp_backend *rdpBackend;
struct wl_event_source *events[MAX_FREERDP_FDS];
struct wl_event_source *events[MAX_FREERDP_FDS + 1]; /* +1 for WTSVirtualChannelManagerGetFileDescriptor */
RFX_CONTEXT *rfx_context;
wStream *encode_stream;
RFX_RECT *rfx_rects;
@ -133,6 +134,8 @@ struct rdp_peer_context {
int horizontalAccumWheelRotationPrecise;
int horizontalAccumWheelRotationDiscrete;
HANDLE vcm;
/* list of outstanding event_source sent from FreeRDP thread to display loop.*/
int loop_task_event_source_fd;
struct wl_event_source *loop_task_event_source;