Defer pending resize until after autoreconnect cookie is received

Resize session using disconnect/reconnect sequence should not be
performed before we have received an auto-reconnect cookie which is
used for reconnecting to the session. There is a race when trying to
reconnect at this point so a defer timer is used to delay this further
from the point where the auto-reconnect cookie is received.

Fixes a problem where a login prompt is shown upon reconnect even if
the auto-reconnect cookie is available and used.

Signed-off-by: Henrik Andersson <hean01@cendio.com>
Signed-off-by: Karl Mikaelsson <derfian@cendio.se>
This commit is contained in:
Cendio 2018-01-22 17:46:36 +01:00
parent e112b69c61
commit 07abc9bade
4 changed files with 67 additions and 2 deletions

View File

@ -141,6 +141,8 @@ RD_BOOL g_has_reconnect_random = False;
RD_BOOL g_reconnect_loop = False; RD_BOOL g_reconnect_loop = False;
uint8 g_client_random[SEC_RANDOM_SIZE]; uint8 g_client_random[SEC_RANDOM_SIZE];
RD_BOOL g_pending_resize = False; RD_BOOL g_pending_resize = False;
RD_BOOL g_pending_resize_defer = True;
struct timeval g_pending_resize_defer_timer = {0};
#ifdef WITH_RDPSND #ifdef WITH_RDPSND
RD_BOOL g_rdpsnd = False; RD_BOOL g_rdpsnd = False;
@ -487,6 +489,8 @@ handle_disconnect_reason(RD_BOOL deactivated, uint16 reason)
static void static void
rdesktop_reset_state(void) rdesktop_reset_state(void)
{ {
g_pending_resize_defer = True;
rdp_reset_state(); rdp_reset_state();
#ifdef WITH_SCARD #ifdef WITH_SCARD
scard_reset_state(); scard_reset_state();

4
rdp.c
View File

@ -49,6 +49,8 @@ extern RD_BOOL g_bitmap_cache;
extern RD_BOOL g_bitmap_cache_persist_enable; extern RD_BOOL g_bitmap_cache_persist_enable;
extern RD_BOOL g_numlock_sync; extern RD_BOOL g_numlock_sync;
extern RD_BOOL g_pending_resize; extern RD_BOOL g_pending_resize;
extern RD_BOOL g_pending_resize_defer;
extern struct timeval g_pending_resize_defer_timer;
extern RD_BOOL g_network_error; extern RD_BOOL g_network_error;
extern time_t g_wait_for_deactivate_ts; extern time_t g_wait_for_deactivate_ts;
@ -1484,6 +1486,8 @@ process_ts_logon_info_extended(STREAM s)
logger(Protocol, Debug, logger(Protocol, Debug,
"process_ts_logon_info_extended(), saving Auto-Reconnect cookie, id=%u", "process_ts_logon_info_extended(), saving Auto-Reconnect cookie, id=%u",
g_reconnect_logonid); g_reconnect_logonid);
gettimeofday(&g_pending_resize_defer_timer, NULL);
} }
} }

View File

@ -27,6 +27,7 @@
#define RDPEDISP_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl" #define RDPEDISP_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl"
extern int g_dpi; extern int g_dpi;
extern RD_BOOL g_pending_resize_defer;
static void rdpedisp_send(STREAM s); static void rdpedisp_send(STREAM s);
static void rdpedisp_init_packet(STREAM s, uint32 type, uint32 length); static void rdpedisp_init_packet(STREAM s, uint32 type, uint32 length);
@ -43,6 +44,9 @@ rdpedisp_process_caps_pdu(STREAM s)
logger(Protocol, Debug, logger(Protocol, Debug,
"rdpedisp_process_caps_pdu(), Max supported monitor area (square pixels) is %d", "rdpedisp_process_caps_pdu(), Max supported monitor area (square pixels) is %d",
tmp[0] * tmp[1] * tmp[2]); tmp[0] * tmp[1] * tmp[2]);
/* Start allowing session resizes */
g_pending_resize_defer = False;
} }
static void static void

57
xwin.c
View File

@ -58,6 +58,9 @@ extern RD_BOOL g_fullscreen;
extern RD_BOOL g_grab_keyboard; extern RD_BOOL g_grab_keyboard;
extern RD_BOOL g_hide_decorations; extern RD_BOOL g_hide_decorations;
extern RD_BOOL g_pending_resize; extern RD_BOOL g_pending_resize;
extern RD_BOOL g_pending_resize_defer;
extern struct timeval g_pending_resize_defer_timer;
extern char g_title[]; extern char g_title[];
extern char g_seamless_spawn_cmd[]; extern char g_seamless_spawn_cmd[];
/* Color depth of the RDP session. /* Color depth of the RDP session.
@ -2993,6 +2996,21 @@ process_ui()
return False; return False;
} }
static RD_BOOL
timeval_is_set(struct timeval *time)
{
return (time->tv_sec == 0 && time->tv_usec == 0) ? False : True;
}
/* Handle a pending resize. Resize is handled by either a disconnect/reconnect
sequence or online using RDPEDISP messages. Windows 2008 requires the use of
disconnect/reconnect and to do that without user login credentials the
auto-reconnect cookie is used. Windows 2008 seems sensitive to disconnects
to early in the login sequence so we defer to resize until we get the cookie.
Windows 2016 on the other hand does not seem to send cookies but uses
RDPEDISP so in this case we defer until the RDPEDISP channel is established.
*/
static RD_BOOL static RD_BOOL
process_pending_resize () process_pending_resize ()
{ {
@ -3007,6 +3025,41 @@ process_pending_resize ()
if (time_difference_in_ms(g_resize_timer, now) <= 500) if (time_difference_in_ms(g_resize_timer, now) <= 500)
return False; return False;
/* There is a race problem when using disconnect / reconnect
sequence were one sometimes would be presented with
unexpected login window. Waiting a little bit extra after
getting the reconnect cookie solves this problem. */
if (timeval_is_set(&g_pending_resize_defer_timer) &&
time_difference_in_ms(g_pending_resize_defer_timer, now) >= 100)
{
g_pending_resize_defer_timer.tv_sec = g_pending_resize_defer_timer.tv_usec = 0;
g_pending_resize_defer = False;
}
if (g_pending_resize_defer == True)
return False;
/* only for fullscreen or x%-of-screen-sized windows */
if (g_window_size_type == PercentageOfScreen
|| g_window_size_type == Fullscreen
|| g_fullscreen)
{
/* follow root window size */
width = WidthOfScreen(g_screen);
height = HeightOfScreen(g_screen);
if (g_window_size_type == PercentageOfScreen)
{
/* TODO: Implement percentage of screen */
}
}
else
{
/* Follow window size */
width = g_window_width;
height = g_window_height;
}
/* carry out a resize to desired size */ /* carry out a resize to desired size */
if (rdpedisp_is_available() == False) if (rdpedisp_is_available() == False)
{ {
@ -3015,8 +3068,8 @@ process_pending_resize ()
* server. * server.
*/ */
g_requested_session_width = g_window_width; g_requested_session_width = width;
g_requested_session_height = g_window_height; g_requested_session_height = height;
logger(GUI, Verbose, "Window resize detected, reconnecting to new size %dx%d", logger(GUI, Verbose, "Window resize detected, reconnecting to new size %dx%d",
g_requested_session_width, g_requested_session_width,