Merge pull request #1664 from vworkspace/auto-reconnect

Addition of auto reconnect to FreeRDP core and X11 client
This commit is contained in:
Marc-André Moreau 2014-01-23 10:15:18 -08:00
commit ae9c10e233
7 changed files with 120 additions and 2 deletions

View File

@ -51,6 +51,8 @@
#include <X11/extensions/Xrender.h>
#endif
#define WITH_AUTORECONNECT
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -1336,6 +1338,51 @@ void* xf_channels_thread(void* arg)
return NULL;
}
#ifdef WITH_AUTORECONNECT
BOOL xf_auto_reconnect(freerdp* instance)
{
xfContext* xfc = (xfContext*)instance->context;
UINT32 num_retries = 0;
UINT32 max_retries = instance->settings->AutoReconnectMaxRetries;
/* Only auto reconnect on network disconnects. */
if (freerdp_error_info(instance) != 0) return FALSE;
/* A network disconnect was detected */
fprintf(stderr, "Network disconnect!\n");
if (!instance->settings->AutoReconnectionEnabled)
{
/* No auto-reconnect - just quit */
return FALSE;
}
/* Perform an auto-reconnect. */
for (;;)
{
/* Quit retrying if max retries has been exceeded */
if (num_retries++ >= max_retries)
{
return FALSE;
}
/* Attempt the next reconnect */
fprintf(stderr, "Attempting reconnect (%u of %u)\n", num_retries, max_retries);
if (freerdp_reconnect(instance))
{
xfc->disconnect = FALSE;
return TRUE;
}
sleep(5);
}
fprintf(stderr, "Maximum reconnect retries exceeded\n");
return FALSE;
}
#endif
/** Main loop for the rdp connection.
* It will be run from the thread's entry point (thread_func()).
* It initiates the connection, and will continue to run until the session ends,
@ -1382,6 +1429,11 @@ void* xf_thread(void* param)
ZeroMemory(wfds, sizeof(wfds));
ZeroMemory(&timeout, sizeof(struct timeval));
#ifdef WITH_AUTORECONNECT
instance->settings->AutoReconnectionEnabled = TRUE;
instance->settings->AutoReconnectMaxRetries = 20;
#endif
status = freerdp_connect(instance);
xfc = (xfContext*) instance->context;
@ -1526,6 +1578,9 @@ void* xf_thread(void* param)
{
if (freerdp_check_fds(instance) != TRUE)
{
#ifdef WITH_AUTORECONNECT
if (xf_auto_reconnect(instance)) continue;
#endif
fprintf(stderr, "Failed to check FreeRDP file descriptor\n");
break;
}

View File

@ -221,6 +221,7 @@ FREERDP_API void freerdp_context_free(freerdp* instance);
FREERDP_API BOOL freerdp_connect(freerdp* instance);
FREERDP_API BOOL freerdp_shall_disconnect(freerdp* instance);
FREERDP_API BOOL freerdp_disconnect(freerdp* instance);
FREERDP_API BOOL freerdp_reconnect(freerdp* instance);
FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount);
FREERDP_API BOOL freerdp_check_fds(freerdp* instance);

View File

@ -336,6 +336,33 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
return status;
}
BOOL rdp_client_reconnect(rdpRdp* rdp)
{
int i;
transport_disconnect(rdp->transport);
mcs_free(rdp->mcs);
nego_free(rdp->nego);
license_free(rdp->license);
transport_free(rdp->transport);
/* Reset virtual channel status */
for (i = 0; i < rdp->settings->ChannelCount; i++)
{
rdp->settings->ChannelDefArray[i].joined = FALSE;
}
rdp->transport = transport_new(rdp->settings);
rdp->license = license_new(rdp);
rdp->nego = nego_new(rdp->transport);
rdp->mcs = mcs_new(rdp->transport);
rdp->transport->layer = TRANSPORT_LAYER_TCP;
return rdp_client_connect(rdp);
}
static BYTE fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
static BOOL rdp_client_establish_keys(rdpRdp* rdp)

View File

@ -49,6 +49,7 @@ enum CONNECTION_STATE
BOOL rdp_client_connect(rdpRdp* rdp);
BOOL rdp_client_redirect(rdpRdp* rdp);
BOOL rdp_client_reconnect(rdpRdp* rdp);
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);

View File

@ -322,6 +322,11 @@ BOOL freerdp_disconnect(freerdp* instance)
return TRUE;
}
BOOL freerdp_reconnect(freerdp* instance)
{
return rdp_client_reconnect(instance->context->rdp);
}
BOOL freerdp_shall_disconnect(freerdp* instance)
{
return instance->context->rdp->disconnect;

View File

@ -41,6 +41,9 @@
#include <net/if.h>
#ifdef __APPLE__
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
#ifndef TCP_KEEPIDLE
#define TCP_KEEPIDLE TCP_KEEPALIVE
#endif
@ -251,7 +254,29 @@ BOOL tcp_set_keep_alive_mode(rdpTcp* tcp)
if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &option_value, option_len) < 0)
{
perror("setsockopt() IPPROTO_TCP, SO_KEEPIDLE:");
perror("setsockopt() IPPROTO_TCP, TCP_KEEPIDLE:");
return FALSE;
}
#endif
#ifdef TCP_KEEPCNT
option_value = 3;
option_len = sizeof(option_value);
if (setsockopt(tcp->sockfd, SOL_TCP, TCP_KEEPCNT, (void *) &option_value, option_len) < 0)
{
perror("setsockopt() SOL_TCP, TCP_KEEPCNT:");
return FALSE;
}
#endif
#ifdef TCP_KEEPINTVL
option_value = 2;
option_len = sizeof(option_value);
if (setsockopt(tcp->sockfd, SOL_TCP, TCP_KEEPINTVL, (void *) &option_value, option_len) < 0)
{
perror("setsockopt() SOL_TCP, TCP_KEEPINTVL:");
return FALSE;
}
#endif

View File

@ -49,6 +49,8 @@ static void fatal_handler(int signum)
struct sigaction default_sigaction;
sigset_t this_mask;
printf("fatal_handler: signum=%d\n", signum);
if (terminal_needs_reset)
tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags);
@ -74,7 +76,6 @@ const int fatal_signals[] =
SIGILL,
SIGINT,
SIGKILL,
SIGPIPE,
SIGQUIT,
SIGSEGV,
SIGSTOP,
@ -128,6 +129,9 @@ int freerdp_handle_signals(void)
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
/* Ignore SIGPIPE signal. */
signal(SIGPIPE, SIG_IGN);
return 0;
}