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>
This commit is contained in:
Brenton DeGeer 2022-03-15 12:24:42 -05:00 committed by Derek Foreman
parent 13e62c9d18
commit 2f9319cef6
5 changed files with 40 additions and 12 deletions

View File

@ -688,6 +688,7 @@ usage(int error_code)
" --width=WIDTH\t\tWidth of desktop\n"
" --height=HEIGHT\tHeight of desktop\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"
" --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"
@ -2772,6 +2773,7 @@ weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
config->server_cert = NULL;
config->server_key = NULL;
config->env_socket = 0;
config->external_listener_fd = -1;
config->no_clients_resize = 0;
config->force_no_compression = 0;
config->remotefx_codec = true;
@ -2793,6 +2795,7 @@ load_rdp_backend(struct weston_compositor *c,
const struct weston_option rdp_options[] = {
{ 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, "height", 0, &parsed_options->height },
{ WESTON_OPTION_STRING, "address", 0, &config.bind_address },

View File

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

View File

@ -1354,14 +1354,27 @@ rdp_backend_create(struct weston_compositor *compositor,
compositor->backend = &b->base;
/* activate TLS only if certificate/key are available */
if (config->server_cert && config->server_key) {
weston_log("TLS support activated\n");
b->server_cert = strdup(config->server_cert);
b->server_key = strdup(config->server_key);
if (!b->server_cert || !b->server_key)
goto err_free_strings;
b->tls_enabled = 1;
}
/* 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;
rdp_debug(b, "TLS support activated\n");
}
}
if (weston_compositor_set_presentation_clock_software(compositor) < 0)
@ -1379,9 +1392,18 @@ rdp_backend_create(struct weston_compositor *compositor,
b->listener = freerdp_listener_new();
b->listener->PeerAccepted = rdp_incoming_peer;
b->listener->param4 = b;
if (!b->listener->Open(b->listener, config->bind_address, config->port)) {
weston_log("unable to bind rdp socket\n");
goto err_listener;
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)) {
weston_log("RDP unable to bind socket\n");
goto err_listener;
}
}
if (rdp_implant_listener(b, b->listener) < 0)
@ -1444,6 +1466,7 @@ config_init_to_defaults(struct weston_rdp_backend_config *config)
config->no_clients_resize = 0;
config->force_no_compression = 0;
config->remotefx_codec = true;
config->external_listener_fd = -1;
}
WL_EXPORT int
@ -1470,12 +1493,6 @@ weston_backend_init(struct weston_compositor *compositor,
config_init_to_defaults(&config);
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);
if (b == NULL)
return -1;

View File

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

View File

@ -59,6 +59,12 @@ to ship a file containing a certificate.
\fB\-\-rdp\-tls\-cert\fR=\fIfile\fR
The file containing the certificate for doing TLS security. To have TLS security you also need
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.
.\" ***************************************************************