diff options
author | Cendio <cendio@pairstation.lkpg.cendio.se> | 2018-01-22 17:46:36 +0100 |
---|---|---|
committer | Cendio <cendio@pairstation.lkpg.cendio.se> | 2018-01-31 11:03:32 +0100 |
commit | 07abc9bade662e7cfb8d4947f766502c45839d0b (patch) | |
tree | a7e914df85409fe3baf6ceb97c9e00713c76c2d6 | |
parent | e112b69c619e833e934d2428f6556c9047e955ed (diff) | |
download | rdesktop-07abc9bade662e7cfb8d4947f766502c45839d0b.zip |
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>
-rw-r--r-- | rdesktop.c | 4 | ||||
-rw-r--r-- | rdp.c | 4 | ||||
-rw-r--r-- | rdpedisp.c | 4 | ||||
-rw-r--r-- | xwin.c | 57 |
4 files changed, 67 insertions, 2 deletions
@@ -141,6 +141,8 @@ RD_BOOL g_has_reconnect_random = False; RD_BOOL g_reconnect_loop = False; uint8 g_client_random[SEC_RANDOM_SIZE]; RD_BOOL g_pending_resize = False; +RD_BOOL g_pending_resize_defer = True; +struct timeval g_pending_resize_defer_timer = {0}; #ifdef WITH_RDPSND RD_BOOL g_rdpsnd = False; @@ -487,6 +489,8 @@ handle_disconnect_reason(RD_BOOL deactivated, uint16 reason) static void rdesktop_reset_state(void) { + g_pending_resize_defer = True; + rdp_reset_state(); #ifdef WITH_SCARD scard_reset_state(); @@ -49,6 +49,8 @@ extern RD_BOOL g_bitmap_cache; extern RD_BOOL g_bitmap_cache_persist_enable; extern RD_BOOL g_numlock_sync; 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 time_t g_wait_for_deactivate_ts; @@ -1484,6 +1486,8 @@ process_ts_logon_info_extended(STREAM s) logger(Protocol, Debug, "process_ts_logon_info_extended(), saving Auto-Reconnect cookie, id=%u", g_reconnect_logonid); + + gettimeofday(&g_pending_resize_defer_timer, NULL); } } @@ -27,6 +27,7 @@ #define RDPEDISP_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl" extern int g_dpi; +extern RD_BOOL g_pending_resize_defer; static void rdpedisp_send(STREAM s); static void rdpedisp_init_packet(STREAM s, uint32 type, uint32 length); @@ -43,6 +44,9 @@ rdpedisp_process_caps_pdu(STREAM s) logger(Protocol, Debug, "rdpedisp_process_caps_pdu(), Max supported monitor area (square pixels) is %d", tmp[0] * tmp[1] * tmp[2]); + + /* Start allowing session resizes */ + g_pending_resize_defer = False; } static void @@ -58,6 +58,9 @@ extern RD_BOOL g_fullscreen; extern RD_BOOL g_grab_keyboard; extern RD_BOOL g_hide_decorations; 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_seamless_spawn_cmd[]; /* Color depth of the RDP session. @@ -2994,6 +2997,21 @@ process_ui() } 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 process_pending_resize () { uint32 width, height; @@ -3007,6 +3025,41 @@ process_pending_resize () if (time_difference_in_ms(g_resize_timer, now) <= 500) 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 */ if (rdpedisp_is_available() == False) { @@ -3015,8 +3068,8 @@ process_pending_resize () * server. */ - g_requested_session_width = g_window_width; - g_requested_session_height = g_window_height; + g_requested_session_width = width; + g_requested_session_height = height; logger(GUI, Verbose, "Window resize detected, reconnecting to new size %dx%d", g_requested_session_width, |