summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCendio <cendio@pairstation.lkpg.cendio.se>2018-01-22 17:46:36 +0100
committerCendio <cendio@pairstation.lkpg.cendio.se>2018-01-31 11:03:32 +0100
commit07abc9bade662e7cfb8d4947f766502c45839d0b (patch)
treea7e914df85409fe3baf6ceb97c9e00713c76c2d6
parente112b69c619e833e934d2428f6556c9047e955ed (diff)
downloadrdesktop-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.c4
-rw-r--r--rdp.c4
-rw-r--r--rdpedisp.c4
-rw-r--r--xwin.c57
4 files changed, 67 insertions, 2 deletions
diff --git a/rdesktop.c b/rdesktop.c
index 085f9b5..e633c21 100644
--- a/rdesktop.c
+++ b/rdesktop.c
@@ -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();
diff --git a/rdp.c b/rdp.c
index e92f77f..ccb21bd 100644
--- a/rdp.c
+++ b/rdp.c
@@ -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);
}
}
diff --git a/rdpedisp.c b/rdpedisp.c
index 94c9050..43903ae 100644
--- a/rdpedisp.c
+++ b/rdpedisp.c
@@ -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
diff --git a/xwin.c b/xwin.c
index c538ed9..776028f 100644
--- a/xwin.c
+++ b/xwin.c
@@ -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,