Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resize state machine: A fix and a question #2929

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion common/xrdp_client_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ struct xrdp_client_info
int no_orders_supported;
int use_cache_glyph_v2;
int rail_enable;
int suppress_output;
// Mask of reasons why output may be suppressed
// (see enum suppress_output_reason)
unsigned int suppress_output_mask;

int enable_token_login;
char domain_user_separator[16];
Expand Down Expand Up @@ -227,6 +229,12 @@ enum xrdp_encoder_flags
KEY_FRAME_REQUESTED = 1 << 3
};

/*
* Return true if output is suppressed for a particular reason
*/
#define OUTPUT_SUPPRESSED_FOR_REASON(ci,reason) \
(((ci)->suppress_output_mask & (unsigned int)reason) != 0)

/* yyyymmdd of last incompatible change to xrdp_client_info */
/* also used for changes to all the xrdp installed headers */
#define CLIENT_INFO_CURRENT_VERSION 20230425
Expand Down
6 changes: 6 additions & 0 deletions libxrdp/libxrdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,12 @@ libxrdp_reset(struct xrdp_session *session,
return 1;
}

/*
* Stop output from the client during the deactivation-reactivation
* sequence [MS-RDPBCGR] 1.3.1.3 */
xrdp_rdp_suppress_output((struct xrdp_rdp *)session->rdp, 1,
XSO_REASON_DEACTIVATE_REACTIVATE, 0, 0, 0, 0);

/* shut down the rdp client
*
* When resetting the lib, disable application input checks, as
Expand Down
29 changes: 29 additions & 0 deletions libxrdp/libxrdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,20 @@ int
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s);

/* xrdp_rdp.c */

/**
* Reasons why output is being suppressed or restarted
*/
enum suppress_output_reason
{
/// Client has requested suppress via TS_SUPPRESS_OUTPUT_PDU
XSO_REASON_CLIENT_REQUEST = (1 << 0),
/// Deactivation-Reactivation Sequence [MS-RDPBCGR] 1.3.1.3
XSO_REASON_DEACTIVATE_REACTIVATE = (1 << 1),
/// Dynamic resize in progress
XSO_REASON_DYNAMIC_RESIZE = (1 << 2)
};

struct xrdp_rdp *
xrdp_rdp_create(struct xrdp_session *session, struct trans *trans);
void
Expand Down Expand Up @@ -438,6 +452,21 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self);
int
xrdp_rdp_send_session_info(struct xrdp_rdp *self, const char *data,
int data_bytes);
/**
* Request output suppress or resume
*
* @param self RDP struct
* @param suppress (!= 0 for suppress, 0 for resume)
* @param reason Why the output is being suppressed or resumed
* @param left Left pixel of repaint area (ignored for suppress)
* @param top Top pixel of repaint area (ignored for suppress)
* @param right Right pixel of inclusive repaint area (ignored for suppress)
* @param bottom Bottom pixel of inclusive repaint area (ignored for suppress)
*/
void
xrdp_rdp_suppress_output(struct xrdp_rdp *self, int suppress,
enum suppress_output_reason reason,
int left, int top, int right, int bottom);

/* xrdp_orders.c */
struct xrdp_orders *
Expand Down
128 changes: 78 additions & 50 deletions libxrdp/xrdp_rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,20 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s)
self->session->up_and_running = 1;
LOG_DEVEL(LOG_LEVEL_INFO, "yeah, up_and_running");
xrdp_rdp_send_data_update_sync(self);

/* This is also the end of an Deactivation-reactivation
* sequence [MS-RDPBCGR] 1.3.1.3 */
xrdp_rdp_suppress_output(self, 0, XSO_REASON_DEACTIVATE_REACTIVATE,
0, 0,
self->client_info.display_sizes.session_width,
self->client_info.display_sizes.session_height);

if (self->session->callback != 0)
{
/* call to xrdp_wm.c : callback */
self->session->callback(self->session->id, 0x555a, 0, 0,
0, 0);
}
xrdp_channel_drdynvc_start(self->sec_layer->chan_layer);
}
else
Expand Down Expand Up @@ -1401,69 +1415,83 @@ xrdp_rdp_process_frame_ack(struct xrdp_rdp *self, struct stream *s)
return 0;
}

/*****************************************************************************/
void
xrdp_rdp_suppress_output(struct xrdp_rdp *self, int suppress,
enum suppress_output_reason reason,
int left, int top, int right, int bottom)
{
int old_suppress = self->client_info.suppress_output_mask != 0;
if (suppress)
{
self->client_info.suppress_output_mask |= (unsigned int)reason;
}
else
{
self->client_info.suppress_output_mask &= ~(unsigned int)reason;
}

int current_suppress = self->client_info.suppress_output_mask != 0;
if (current_suppress != old_suppress && self->session->callback != 0)
{
self->session->callback(self->session->id, 0x5559, suppress,
MAKELONG(left, top),
MAKELONG(right, bottom), 0);
}
}

/*****************************************************************************/
/* Process a [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU message */
static int
xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s)
{
int rv = 1;
int allowDisplayUpdates;
int left;
int top;
int right;
int bottom;

if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU"))
{
return 1;
}
in_uint8(s, allowDisplayUpdates);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU "
"allowDisplayUpdates %d", allowDisplayUpdates);
switch (allowDisplayUpdates)
if (s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU"))
{
case 0: /* SUPPRESS_DISPLAY_UPDATES */
self->client_info.suppress_output = 1;
LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be suppressed");
if (self->session->callback != 0)
{
self->session->callback(self->session->id, 0x5559, 1,
0, 0, 0);
}
else
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Bug: no callback registered for xrdp_rdp_process_suppress");
}
break;
case 1: /* ALLOW_DISPLAY_UPDATES */
self->client_info.suppress_output = 0;
LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be enabled");
if (!s_check_rem_and_log(s, 11, "Parsing [MS-RDPBCGR] Padding and TS_RECTANGLE16"))
{
return 1;
}
in_uint8s(s, 3); /* pad */
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_RECTANGLE16 "
"left %d, top %d, right %d, bottom %d",
left, top, right, bottom);
if (self->session->callback != 0)
{
self->session->callback(self->session->id, 0x5559, 0,
MAKELONG(left, top),
MAKELONG(right, bottom), 0);
}
else
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Bug: no callback registered for xrdp_rdp_process_suppress");
}
break;
in_uint8(s, allowDisplayUpdates);
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU "
"allowDisplayUpdates %d", allowDisplayUpdates);
switch (allowDisplayUpdates)
{
case 0: /* SUPPRESS_DISPLAY_UPDATES */
LOG_DEVEL(LOG_LEVEL_DEBUG,
"Client requested display output to be suppressed");
xrdp_rdp_suppress_output(self, 1,
XSO_REASON_CLIENT_REQUEST,
0, 0, 0, 0);
rv = 0;
break;
case 1: /* ALLOW_DISPLAY_UPDATES */
LOG_DEVEL(LOG_LEVEL_DEBUG,
"Client requested display output to be enabled");
if (s_check_rem_and_log(s, 11,
"Parsing [MS-RDPBCGR] Padding and TS_RECTANGLE16"))
{
in_uint8s(s, 3); /* pad */
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [MS-RDPBCGR] TS_RECTANGLE16 "
"left %d, top %d, right %d, bottom %d",
left, top, right, bottom);
xrdp_rdp_suppress_output(self, 0,
XSO_REASON_CLIENT_REQUEST,
left, top, right, bottom);
rv = 0;
}
break;
}
}
return 0;
return rv;
}

/*****************************************************************************/
Expand Down
6 changes: 6 additions & 0 deletions vnc/vnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,12 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
{
LOG(LOG_LEVEL_DEBUG, "VNC server successfully resized");
log_screen_layout(LOG_LEVEL_INFO, "NewLayout", &layout);
// If this resize was requested by the client mid-session
// (dynamic resize), we need to tell xrdp_mm that
// it's OK to continue with the resize state machine.
// We do this by sending a reset with bpp == 0
error = v->server_reset(v, v->server_width,
v->server_height, 0);
}
else
{
Expand Down
5 changes: 5 additions & 0 deletions xrdp/xrdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,13 +471,18 @@ struct display_control_monitor_layout_data
enum display_resize_state state;
int last_state_update_timestamp;
int start_time;
/// This flag is set if the state machine needs to
/// shutdown/startup EGFX
int using_egfx;
};

int
xrdp_mm_drdynvc_up(struct xrdp_mm *self);
int
xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress,
int left, int top, int right, int bottom);
int
xrdp_mm_up_and_running(struct xrdp_mm *self);
struct xrdp_mm *
xrdp_mm_create(struct xrdp_wm *owner);
void
Expand Down
Loading
Loading