libfreerdp-core: add connection timeout, fix gateway bypass local

This commit is contained in:
Marc-André Moreau 2014-05-30 14:03:20 -04:00
parent e60a59134f
commit 709df9aecc
6 changed files with 60 additions and 16 deletions

View File

@ -1382,6 +1382,7 @@ FREERDP_API void freerdp_performance_flags_make(rdpSettings* settings);
FREERDP_API void freerdp_performance_flags_split(rdpSettings* settings); FREERDP_API void freerdp_performance_flags_split(rdpSettings* settings);
FREERDP_API void freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod); FREERDP_API void freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod);
FREERDP_API void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled, UINT32 GatewayBypassLocal);
FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id); FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id);
FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param); FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param);

View File

@ -220,18 +220,18 @@ BOOL nego_tcp_connect(rdpNego* nego)
{ {
/* Attempt a direct connection first, and then fallback to using the gateway */ /* Attempt a direct connection first, and then fallback to using the gateway */
transport_set_gateway_enabled(nego->transport, FALSE); transport_set_gateway_enabled(nego->transport, FALSE);
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port); nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 1);
} }
if (!nego->tcp_connected) if (!nego->tcp_connected)
{ {
transport_set_gateway_enabled(nego->transport, TRUE); transport_set_gateway_enabled(nego->transport, TRUE);
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port); nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
} }
} }
else else
{ {
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port); nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
} }
} }

View File

@ -284,8 +284,9 @@ void tcp_get_mac_address(rdpTcp* tcp)
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); */ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); */
} }
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port) BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout)
{ {
int status;
UINT32 option_value; UINT32 option_value;
socklen_t option_len; socklen_t option_len;
@ -295,26 +296,55 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
if (hostname[0] == '/') if (hostname[0] == '/')
{ {
tcp->sockfd = freerdp_uds_connect(hostname); tcp->sockfd = freerdp_uds_connect(hostname);
if (tcp->sockfd < 0) if (tcp->sockfd < 0)
return FALSE; return FALSE;
tcp->socketBio = BIO_new_fd(tcp->sockfd, 1); tcp->socketBio = BIO_new_fd(tcp->sockfd, 1);
if (!tcp->socketBio) if (!tcp->socketBio)
return FALSE; return FALSE;
} }
else else
{ {
fd_set cfds;
struct timeval tv;
tcp->socketBio = BIO_new(BIO_s_connect()); tcp->socketBio = BIO_new(BIO_s_connect());
if (!tcp->socketBio) if (!tcp->socketBio)
return FALSE; return FALSE;
if (BIO_set_conn_hostname(tcp->socketBio, hostname) < 0 || BIO_set_conn_int_port(tcp->socketBio, &port) < 0) if (BIO_set_conn_hostname(tcp->socketBio, hostname) < 0 || BIO_set_conn_int_port(tcp->socketBio, &port) < 0)
return FALSE; return FALSE;
if (BIO_do_connect(tcp->socketBio) <= 0) BIO_set_nbio(tcp->socketBio, 1);
status = BIO_do_connect(tcp->socketBio);
if ((status <= 0) && !BIO_should_retry(tcp->socketBio))
return FALSE; return FALSE;
tcp->sockfd = BIO_get_fd(tcp->socketBio, NULL); tcp->sockfd = BIO_get_fd(tcp->socketBio, NULL);
if (tcp->sockfd < 0)
return FALSE;
if (status <= 0)
{
FD_ZERO(&cfds);
FD_SET(tcp->sockfd, &cfds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
status = select(tcp->sockfd + 1, NULL, &cfds, NULL, &tv);
if (status == 0)
{
return FALSE; /* timeout */
}
}
} }
SetEventFileDescriptor(tcp->event, tcp->sockfd); SetEventFileDescriptor(tcp->event, tcp->sockfd);
@ -324,6 +354,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
option_value = 1; option_value = 1;
option_len = sizeof(option_value); option_len = sizeof(option_value);
if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len) < 0) if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len) < 0)
fprintf(stderr, "%s: unable to set TCP_NODELAY\n", __FUNCTION__); fprintf(stderr, "%s: unable to set TCP_NODELAY\n", __FUNCTION__);
@ -334,6 +365,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
{ {
option_value = 1024 * 32; option_value = 1024 * 32;
option_len = sizeof(option_value); option_len = sizeof(option_value);
if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len) < 0) if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len) < 0)
{ {
fprintf(stderr, "%s: unable to set receive buffer len\n", __FUNCTION__); fprintf(stderr, "%s: unable to set receive buffer len\n", __FUNCTION__);
@ -346,15 +378,17 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
return FALSE; return FALSE;
tcp->bufferedBio = BIO_new(BIO_s_buffered_socket()); tcp->bufferedBio = BIO_new(BIO_s_buffered_socket());
if (!tcp->bufferedBio) if (!tcp->bufferedBio)
return FALSE; return FALSE;
tcp->bufferedBio->ptr = tcp; tcp->bufferedBio->ptr = tcp;
tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio); tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
return TRUE; return TRUE;
} }
BOOL tcp_disconnect(rdpTcp* tcp) BOOL tcp_disconnect(rdpTcp* tcp)
{ {
freerdp_tcp_disconnect(tcp->sockfd); freerdp_tcp_disconnect(tcp->sockfd);
@ -503,7 +537,8 @@ rdpTcp* tcp_new(rdpSettings* settings)
{ {
rdpTcp* tcp; rdpTcp* tcp;
tcp = (rdpTcp *)calloc(1, sizeof(rdpTcp)); tcp = (rdpTcp*) calloc(1, sizeof(rdpTcp));
if (!tcp) if (!tcp)
return NULL; return NULL;
@ -515,6 +550,7 @@ rdpTcp* tcp_new(rdpSettings* settings)
#ifndef _WIN32 #ifndef _WIN32
tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd); tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd);
if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE) if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE)
goto out_ringbuffer; goto out_ringbuffer;
#endif #endif

View File

@ -60,7 +60,7 @@ struct rdp_tcp
HANDLE event; HANDLE event;
}; };
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port); BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout);
BOOL tcp_disconnect(rdpTcp* tcp); BOOL tcp_disconnect(rdpTcp* tcp);
int tcp_read(rdpTcp* tcp, BYTE* data, int length); int tcp_read(rdpTcp* tcp, BYTE* data, int length);
int tcp_write(rdpTcp* tcp, BYTE* data, int length); int tcp_write(rdpTcp* tcp, BYTE* data, int length);

View File

@ -373,6 +373,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
context = instance->context; context = instance->context;
tsg = tsg_new(transport); tsg = tsg_new(transport);
if (!tsg) if (!tsg)
return FALSE; return FALSE;
@ -383,12 +384,15 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
if (!transport->TlsIn) if (!transport->TlsIn)
{ {
transport->TlsIn = tls_new(settings); transport->TlsIn = tls_new(settings);
if (!transport->TlsIn) if (!transport->TlsIn)
return FALSE; return FALSE;
} }
if (!transport->TlsOut) if (!transport->TlsOut)
{ {
transport->TlsOut = tls_new(settings); transport->TlsOut = tls_new(settings);
if (!transport->TlsOut) if (!transport->TlsOut)
return FALSE; return FALSE;
} }
@ -400,8 +404,8 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname; transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname;
transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort; transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort;
tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio); tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio);
if (tls_status < 1) if (tls_status < 1)
{ {
if (tls_status < 0) if (tls_status < 0)
@ -419,6 +423,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
} }
tls_status = tls_connect(transport->TlsOut, transport->TcpOut->bufferedBio); tls_status = tls_connect(transport->TlsOut, transport->TcpOut->bufferedBio);
if (tls_status < 1) if (tls_status < 1)
{ {
if (tls_status < 0) if (tls_status < 0)
@ -440,10 +445,11 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
transport->frontBio = BIO_new(BIO_s_tsg()); transport->frontBio = BIO_new(BIO_s_tsg());
transport->frontBio->ptr = tsg; transport->frontBio->ptr = tsg;
return TRUE; return TRUE;
} }
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port) BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout)
{ {
BOOL status = FALSE; BOOL status = FALSE;
rdpSettings* settings = transport->settings; rdpSettings* settings = transport->settings;
@ -456,21 +462,22 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
transport->SplitInputOutput = TRUE; transport->SplitInputOutput = TRUE;
transport->TcpOut = tcp_new(settings); transport->TcpOut = tcp_new(settings);
if (!tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort) || if (!tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!tcp_set_blocking_mode(transport->TcpIn, FALSE)) !tcp_set_blocking_mode(transport->TcpIn, FALSE))
return FALSE; return FALSE;
if (!tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort) || if (!tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!tcp_set_blocking_mode(transport->TcpOut, FALSE)) !tcp_set_blocking_mode(transport->TcpOut, FALSE))
return FALSE; return FALSE;
if (!transport_tsg_connect(transport, hostname, port)) if (!transport_tsg_connect(transport, hostname, port))
return FALSE; return FALSE;
status = TRUE; status = TRUE;
} }
else else
{ {
status = tcp_connect(transport->TcpIn, hostname, port); status = tcp_connect(transport->TcpIn, hostname, port, timeout);
transport->SplitInputOutput = FALSE; transport->SplitInputOutput = FALSE;
transport->TcpOut = transport->TcpIn; transport->TcpOut = transport->TcpIn;
@ -635,6 +642,7 @@ static int transport_wait_for_read(rdpTransport* transport)
rdpTcp *tcpIn; rdpTcp *tcpIn;
tcpIn = transport->TcpIn; tcpIn = transport->TcpIn;
if (tcpIn->readBlocked) if (tcpIn->readBlocked)
{ {
rsetPtr = &rset; rsetPtr = &rset;
@ -660,7 +668,6 @@ static int transport_wait_for_read(rdpTransport* transport)
return select(tcpIn->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv); return select(tcpIn->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
} }
static int transport_wait_for_write(rdpTransport* transport) static int transport_wait_for_write(rdpTransport* transport)
{ {
struct timeval tv; struct timeval tv;

View File

@ -86,7 +86,7 @@ struct rdp_transport
}; };
wStream* transport_send_stream_init(rdpTransport* transport, int size); wStream* transport_send_stream_init(rdpTransport* transport, int size);
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port); BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout);
void transport_attach(rdpTransport* transport, int sockfd); void transport_attach(rdpTransport* transport, int sockfd);
BOOL transport_disconnect(rdpTransport* transport); BOOL transport_disconnect(rdpTransport* transport);
BOOL transport_connect_rdp(rdpTransport* transport); BOOL transport_connect_rdp(rdpTransport* transport);