From 90e3258c04a609cba0e0ac5c0e55905d84a14da5 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 1/2] 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 From 84970a8d9286637ab00f2a4bd692d3ccbff4960e Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Sat, 23 Nov 2024 14:39:16 +0000 Subject: [PATCH 2/2] xup: Display mismatched version number to user The mismatched versions are now displayed to the user rathe than being buried in the log. This should aid fault reporting and help users find distro-introduced problems with an Internet search. --- xup/xup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xup/xup.c b/xup/xup.c index 6860f594e..cfe65f8da 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -1836,12 +1836,12 @@ lib_mod_process_message(struct mod *mod, struct stream *s) 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); + char msg[128]; + g_snprintf(msg, sizeof(msg), + "Xorg module has version %d, expected %d", + version, CLIENT_INFO_CURRENT_VERSION); + LOG(LOG_LEVEL_ERROR, "%s", msg); + mod->server_msg(mod, msg, 0); mod->caps_processing_status = E_CAPS_NOT_OK; } break;