Merge pull request #252 from rdesktop/revert-249-reconnect-related-fixes

Revert "Reconnect-related fixes"
This commit is contained in:
Karl Mikaelsson 2018-03-23 15:52:50 +01:00 committed by GitHub
commit a0bf290ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 152 deletions

View File

@ -1395,55 +1395,54 @@ main(int argc, char *argv[])
deactivated = False;
g_reconnect_loop = False;
ext_disc_reason = 0;
rdp_main_loop(&deactivated, &ext_disc_reason);
tcp_run_ui(False);
logger(Core, Verbose, "Disconnecting...");
rdp_disconnect();
if (deactivated)
/* If error info is set we do want to exit rdesktop
connect loop. We do this by clearing flags that
triggers a reconnect that could be set elsewere */
if (ext_disc_reason != 0)
{
/* Server disconnected while deactivated */
logger(Core, Notice, "Disconnecting...");
break;
g_redirect = False;
g_network_error = False;
g_pending_resize = False;
}
else
if (g_redirect)
continue;
/* handle network error and start autoreconnect */
if (g_network_error && !deactivated)
{
/* Unexpected disconnect or rdesktop-initiated loop exit */
if (g_user_quit)
{
/* User closed window */
break;
}
else if (g_redirect)
{
/* see beginning of loop */
}
else if (g_network_error)
{
logger(Core, Notice,
"Disconnected due to network error, retrying to reconnect for %d minutes.",
RECONNECT_TIMEOUT / 60);
g_network_error = False;
g_reconnect_loop = True;
}
else if (g_pending_resize)
{
/* Prepare to re-create rdesktop window */
ui_seamless_end();
ui_destroy_window();
logger(Core, Verbose, "Resize reconnect loop triggered, new size %dx%d",
g_requested_session_width, g_requested_session_height);
g_pending_resize = False;
g_reconnect_loop = True;
}
logger(Core, Notice,
"Disconnected due to network error, retrying to reconnect for %d minutes.",
RECONNECT_TIMEOUT / 60);
g_network_error = False;
g_reconnect_loop = True;
continue;
}
}
ui_seamless_end();
ui_destroy_window();
ui_seamless_end();
ui_destroy_window();
/* Enter a reconnect loop if we have a pending resize request */
if (g_pending_resize)
{
logger(Core, Verbose, "Resize reconnect loop triggered, new size %dx%d",
g_requested_session_width, g_requested_session_height);
g_pending_resize = False;
g_reconnect_loop = True;
continue;
}
/* exit main reconnect loop */
break;
}
cache_save_state();
ui_deinit();

146
tcp.c
View File

@ -58,13 +58,6 @@
#define STREAM_COUNT 1
#endif
#ifdef IPv6
static struct addrinfo *g_server_address = NULL;
#else
struct sockaddr_in *g_server_address = NULL;
#endif
static char *g_last_server_name = NULL;
static RD_BOOL g_ssl_initialized = False;
static SSL *g_ssl = NULL;
static SSL_CTX *g_ssl_ctx = NULL;
@ -423,85 +416,47 @@ tcp_tls_get_server_pubkey(STREAM s)
return (s->size != 0);
}
/* Helper function to determine if rdesktop should resolve hostnames again or not */
static RD_BOOL
tcp_connect_resolve_hostname(const char *server)
{
return (g_server_address == NULL ||
g_last_server_name == NULL ||
strcmp(g_last_server_name, server) != 0);
}
/* Establish a connection on the TCP layer
This function tries to avoid resolving any server address twice. The
official Windows 2008 documentation states that the windows farm name
should be a round-robin DNS entry containing all the terminal servers
in the farm. When connected to the farm address, if we look up the
address again when reconnecting (for any reason) we risk reconnecting
to a different server in the farm.
*/
/* Establish a connection on the TCP layer */
RD_BOOL
tcp_connect(char *server)
{
socklen_t option_len;
uint32 option_value;
int i;
char buf[NI_MAXHOST];
#ifdef IPv6
int n;
struct addrinfo hints, *res, *addr;
struct sockaddr *oldaddr;
struct addrinfo hints, *res, *ressave;
char tcp_port_rdp_s[10];
if (tcp_connect_resolve_hostname(server))
{
snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
{
logger(Core, Error, "tcp_connect(), getaddrinfo() failed: %s", gai_strerror(n));
return False;
}
}
else
if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
{
res = g_server_address;
logger(Core, Error, "tcp_connect(), getaddrinfo() failed: %s", gai_strerror(n));
return False;
}
ressave = res;
g_sock = -1;
for (addr = res; addr != NULL; addr = addr->ai_next)
while (res)
{
g_sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (g_sock < 0)
g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (!(g_sock < 0))
{
logger(Core, Debug, "tcp_connect(), socket() failed: %s", TCP_STRERROR);
continue;
if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
break;
TCP_CLOSE(g_sock);
g_sock = -1;
}
n = getnameinfo(addr->ai_addr, addr->ai_addrlen, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
if (n != 0)
{
logger(Core, Error, "tcp_connect(), getnameinfo() failed: %s", gai_strerror(n));
return False;
}
logger(Core, Debug, "tcp_connect(), trying %s (%s)", server, buf);
if (connect(g_sock, addr->ai_addr, addr->ai_addrlen) == 0)
break;
TCP_CLOSE(g_sock);
g_sock = -1;
res = res->ai_next;
}
freeaddrinfo(ressave);
if (g_sock == -1)
{
@ -509,50 +464,19 @@ tcp_connect(char *server)
return False;
}
/* Save server address for later use, if we haven't already. */
if (g_server_address == NULL)
{
g_server_address = xmalloc(sizeof(struct addrinfo));
g_server_address->ai_addr = xmalloc(sizeof(struct sockaddr_storage));
}
if (g_server_address != addr)
{
/* don't overwrite ptr to allocated sockaddr */
oldaddr = g_server_address->ai_addr;
memcpy(g_server_address, addr, sizeof(struct addrinfo));
g_server_address->ai_addr = oldaddr;
memcpy(g_server_address->ai_addr, addr->ai_addr, addr->ai_addrlen);
g_server_address->ai_canonname = NULL;
g_server_address->ai_next = NULL;
freeaddrinfo(res);
}
#else /* no IPv6 support */
struct hostent *nslookup = NULL;
if (tcp_connect_resolve_hostname(server))
struct hostent *nslookup;
struct sockaddr_in servaddr;
if ((nslookup = gethostbyname(server)) != NULL)
{
if (g_server_address != NULL)
xfree(g_server_address);
g_server_address = xmalloc(sizeof(struct sockaddr_in));
g_server_address->sin_family = AF_INET;
g_server_address->sin_port = htons((uint16) g_tcp_port_rdp);
if ((nslookup = gethostbyname(server)) != NULL)
{
memcpy(&g_server_address->sin_addr, nslookup->h_addr,
sizeof(g_server_address->sin_addr));
}
else if ((g_server_address->sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
{
logger(Core, Error, "tcp_connect(), unable to resolve host '%s'", server);
return False;
}
memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr));
}
else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
{
logger(Core, Error, "tcp_connect(), unable to resolve host '%s'", server);
return False;
}
if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
@ -561,12 +485,10 @@ tcp_connect(char *server)
return False;
}
logger(Core, Debug, "tcp_connect(), trying %s (%s)",
server, inet_ntop(g_server_address->sin_family,
&g_server_address->sin_addr,
buf, sizeof(buf)));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
if (connect(g_sock, (struct sockaddr *) g_server_address, sizeof(struct sockaddr)) < 0)
if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
{
if (!g_reconnect_loop)
logger(Core, Error, "tcp_connect(), connect() failed: %s", TCP_STRERROR);
@ -602,10 +524,6 @@ tcp_connect(char *server)
g_out[i].data = (uint8 *) xmalloc(g_out[i].size);
}
/* After successful connect: update the last server name */
if (g_last_server_name)
xfree(g_last_server_name);
g_last_server_name = strdup(server);
return True;
}