From eced6ca82116f455e1e6a166c8f04840c063c045 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Fri, 12 Apr 2013 06:46:07 +0000 Subject: [PATCH] Reconnect upon network failure, retry as long the autoreconnect cookie is valid. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/rdesktop/trunk@1707 423420c4-83ab-492f-b58f-81f9feb106b5 --- proto.h | 1 + rdesktop.c | 39 +++++++++++++++++++++++++++++++++++---- rdp.c | 6 ++++++ tcp.c | 18 ++++++++++++++++++ xwin.c | 6 ++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/proto.h b/proto.h index 903814a..3aadb91 100644 --- a/proto.h +++ b/proto.h @@ -268,6 +268,7 @@ void ui_deinit(void); RD_BOOL ui_create_window(void); void ui_resize_window(void); void ui_destroy_window(void); +RD_BOOL ui_have_window(void); void xwin_toggle_fullscreen(void); int ui_select(int rdp_socket); void ui_move_pointer(int x, int y); diff --git a/rdesktop.c b/rdesktop.c index 9615132..b7026ed 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -80,6 +80,7 @@ int g_pos = 0; /* 0 position unspecified, extern int g_tcp_port_rdp; int g_server_depth = -1; int g_win_button_size = 0; /* If zero, disable single app mode */ +RD_BOOL g_network_error = False; RD_BOOL g_bitmap_compression = True; RD_BOOL g_sendmotion = True; RD_BOOL g_bitmap_cache = True; @@ -119,6 +120,7 @@ uint32 g_redirect_flags = 0; uint32 g_reconnect_logonid = 0; char g_reconnect_random[16]; +time_t g_reconnect_random_ts; RD_BOOL g_has_reconnect_random = False; uint8 g_client_random[SEC_RANDOM_SIZE]; RD_BOOL g_pending_resize = False; @@ -489,6 +491,7 @@ main(int argc, char *argv[]) char password[64]; char shell[256]; char directory[256]; + RD_BOOL reconnect_loop; RD_BOOL prompt_password, deactivated; struct passwd *pw; uint32 flags, ext_disc_reason = 0; @@ -1066,7 +1069,7 @@ main(int argc, char *argv[]) lspci_init(); rdpdr_init(); - + reconnect_loop = False; while (1) { rdesktop_reset_state(); @@ -1084,7 +1087,21 @@ main(int argc, char *argv[]) ui_init_connection(); if (!rdp_connect(server, flags, domain, password, shell, directory, g_redirect)) - return EX_PROTOCOL; + { + + g_network_error = False; + + if (reconnect_loop == False) + return EX_PROTOCOL; + + /* check if auto reconnect cookie has timed out */ + if (time(NULL) - g_reconnect_random_ts > (3600 + 600)) + return EX_PROTOCOL; + + fprintf(stderr, "Failed to connect, retry in 4 secs...\n"); + sleep(4); + continue; + } /* By setting encryption to False here, we have an encrypted login packet but unencrypted transfer of other packets */ @@ -1095,11 +1112,15 @@ main(int argc, char *argv[]) DEBUG(("Connection successful.\n")); memset(password, 0, sizeof(password)); - if (!g_redirect) + /* only create a window if we dont have one intialized */ + if (!ui_have_window()) + { if (!ui_create_window()) return EX_OSERR; + } g_redirect = False; + reconnect_loop = False; rdp_main_loop(&deactivated, &ext_disc_reason); DEBUG(("Disconnecting...\n")); @@ -1109,12 +1130,22 @@ main(int argc, char *argv[]) if (g_redirect) continue; + /* handle network error and start autoreconnect */ + if (g_network_error) + { + g_network_error = False; + reconnect_loop = True; + continue; + } + ui_seamless_end(); ui_destroy_window(); + + /* Enter a reconnect loop if we have a pending resize request */ if (g_pending_resize) { - /* If we have a pending resize, reconnect using the new size, rather than exit */ g_pending_resize = False; + reconnect_loop = True; continue; } break; diff --git a/rdp.c b/rdp.c index 101852d..12f40a5 100644 --- a/rdp.c +++ b/rdp.c @@ -54,6 +54,7 @@ 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_network_error; uint8 *g_next_packet; uint32 g_rdp_shareid; @@ -72,6 +73,7 @@ extern uint32 g_redirect_flags; extern uint32 g_reconnect_logonid; extern char g_reconnect_random[16]; +extern time_t g_reconnect_random_ts; extern RD_BOOL g_has_reconnect_random; extern uint8 g_client_random[SEC_RANDOM_SIZE]; @@ -1369,6 +1371,7 @@ process_pdu_logon(STREAM s) in_uint32_le(s, g_reconnect_logonid); in_uint8a(s, g_reconnect_random, 16); g_has_reconnect_random = True; + g_reconnect_random_ts = time(NULL); DEBUG(("Saving auto-reconnect cookie, id=%u\n", g_reconnect_logonid)); } } @@ -1644,6 +1647,9 @@ rdp_connect(char *server, uint32 flags, char *domain, char *password, /* run RDP loop until first licence demand active PDU */ while (!g_rdp_shareid) { + if (g_network_error) + return False; + if (!rdp_loop(&deactivated, &ext_disc_reason)) return False; } diff --git a/tcp.c b/tcp.c index f11bf64..65a3960 100644 --- a/tcp.c +++ b/tcp.c @@ -64,6 +64,7 @@ static struct stream g_in; static struct stream g_out[STREAM_COUNT]; int g_tcp_port_rdp = TCP_PORT_RDP; extern RD_BOOL g_user_quit; +extern RD_BOOL g_network_error; /* wait till socket is ready to write or timeout */ static RD_BOOL @@ -140,6 +141,10 @@ tcp_send(STREAM s) else { error("SSL_write: %d (%s)\n", ssl_err, TCP_STRERROR); + g_network_error = True; +#ifdef WITH_SCARD + scard_unlock(SCARD_LOCK_TCP); +#endif return; } } @@ -157,6 +162,10 @@ tcp_send(STREAM s) else { error("send: %s\n", TCP_STRERROR); + g_network_error = True; +#ifdef WITH_SCARD + scard_unlock(SCARD_LOCK_TCP); +#endif return; } } @@ -224,6 +233,7 @@ tcp_recv(STREAM s, uint32 length) } ERR_print_errors_fp(stdout); + g_network_error = True; return NULL; } @@ -234,6 +244,7 @@ tcp_recv(STREAM s, uint32 length) else if (ssl_err != SSL_ERROR_NONE) { error("SSL_read: %d (%s)\n", ssl_err, TCP_STRERROR); + g_network_error = True; return NULL; } @@ -250,6 +261,7 @@ tcp_recv(STREAM s, uint32 length) else { error("recv: %s\n", TCP_STRERROR); + g_network_error = True; return NULL; } } @@ -532,6 +544,12 @@ tcp_reset_state(void) { int i; + if (g_ssl) + { + SSL_free(g_ssl); + g_ssl = NULL; + } + g_sock = -1; /* reset socket */ /* Clear the incoming stream */ diff --git a/xwin.c b/xwin.c index 297d713..76e4fb4 100644 --- a/xwin.c +++ b/xwin.c @@ -2160,6 +2160,12 @@ ui_resize_window() } } +RD_BOOL +ui_have_window() +{ + return g_wnd ? True : False; +} + void ui_destroy_window(void) {