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.
This commit is contained in:
matt335672 2024-08-06 09:34:00 +01:00
parent ba0b6fd6fe
commit 5111cebec1
2 changed files with 119 additions and 41 deletions

148
xup/xup.c
View File

@ -146,6 +146,72 @@ lib_data_in(struct trans *trans)
return 0; 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 */ /* return error */
static int static int
@ -220,26 +286,32 @@ lib_mod_connect(struct mod *mod)
free_stream(s); free_stream(s);
return 1; return 1;
} }
// Set the transport up
mod->trans->si = mod->si; mod->trans->si = mod->si;
mod->trans->my_source = XRDP_SOURCE_MOD; mod->trans->my_source = XRDP_SOURCE_MOD;
mod->trans->is_term = mod->server_is_term; 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 */ /* 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 " LOG_DEVEL(LOG_LEVEL_INFO, "lib_mod_connect: connected to Xserver "
"(Xorg) sck %lld", "(Xorg) sck %lld",
(long long) (mod->trans->sck)); (long long) (mod->trans->sck));
if (socket_mode == TRANS_MODE_UNIX)
{
lib_mod_log_peer(mod);
}
} }
else else
{ {
mod->server_msg(mod, "connection problem, giving up", 0); mod->server_msg(mod, "connection problem, giving up", 0);
error = 1;
}
if (error == 0 && socket_mode == TRANS_MODE_UNIX)
{
lib_mod_log_peer(mod);
} }
if (error == 0) if (error == 0)
@ -247,6 +319,16 @@ lib_mod_connect(struct mod *mod)
error = send_server_version_message(mod, s); error = send_server_version_message(mod, s);
} }
if (error == 0)
{
error = wait_for_module_caps_message(mod);
}
if (error == 0)
{
error = lib_send_client_info(mod);
}
if (error == 0) if (error == 0)
{ {
error = send_server_monitor_full_invalidate( error = send_server_monitor_full_invalidate(
@ -259,21 +341,14 @@ lib_mod_connect(struct mod *mod)
{ {
trans_delete(mod->trans); trans_delete(mod->trans);
mod->trans = 0; mod->trans = 0;
mod->server_msg(mod, "some problem", 0); mod->server_msg(mod, "Error connecting to Xorg - check log", 0);
return 1;
} }
else else
{ {
mod->server_msg(mod, "connected ok", 0); 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"); 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 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 */ /* return error */
static int static int
@ -1743,6 +1794,7 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
int len; int len;
int type; int type;
char *phold; char *phold;
int version;
int width; int width;
int height; int height;
@ -1769,6 +1821,7 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
} }
else if (type == 2) /* caps */ else if (type == 2) /* caps */
{ {
mod->caps_processing_status = E_CAPS_OK; /* Assume all OK */
LOG_DEVEL(LOG_LEVEL_TRACE, LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: type 2 len %d", len); "lib_mod_process_message: type 2 len %d", len);
for (index = 0; index < num_orders; index++) for (index = 0; index < num_orders; index++)
@ -1779,6 +1832,20 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
switch (type) 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: default:
LOG_DEVEL(LOG_LEVEL_TRACE, LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: unknown" "lib_mod_process_message: unknown"
@ -1788,7 +1855,6 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
} }
s->p = phold + len; s->p = phold + len;
} }
lib_send_client_info(mod);
} }
else if (type == 3) /* order list with len after type */ else if (type == 3) /* order list with len after type */
{ {

View File

@ -21,6 +21,17 @@
#ifndef XUP_H #ifndef XUP_H
#define 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 other h files */
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
@ -202,6 +213,7 @@ struct mod
char *screen_shmem_pixels; char *screen_shmem_pixels;
struct trans *trans; struct trans *trans;
char keycode_set[32]; char keycode_set[32];
enum caps_processing_status caps_processing_status;
}; };
#endif // XUP_H #endif // XUP_H