From 5111cebec117001735be348e50a7513c76a49190 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 6 Aug 2024 09:34:00 +0100 Subject: [PATCH] Wait for capabilities message from Xorg This commit adds a stage into the Xorg connection status to wait for the capabilities message from the Xorg server. This allows us to move the xorgxrdp version check to xrdp from the X server for better reporting to the user. --- xup/xup.c | 144 +++++++++++++++++++++++++++++++++++++++--------------- xup/xup.h | 12 +++++ 2 files changed, 117 insertions(+), 39 deletions(-) diff --git a/xup/xup.c b/xup/xup.c index 71ced6001..6860f594e 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -146,6 +146,72 @@ lib_data_in(struct trans *trans) return 0; } +/******************************************************************************/ +/* + * Wait for module caps message from Xorg module + * + * This routine waits for the Xorg module to send a caps message. + * + * We use this to check the caps are compatible with us before we + * go for a fuull-on connect + */ +static int +wait_for_module_caps_message(struct mod *mod) +{ + int robjs_count; + intptr_t robjs[10]; + + mod->caps_processing_status = E_CAPS_NOT_PROCESSED; + + while (mod->caps_processing_status == E_CAPS_NOT_PROCESSED) + { + robjs_count = 0; + if (trans_get_wait_objs(mod->trans, robjs, &robjs_count) != 0) + { + LOG(LOG_LEVEL_ERROR, "Xorg module has dropped connection"); + return 1; + } + + // We don't need a big timeout here, as all the module has to do is + // turn around the version message. + int status = g_obj_wait(robjs, robjs_count, 0, 0, 3 * 1000); + + if (status < 0) + { + LOG(LOG_LEVEL_ERROR, "No response from Xorg module before timeout"); + return 1; + } + + (void)trans_check_wait_objs(mod->trans); + } + + return (mod->caps_processing_status == E_CAPS_OK) ? 0 : 1; +} + +/******************************************************************************/ +/* return error */ +static int +lib_send_client_info(struct mod *mod) +{ + struct stream *s; + int len; + + LOG_DEVEL(LOG_LEVEL_TRACE, "lib_send_client_info:"); + make_stream(s); + init_stream(s, 8192); + s_push_layer(s, iso_hdr, 4); + out_uint16_le(s, 104); + g_memcpy(s->p, &(mod->client_info), sizeof(mod->client_info)); + s->p += sizeof(mod->client_info); + s_mark_end(s); + len = (int)(s->end - s->data); + s_pop_layer(s, iso_hdr); + out_uint32_le(s, len); + lib_send_copy(mod, s); + free_stream(s); + return 0; +} + /******************************************************************************/ /* return error */ static int @@ -220,31 +286,47 @@ lib_mod_connect(struct mod *mod) free_stream(s); return 1; } + + // Set the transport up mod->trans->si = mod->si; mod->trans->my_source = XRDP_SOURCE_MOD; mod->trans->is_term = mod->server_is_term; + mod->trans->trans_data_in = lib_data_in; + mod->trans->header_size = 8; + mod->trans->callback_data = mod; + mod->trans->no_stream_init_on_data_in = 1; + mod->trans->extra_flags = 1; /* Give the X server a bit of time to start */ - if (trans_connect(mod->trans, mod->ip, con_port, 30 * 1000) == 0) + error = trans_connect(mod->trans, mod->ip, con_port, 30 * 1000); + if (error == 0) { LOG_DEVEL(LOG_LEVEL_INFO, "lib_mod_connect: connected to Xserver " "(Xorg) sck %lld", (long long) (mod->trans->sck)); + if (socket_mode == TRANS_MODE_UNIX) + { + lib_mod_log_peer(mod); + } } else { mod->server_msg(mod, "connection problem, giving up", 0); - error = 1; } - if (error == 0 && socket_mode == TRANS_MODE_UNIX) + if (error == 0) { - lib_mod_log_peer(mod); + error = send_server_version_message(mod, s); } if (error == 0) { - error = send_server_version_message(mod, s); + error = wait_for_module_caps_message(mod); + } + + if (error == 0) + { + error = lib_send_client_info(mod); } if (error == 0) @@ -259,21 +341,14 @@ lib_mod_connect(struct mod *mod) { trans_delete(mod->trans); mod->trans = 0; - mod->server_msg(mod, "some problem", 0); - return 1; + mod->server_msg(mod, "Error connecting to Xorg - check log", 0); } else { mod->server_msg(mod, "connected ok", 0); - mod->trans->trans_data_in = lib_data_in; - mod->trans->header_size = 8; - mod->trans->callback_data = mod; - mod->trans->no_stream_init_on_data_in = 1; - mod->trans->extra_flags = 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_connect"); - return 0; + return error; } /******************************************************************************/ @@ -1708,30 +1783,6 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) return rv; } -/******************************************************************************/ -/* return error */ -static int -lib_send_client_info(struct mod *mod) -{ - struct stream *s; - int len; - - LOG_DEVEL(LOG_LEVEL_TRACE, "lib_send_client_info:"); - make_stream(s); - init_stream(s, 8192); - s_push_layer(s, iso_hdr, 4); - out_uint16_le(s, 104); - g_memcpy(s->p, &(mod->client_info), sizeof(mod->client_info)); - s->p += sizeof(mod->client_info); - s_mark_end(s); - len = (int)(s->end - s->data); - s_pop_layer(s, iso_hdr); - out_uint32_le(s, len); - lib_send_copy(mod, s); - free_stream(s); - return 0; -} - /******************************************************************************/ /* return error */ static int @@ -1743,6 +1794,7 @@ lib_mod_process_message(struct mod *mod, struct stream *s) int len; int type; char *phold; + int version; int width; int height; @@ -1769,6 +1821,7 @@ lib_mod_process_message(struct mod *mod, struct stream *s) } else if (type == 2) /* caps */ { + mod->caps_processing_status = E_CAPS_OK; /* Assume all OK */ LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: type 2 len %d", len); for (index = 0; index < num_orders; index++) @@ -1779,6 +1832,20 @@ lib_mod_process_message(struct mod *mod, struct stream *s) switch (type) { + case 100: + in_uint32_le(s, version); + if (version != CLIENT_INFO_CURRENT_VERSION) + { + LOG(LOG_LEVEL_ERROR, + "Xorg module has version %d, expected %d", + version, CLIENT_INFO_CURRENT_VERSION); + mod->server_msg(mod, + "Xorg module has wrong version number", + 0); + mod->caps_processing_status = E_CAPS_NOT_OK; + } + break; + default: LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: unknown" @@ -1788,7 +1855,6 @@ lib_mod_process_message(struct mod *mod, struct stream *s) } s->p = phold + len; } - lib_send_client_info(mod); } else if (type == 3) /* order list with len after type */ { diff --git a/xup/xup.h b/xup/xup.h index 37aa67dc6..6486be046 100644 --- a/xup/xup.h +++ b/xup/xup.h @@ -21,6 +21,17 @@ #ifndef XUP_H #define XUP_H +/** + * Enum for the states used to process a + * capabilities message from the Xorg module + */ +enum caps_processing_status +{ + E_CAPS_NOT_PROCESSED, ///< Capabilities mesage from module not processed + E_CAPS_OK, ///< Capabilities are OK + E_CAPS_NOT_OK ///< Capabilities are not OK +}; + /* include other h files */ #include "arch.h" #include "parse.h" @@ -202,6 +213,7 @@ struct mod char *screen_shmem_pixels; struct trans *trans; char keycode_set[32]; + enum caps_processing_status caps_processing_status; }; #endif // XUP_H