rdp: Allow specifying a listener fd on the command line

We already have a way for a single RDP client connection to be
passed from a parent process to a child using a combination
of environment variable (RDP_FD) and env var (--env-socket)

This patch allows a bound socket fd (as opposed to a client
connection) to be established in a parent process and provided
to the rdp backend. WSLg uses this to set up an AF_VSOCK
socket for communication between a Windows RDP client and a
weston compositor running under a hypervisor.

Co-authored-by: Hideyuki Nagase <hideyukn@microsoft.com>
Co-authored-by: Steve Pronovost <spronovo@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
Brenton DeGeer 3 years ago committed by Derek Foreman
parent 13e62c9d18
commit 2f9319cef6
  1. 3
      compositor/main.c
  2. 1
      include/libweston/backend-rdp.h
  3. 35
      libweston/backend-rdp/rdp.c
  4. 1
      libweston/backend-rdp/rdp.h
  5. 6
      man/weston-rdp.man

@ -688,6 +688,7 @@ usage(int error_code)
" --width=WIDTH\t\tWidth of desktop\n" " --width=WIDTH\t\tWidth of desktop\n"
" --height=HEIGHT\tHeight of desktop\n" " --height=HEIGHT\tHeight of desktop\n"
" --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n" " --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
" --external-listener-fd=FD\tUse socket as listener connection\n"
" --address=ADDR\tThe address to bind\n" " --address=ADDR\tThe address to bind\n"
" --port=PORT\t\tThe port to listen on\n" " --port=PORT\t\tThe port to listen on\n"
" --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n" " --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
@ -2772,6 +2773,7 @@ weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
config->server_cert = NULL; config->server_cert = NULL;
config->server_key = NULL; config->server_key = NULL;
config->env_socket = 0; config->env_socket = 0;
config->external_listener_fd = -1;
config->no_clients_resize = 0; config->no_clients_resize = 0;
config->force_no_compression = 0; config->force_no_compression = 0;
config->remotefx_codec = true; config->remotefx_codec = true;
@ -2793,6 +2795,7 @@ load_rdp_backend(struct weston_compositor *c,
const struct weston_option rdp_options[] = { const struct weston_option rdp_options[] = {
{ WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket }, { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
{ WESTON_OPTION_INTEGER, "external-listener-fd", 0, &config.external_listener_fd },
{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width }, { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height }, { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
{ WESTON_OPTION_STRING, "address", 0, &config.bind_address }, { WESTON_OPTION_STRING, "address", 0, &config.bind_address },

@ -67,6 +67,7 @@ struct weston_rdp_backend_config {
int no_clients_resize; int no_clients_resize;
int force_no_compression; int force_no_compression;
bool remotefx_codec; bool remotefx_codec;
int external_listener_fd;
}; };
#ifdef __cplusplus #ifdef __cplusplus

@ -1354,14 +1354,27 @@ rdp_backend_create(struct weston_compositor *compositor,
compositor->backend = &b->base; compositor->backend = &b->base;
/* activate TLS only if certificate/key are available */
if (config->server_cert && config->server_key) { if (config->server_cert && config->server_key) {
weston_log("TLS support activated\n");
b->server_cert = strdup(config->server_cert); b->server_cert = strdup(config->server_cert);
b->server_key = strdup(config->server_key); b->server_key = strdup(config->server_key);
if (!b->server_cert || !b->server_key) if (!b->server_cert || !b->server_key)
goto err_free_strings; goto err_free_strings;
}
/* if we are listening for client connections on an external listener
* fd, we don't need to enforce TLS or RDP security, since FreeRDP
* will consider it to be a local connection */
fd = config->external_listener_fd;
if (fd < 0) {
if (!b->rdp_key && (!b->server_cert || !b->server_key)) {
weston_log("the RDP compositor requires keys and an optional certificate for RDP or TLS security ("
"--rdp4-key or --rdp-tls-cert/--rdp-tls-key)\n");
goto err_free_strings;
}
if (b->server_cert && b->server_key) {
b->tls_enabled = 1; b->tls_enabled = 1;
rdp_debug(b, "TLS support activated\n");
}
} }
if (weston_compositor_set_presentation_clock_software(compositor) < 0) if (weston_compositor_set_presentation_clock_software(compositor) < 0)
@ -1379,10 +1392,19 @@ rdp_backend_create(struct weston_compositor *compositor,
b->listener = freerdp_listener_new(); b->listener = freerdp_listener_new();
b->listener->PeerAccepted = rdp_incoming_peer; b->listener->PeerAccepted = rdp_incoming_peer;
b->listener->param4 = b; b->listener->param4 = b;
if (fd >= 0) {
rdp_debug(b, "Using external fd for incoming connections: %d\n", fd);
if (!b->listener->OpenFromSocket(b->listener, fd)) {
weston_log("RDP unable to use external listener fd: %d\n", fd);
goto err_listener;
}
} else {
if (!b->listener->Open(b->listener, config->bind_address, config->port)) { if (!b->listener->Open(b->listener, config->bind_address, config->port)) {
weston_log("unable to bind rdp socket\n"); weston_log("RDP unable to bind socket\n");
goto err_listener; goto err_listener;
} }
}
if (rdp_implant_listener(b, b->listener) < 0) if (rdp_implant_listener(b, b->listener) < 0)
goto err_listener; goto err_listener;
@ -1444,6 +1466,7 @@ config_init_to_defaults(struct weston_rdp_backend_config *config)
config->no_clients_resize = 0; config->no_clients_resize = 0;
config->force_no_compression = 0; config->force_no_compression = 0;
config->remotefx_codec = true; config->remotefx_codec = true;
config->external_listener_fd = -1;
} }
WL_EXPORT int WL_EXPORT int
@ -1470,12 +1493,6 @@ weston_backend_init(struct weston_compositor *compositor,
config_init_to_defaults(&config); config_init_to_defaults(&config);
memcpy(&config, config_base, config_base->struct_size); memcpy(&config, config_base, config_base->struct_size);
if (!config.rdp_key && (!config.server_cert || !config.server_key)) {
weston_log("the RDP compositor requires keys and an optional certificate for RDP or TLS security ("
"--rdp4-key or --rdp-tls-cert/--rdp-tls-key)\n");
return -1;
}
b = rdp_backend_create(compositor, &config); b = rdp_backend_create(compositor, &config);
if (b == NULL) if (b == NULL)
return -1; return -1;

@ -71,6 +71,7 @@ struct rdp_backend {
int no_clients_resize; int no_clients_resize;
int force_no_compression; int force_no_compression;
bool remotefx_codec; bool remotefx_codec;
int external_listener_fd;
}; };
enum peer_item_flags { enum peer_item_flags {

@ -59,6 +59,12 @@ to ship a file containing a certificate.
\fB\-\-rdp\-tls\-cert\fR=\fIfile\fR \fB\-\-rdp\-tls\-cert\fR=\fIfile\fR
The file containing the certificate for doing TLS security. To have TLS security you also need The file containing the certificate for doing TLS security. To have TLS security you also need
to ship a key file. to ship a key file.
.TP
\fB\-\-external\-listener\-fd\fR=\fIfd\fR
Specifies a file descriptor inherited from the process that launched weston
to be listened on for client connections. Only local (such as AF_VSOCK)
sockets should be used, as this will be considered to be a local connection
by the RDP backend, and TLS and RDP security will be bypassed.
.\" *************************************************************** .\" ***************************************************************

Loading…
Cancel
Save