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>
dev
Hideyuki Nagase 3 years ago committed by Derek Foreman
parent 3bdc29b934
commit 252771d9aa
  1. 6
      libweston/backend-rdp/meson.build
  2. 47
      libweston/backend-rdp/rdp.c
  3. 5
      libweston/backend-rdp/rdp.h

@ -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\'.') error('RDP-backend requires freerdp >= 2.2.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif 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) dep_wpr = dependency('winpr2', version: '>= 2.2.0', required: false)
if not dep_wpr.found() if not dep_wpr.found()
error('RDP-backend requires winpr >= 2.2.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.') 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 = [ deps_rdp = [
dep_libweston_private, dep_libweston_private,
dep_frdp, dep_frdp,
dep_frdp_server,
dep_wpr, dep_wpr,
] ]
srcs_rdp = [ srcs_rdp = [

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

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

Loading…
Cancel
Save