From 252771d9aae0833d0354e92ec112c962aa459a47 Mon Sep 17 00:00:00 2001 From: Hideyuki Nagase Date: Tue, 10 May 2022 12:28:58 -0500 Subject: [PATCH] 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 Co-authored-by: Brenton DeGeer Signed-off-by: Hideyuki Nagase Signed-off-by: Steve Pronovost Signed-off-by: Brenton DeGeer --- libweston/backend-rdp/meson.build | 6 ++++ libweston/backend-rdp/rdp.c | 47 +++++++++++++++++++++++++++---- libweston/backend-rdp/rdp.h | 5 +++- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/libweston/backend-rdp/meson.build b/libweston/backend-rdp/meson.build index ac19a4cd..7da92469 100644 --- a/libweston/backend-rdp/meson.build +++ b/libweston/backend-rdp/meson.build @@ -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 = [ diff --git a/libweston/backend-rdp/rdp.c b/libweston/backend-rdp/rdp.c index 6d2b63f3..3f104d25 100644 --- a/libweston/backend-rdp/rdp.c +++ b/libweston/backend-rdp/rdp.c @@ -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; diff --git a/libweston/backend-rdp/rdp.h b/libweston/backend-rdp/rdp.h index 1e4e51eb..ea28919f 100644 --- a/libweston/backend-rdp/rdp.h +++ b/libweston/backend-rdp/rdp.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -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;