Merge pull request #2765 from akallabeth/connect_abort

Connect abort and unified TCP connect
This commit is contained in:
MartinHaimberger 2015-09-07 10:05:24 +02:00
commit d971116457
18 changed files with 459 additions and 306 deletions

View File

@ -134,7 +134,8 @@ struct rdp_context
ALIGN64 rdpMetrics* metrics; /* 41 */
ALIGN64 rdpCodecs* codecs; /* 42 */
ALIGN64 rdpAutoDetect* autodetect; /* 43 */
UINT64 paddingC[64 - 44]; /* 44 */
ALIGN64 HANDLE abortEvent; /* 44 */
UINT64 paddingC[64 - 45]; /* 45 */
UINT64 paddingD[96 - 64]; /* 64 */
UINT64 paddingE[128 - 96]; /* 96 */
@ -248,6 +249,7 @@ FREERDP_API BOOL freerdp_context_new(freerdp* instance);
FREERDP_API void freerdp_context_free(freerdp* instance);
FREERDP_API BOOL freerdp_connect(freerdp* instance);
FREERDP_API BOOL freerdp_abort_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);

View File

@ -318,7 +318,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
if (rdp_check_fds(rdp) < 0)
return FALSE;
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
break;
}

View File

@ -3540,7 +3540,7 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
if (!rdp_read_header(rdp, s, &length, pChannelId))
return FALSE;
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
return TRUE;
if (rdp->settings->UseRdpSecurityLayer)
@ -3585,7 +3585,7 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
if (!rdp_recv_get_active_header(rdp, s, &channelId))
return FALSE;
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
return TRUE;
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource))

View File

@ -313,6 +313,8 @@ BOOL rdp_client_disconnect(rdpRdp* rdp)
{
BOOL status;
ResetEvent(rdp->context->abortEvent);
if (rdp->settingsCopy)
{
freerdp_settings_free(rdp->settingsCopy);
@ -832,7 +834,7 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
return rdp_recv_out_of_sequence_pdu(rdp, s);
}
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
return 0;
if (!rdp_send_confirm_active(rdp))

View File

@ -74,6 +74,7 @@ BOOL freerdp_connect(freerdp* instance)
rdp = instance->context->rdp;
settings = instance->settings;
instance->context->codecs = codecs_new(instance->context);
IFCALLRET(instance->PreConnect, status, instance);
@ -102,6 +103,9 @@ BOOL freerdp_connect(freerdp* instance)
goto freerdp_connect_finally;
}
if (!status)
goto freerdp_connect_finally;
if (status)
{
if (instance->settings->DumpRemoteFx)
@ -182,6 +186,14 @@ freerdp_connect_finally:
return status;
}
BOOL freerdp_abort_connect(freerdp* instance)
{
if (!instance || !instance->context)
return FALSE;
return SetEvent(instance->context->abortEvent);
}
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
{
rdpRdp* rdp = instance->context->rdp;
@ -376,7 +388,11 @@ BOOL freerdp_reconnect(freerdp* instance)
BOOL freerdp_shall_disconnect(freerdp* instance)
{
return instance->context->rdp->disconnect;
if (!instance || !instance->context)
return FALSE;
if (WaitForSingleObject(instance->context->abortEvent, 0) != WAIT_OBJECT_0)
return FALSE;
return TRUE;
}
FREERDP_API BOOL freerdp_focus_required(freerdp* instance)
@ -527,14 +543,22 @@ BOOL freerdp_context_new(freerdp* instance)
update_register_client_callbacks(rdp->update);
instance->context->abortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!instance->context->abortEvent)
goto out_error_abort_event;
IFCALLRET(instance->ContextNew, ret, instance, instance->context);
if (ret)
return TRUE;
out_error_create_event:
CloseHandle(context->abortEvent);
out_error_abort_event:
CloseHandle(context->channelErrorEvent);
out_error_description:
out_error_create_event:
free(context->errorDescription);
out_error_description:
graphics_free(context->graphics);
out_error_graphics_new:
rdp_free(rdp);
out_error_rdp_new:
@ -577,6 +601,9 @@ void freerdp_context_free(freerdp* instance)
CloseHandle(instance->context->channelErrorEvent);
free(instance->context->errorDescription);
CloseHandle(instance->context->abortEvent);
instance->context->abortEvent = NULL;
free(instance->context);
instance->context = NULL;

View File

@ -899,7 +899,8 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim
assert(hostname != NULL);
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
sockfd = freerdp_tcp_connect(rdg->context, settings, settings->GatewayHostname,
settings->GatewayPort, timeout);
if (sockfd < 1)
{
@ -955,7 +956,8 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time
assert(hostname != NULL);
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
sockfd = freerdp_tcp_connect(rdg->context, settings, settings->GatewayHostname,
settings->GatewayPort, timeout);
if (sockfd < 1)
return FALSE;

View File

@ -760,7 +760,8 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
rdpContext* context = rpc->context;
rdpSettings* settings = context->settings;
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
sockfd = freerdp_tcp_connect(context, settings, settings->GatewayHostname,
settings->GatewayPort, timeout);
if (sockfd < 1)
return -1;

View File

@ -340,7 +340,7 @@ int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
rpc->result = *((UINT32*) &buffer[StubOffset]);
rpc->context->rdp->disconnect = TRUE;
freerdp_abort_connect(rpc->context->instance);
rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;
EventArgsInit(&e, "freerdp");
e.code = 0;

View File

@ -171,8 +171,13 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
/* FIXME: these file descriptors do not work on Windows */
listener->sockfds[listener->num_sockfds] = sockfd;
listener->events[listener->num_sockfds] =
CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ);
listener->events[listener->num_sockfds] = WSACreateEvent();
if (!listener->events[listener->num_sockfds])
{
listener->num_sockfds = 0;
break;
}
WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
listener->num_sockfds++;
WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
@ -336,7 +341,7 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
void* sin_addr;
int peer_sockfd;
freerdp_peer* client = NULL;
socklen_t peer_addr_size;
int peer_addr_size;
struct sockaddr_storage peer_addr;
rdpListener* listener = (rdpListener*) instance->listener;
static const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
@ -347,8 +352,10 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
for (i = 0; i < listener->num_sockfds; i++)
{
WSAResetEvent(listener->events[i]);
peer_addr_size = sizeof(peer_addr);
peer_sockfd = accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);
peer_sockfd = _accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);
peer_accepted = FALSE;
if (peer_sockfd == -1)

View File

@ -356,7 +356,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
return -1;
}
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
return 0;
if (rdp->settings->UseRdpSecurityLayer)

View File

@ -307,7 +307,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
{
if (code == X224_TPDU_DISCONNECT_REQUEST)
{
rdp->disconnect = TRUE;
freerdp_abort_connect(rdp->instance);
return TRUE;
}
@ -341,7 +341,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
if (!rdp->instance)
{
rdp->disconnect = TRUE;
freerdp_abort_connect(rdp->instance);
return FALSE;
}
@ -364,7 +364,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
}
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
rdp->disconnect = TRUE;
freerdp_abort_connect(rdp->instance);
EventArgsInit(&e, "freerdp");
e.code = 0;
@ -1117,7 +1117,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
return -1;
}
if (rdp->disconnect)
if (freerdp_shall_disconnect(rdp->instance))
return 0;
if (rdp->autodetect->bandwidthMeasureStarted)
@ -1647,7 +1647,6 @@ void rdp_reset(rdpRdp* rdp)
rdp->nego = nego_new(rdp->transport);
rdp->mcs = mcs_new(rdp->transport);
rdp->transport->layer = TRANSPORT_LAYER_TCP;
rdp->disconnect = FALSE;
rdp->errorInfo = 0;
rdp->deactivation_reactivation = 0;
rdp->finalize_sc_pdus = 0;

View File

@ -171,7 +171,6 @@ struct rdp_rdp
BYTE fips_decrypt_key[24];
UINT32 errorInfo;
UINT32 finalize_sc_pdus;
BOOL disconnect;
BOOL resendFocus;
BOOL deactivation_reactivation;
BOOL AwaitCapabilities;

View File

@ -145,6 +145,8 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
BIO_clear_flags(bio, BIO_FLAGS_READ);
WSAResetEvent(ptr->hEvent);
status = _recv(ptr->socket, buf, size, 0);
if (status > 0)
@ -359,20 +361,17 @@ static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->init = 1;
#ifdef _WIN32
ptr->hEvent = WSACreateEvent();
ptr->hEvent = WSACreateEvent();
if (!ptr->hEvent)
return 0;
if (!ptr->hEvent)
return 0;
/* WSAEventSelect automatically sets the socket in non-blocking mode */
WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_WRITE | FD_CLOSE);
#else
ptr->hEvent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket, WINPR_FD_READ);
if (!ptr->hEvent)
return 0;
#endif
/* WSAEventSelect automatically sets the socket in non-blocking mode */
if (WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
{
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
return 0;
}
return 1;
}
@ -693,7 +692,7 @@ char* freerdp_tcp_get_ip_address(int sockfd)
return _strdup(ipAddress);
}
int freerdp_uds_connect(const char* path)
static int freerdp_uds_connect(const char* path)
{
#ifndef _WIN32
int status;
@ -744,265 +743,82 @@ BOOL freerdp_tcp_resolve_hostname(const char* hostname)
return TRUE;
}
BOOL freerdp_tcp_connect_timeout(int sockfd, struct sockaddr* addr, socklen_t addrlen, int timeout)
static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd,
struct sockaddr* addr,
socklen_t addrlen, int timeout)
{
int status;
HANDLE handles[2];
int status = 0;
int count = 0;
u_long arg = 0;
DWORD tout = (timeout) ? timeout * 1000 : INFINITE;
#ifndef _WIN32
int flags;
fd_set cfds;
socklen_t optlen;
struct timeval tv;
/* set socket in non-blocking mode */
flags = fcntl(sockfd, F_GETFL);
if (flags < 0)
handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!handles[count])
return FALSE;
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
/* non-blocking tcp connect */
status = connect(sockfd, addr, addrlen);
if (status >= 0)
return TRUE; /* connection success */
if (errno != EINPROGRESS)
status = WSAEventSelect(sockfd, handles[count++], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
if (status < 0)
{
WLog_ERR(TAG, "WSAEventSelect failed with %lX", WSAGetLastError());
return FALSE;
}
FD_ZERO(&cfds);
FD_SET(sockfd, &cfds);
handles[count++] = context->abortEvent;
tv.tv_sec = timeout;
tv.tv_usec = 0;
status = _connect(sockfd, addr, addrlen);
if (status < 0)
{
status = WSAGetLastError();
switch(status)
{
case WSAEINPROGRESS:
case WSAEWOULDBLOCK:
break;
default:
return FALSE;
}
}
status = _select(sockfd + 1, NULL, &cfds, NULL, &tv);
status = WaitForMultipleObjects(count, handles, FALSE, tout);
if (WAIT_OBJECT_0 != status)
{
if (status == WAIT_OBJECT_0 + 1)
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
if (status != 1)
return FALSE; /* connection timeout or error */
status = 0;
optlen = sizeof(status);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*) &status, &optlen) < 0)
return FALSE;
}
if (status != 0)
status = recv(sockfd, NULL, 0, 0);
if (status == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAECONNRESET)
return FALSE;
}
status = WSAEventSelect(sockfd, handles[0], 0);
CloseHandle(handles[0]);
if (status < 0)
{
WLog_ERR(TAG, "WSAEventSelect failed with %lX", WSAGetLastError());
return FALSE;
}
/* set socket in blocking mode */
flags = fcntl(sockfd, F_GETFL);
if (flags < 0)
if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0)
return FALSE;
fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
#else
status = connect(sockfd, addr, addrlen);
if (status >= 0)
return TRUE;
return FALSE;
#endif
return TRUE;
}
#ifndef _WIN32
int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int port, int timeout)
static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames,
UINT32* ports, int count, int port,
int timeout)
{
int index;
int sindex;
int status;
int flags;
int maxfds;
fd_set cfds;
int sockfd = -1;
int* sockfds;
char port_str[16];
socklen_t optlen;
struct timeval tv;
struct addrinfo hints;
struct addrinfo* addr;
struct addrinfo* result;
struct addrinfo** addrs;
struct addrinfo** results;
sindex = -1;
sprintf_s(port_str, sizeof(port_str) - 1, "%u", port);
sockfds = (int*) calloc(count, sizeof(int));
addrs = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
results = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
for (index = 0; index < count; index++)
{
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (ports)
sprintf_s(port_str, sizeof(port_str) - 1, "%u", ports[index]);
status = getaddrinfo(hostnames[index], port_str, &hints, &result);
if (status)
{
continue;
}
addr = result;
if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
{
while ((addr = addr->ai_next))
{
if (addr->ai_family == AF_INET)
break;
}
if (!addr)
addr = result;
}
sockfds[index] = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sockfds[index] < 0)
{
freeaddrinfo(result);
sockfds[index] = 0;
continue;
}
addrs[index] = addr;
results[index] = result;
}
maxfds = 0;
FD_ZERO(&cfds);
for (index = 0; index < count; index++)
{
if (!sockfds[index])
continue;
sockfd = sockfds[index];
addr = addrs[index];
/* set socket in non-blocking mode */
flags = fcntl(sockfd, F_GETFL);
if (flags < 0)
{
sockfds[index] = 0;
continue;
}
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
/* non-blocking tcp connect */
status = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
if (status >= 0)
{
/* connection success */
break;
}
if (errno != EINPROGRESS)
{
sockfds[index] = 0;
continue;
}
FD_SET(sockfd, &cfds);
if (sockfd > maxfds)
maxfds = sockfd;
}
tv.tv_sec = timeout;
tv.tv_usec = 0;
status = _select(maxfds + 1, NULL, &cfds, NULL, &tv);
for (index = 0; index < count; index++)
{
if (!sockfds[index])
continue;
sockfd = sockfds[index];
if (FD_ISSET(sockfd, &cfds))
{
status = 0;
optlen = sizeof(status);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*) &status, &optlen) < 0)
{
sockfds[index] = 0;
continue;
}
if (status != 0)
{
sockfds[index] = 0;
continue;
}
/* set socket in blocking mode */
flags = fcntl(sockfd, F_GETFL);
if (flags < 0)
{
sockfds[index] = 0;
continue;
}
fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
sindex = index;
break;
}
}
if (sindex >= 0)
{
sockfd = sockfds[sindex];
}
for (index = 0; index < count; index++)
{
if (results[index])
freeaddrinfo(results[index]);
}
free(addrs);
free(results);
free(sockfds);
return sockfd;
}
#else
int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int port, int timeout)
{
int index;
int sindex;
int status;
SOCKET sockfd;
SOCKET sockfd = -1;
SOCKET* sockfds;
HANDLE* events;
DWORD waitStatus;
@ -1013,12 +829,10 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
struct addrinfo** addrs;
struct addrinfo** results;
sindex = -1;
sprintf_s(port_str, sizeof(port_str) - 1, "%u", port);
sockfds = (SOCKET*) calloc(count, sizeof(SOCKET));
events = (HANDLE*) calloc(count, sizeof(HANDLE));
events = (HANDLE*) calloc(count + 1, sizeof(HANDLE));
addrs = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
results = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
@ -1083,8 +897,18 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
addr = addrs[index];
/* set socket in non-blocking mode */
events[index] = WSACreateEvent();
if (!events[index])
{
WLog_ERR(TAG, "WSACreateEvent returned %08X", WSAGetLastError());
continue;
}
WSAEventSelect(sockfd, events[index], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
if (WSAEventSelect(sockfd, events[index], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
{
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
continue;
}
/* non-blocking tcp connect */
@ -1097,31 +921,47 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
}
}
waitStatus = WaitForMultipleObjects(count, events, FALSE, timeout * 1000);
events[count] = context->abortEvent;
waitStatus = WaitForMultipleObjects(count + 1, events, FALSE, timeout * 1000);
sindex = waitStatus - WAIT_OBJECT_0;
for (index = 0; index < count; index++)
{
u_long arg = 0;
if (!sockfds[index])
continue;
sockfd = sockfds[index];
/* set socket in blocking mode */
if (WSAEventSelect(sockfd, NULL, 0))
{
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
continue;
}
WSAEventSelect(sockfd, NULL, 0);
if (_ioctlsocket(sockfd, FIONBIO, &arg))
{
WLog_ERR(TAG, "_ioctlsocket failed");
}
}
if (sindex >= 0)
if ((sindex >= 0) && (sindex < count))
{
sockfd = sockfds[sindex];
}
if (sindex == count)
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
for (index = 0; index < count; index++)
{
if (results[index])
freeaddrinfo(results[index]);
CloseHandle(events[index]);
}
free(addrs);
@ -1132,8 +972,6 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
return sockfd;
}
#endif
BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
{
#ifndef _WIN32
@ -1201,7 +1039,8 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
return TRUE;
}
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout)
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
const char* hostname, int port, int timeout)
{
int status;
int sockfd;
@ -1232,8 +1071,12 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
{
if (settings->TargetNetAddressCount > 0)
{
sockfd = freerdp_tcp_connect_multi(settings->TargetNetAddresses,
settings->TargetNetPorts, settings->TargetNetAddressCount, port, timeout);
sockfd = freerdp_tcp_connect_multi(
context,
settings->TargetNetAddresses,
settings->TargetNetPorts,
settings->TargetNetAddressCount,
port, timeout);
}
}
}
@ -1275,13 +1118,14 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sockfd < 0)
if (sockfd < 0)
{
freeaddrinfo(result);
return -1;
}
if (!freerdp_tcp_connect_timeout(sockfd, addr->ai_addr, addr->ai_addrlen, timeout))
if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr,
addr->ai_addrlen, timeout))
{
freeaddrinfo(result);
close(sockfd);
@ -1340,5 +1184,11 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
}
}
if (WaitForSingleObject(context->abortEvent, 0) == WAIT_OBJECT_0)
{
close(sockfd);
return -1;
}
return sockfd;
}

View File

@ -25,6 +25,7 @@
#include <freerdp/types.h>
#include <freerdp/settings.h>
#include <freerdp/freerdp.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
@ -60,6 +61,7 @@
BIO_METHOD* BIO_s_simple_socket(void);
BIO_METHOD* BIO_s_buffered_socket(void);
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout);
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
const char* hostname, int port, int timeout);
#endif /* __TCP_H */

View File

@ -8,13 +8,24 @@ set(${MODULE_PREFIX}_TESTS
TestVersion.c
TestSettings.c)
if(WITH_SAMPLE AND WITH_SERVER)
set(${MODULE_PREFIX}_TESTS
${${MODULE_PREFIX}_TESTS}
TestConnect.c)
else()
message("Skipping connection tests, requires WITH_SAMPLE and WITH_SERVER set!")
endif()
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
target_link_libraries(${MODULE_NAME} freerdp)
add_definitions(-DTESTING_OUTPUT_DIRECTORY="${CMAKE_BINARY_DIR}")
add_definitions(-DTESTING_SRC_DIRECTORY="${CMAKE_SOURCE_DIR}")
target_link_libraries(${MODULE_NAME} freerdp-client freerdp winpr)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")

View File

@ -0,0 +1,261 @@
#include <winpr/sysinfo.h>
#include <winpr/path.h>
#include <freerdp/freerdp.h>
#include <freerdp/client/cmdline.h>
static HANDLE s_sync = NULL;
static int runInstance(int argc, char* argv[], freerdp** inst)
{
int rc = -1;
freerdp* instance = freerdp_new();
if (!instance)
goto finish;
if (inst)
*inst = instance;
if (!freerdp_context_new(instance))
goto finish;
if (freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE) < 0)
goto finish;
if (freerdp_client_load_addins(instance->context->channels, instance->settings) != 1)
goto finish;
if (s_sync)
{
if (!SetEvent(s_sync))
goto finish;
}
rc = 1;
if (!freerdp_connect(instance))
goto finish;
rc = 2;
if (!freerdp_disconnect(instance))
goto finish;
rc = 0;
finish:
freerdp_context_free(instance);
freerdp_free(instance);
return rc;
}
static int testTimeout(void)
{
DWORD start, end, diff;
char* argv[] =
{
"test",
"/v:192.0.2.1",
NULL
};
int rc;
start = GetTickCount();
rc = runInstance(2, argv, NULL);
end = GetTickCount();
if (rc != 1)
return -1;
diff = end - start;
if (diff > 16000)
return -1;
if (diff < 14000)
return -1;
printf("%s: Success!\n", __FUNCTION__);
return 0;
}
static void* testThread(void* arg)
{
char* argv[] =
{
"test",
"/v:192.0.2.1",
NULL
};
int rc;
rc = runInstance(2, argv, arg);
if (rc != 1)
ExitThread(-1);
ExitThread(0);
return NULL;
}
static int testAbort(void)
{
DWORD status;
DWORD start, end, diff;
HANDLE thread;
freerdp* instance = NULL;
s_sync = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s_sync)
return -1;
start = GetTickCount();
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)testThread,
&instance, 0, NULL);
if (!thread)
{
CloseHandle(s_sync);
s_sync = NULL;
return -1;
}
WaitForSingleObject(s_sync, INFINITE);
freerdp_abort_connect(instance);
status = WaitForSingleObject(instance->context->abortEvent, 0);
if (status != WAIT_OBJECT_0)
{
CloseHandle(s_sync);
CloseHandle(thread);
s_sync = NULL;
return -1;
}
status = WaitForSingleObject(thread, 20000);
end = GetTickCount();
CloseHandle(s_sync);
CloseHandle(thread);
s_sync = NULL;
diff = end - start;
if (diff > 1000)
return -1;
if (WAIT_OBJECT_0 != status)
return -1;
printf("%s: Success!\n", __FUNCTION__);
return 0;
}
static int testSuccess(void)
{
int rc;
STARTUPINFO si;
PROCESS_INFORMATION process;
char* argv[] =
{
"test",
"/v:127.0.0.1",
"/cert-ignore",
"/rfx",
NULL
};
int argc = 4;
char* path = TESTING_OUTPUT_DIRECTORY;
char* wpath = TESTING_SRC_DIRECTORY;
char* exe = GetCombinedPath(path, "server");
char* wexe = GetCombinedPath(wpath, "server");
if (!exe || !wexe)
{
free(exe);
free(wexe);
return -2;
}
path = GetCombinedPath(exe, "Sample");
wpath = GetCombinedPath(wexe, "Sample");
free(exe);
free(wexe);
if (!path || !wpath)
{
free(path);
free(wpath);
return -2;
}
exe = GetCombinedPath(path, "sfreerdp-server");
if (!exe)
{
free(path);
free(wpath);
return -2;
}
printf("Sample Server: %s\n", exe);
printf("Workspace: %s\n", wpath);
if (!PathFileExistsA(exe))
{
free(path);
free(wpath);
free(exe);
return -2;
}
// Start sample server locally.
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcessA(exe, exe, NULL, NULL, FALSE, 0, NULL,
wpath, &si, &process))
{
free(exe);
free(path);
free(wpath);
return -2;
}
free(exe);
free(path);
free(wpath);
Sleep(1000);
rc = runInstance(argc, argv, NULL);
if (!TerminateProcess(process.hProcess, 0))
return -2;
WaitForSingleObject(process.hProcess, INFINITE);
CloseHandle(process.hProcess);
CloseHandle(process.hThread);
printf("%s: returned %d!\n", __FUNCTION__, rc);
if (rc)
return -1;
printf("%s: Success!\n", __FUNCTION__);
return 0;
}
int TestConnect(int argc, char* argv[])
{
/* Test connect to not existing server,
* check if timeout is honored. */
if (testTimeout())
return -1;
/* Test connect to not existing server,
* check if connection abort is working. */
if (testAbort())
return -1;
/* Test connect to existing server,
* check if connection is working. */
if (testSuccess())
return -1;
return 0;
}

View File

@ -204,6 +204,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
int sockfd;
BOOL status = FALSE;
rdpSettings* settings = transport->settings;
rdpContext* context = transport->context;
transport->async = settings->AsyncTransport;
@ -256,7 +257,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
}
else
{
sockfd = freerdp_tcp_connect(settings, hostname, port, timeout);
sockfd = freerdp_tcp_connect(context, settings, hostname, port, timeout);
if (sockfd < 1)
return FALSE;
@ -750,20 +751,7 @@ int transport_check_fds(rdpTransport* transport)
if (!transport)
return -1;
if (BIO_get_event(transport->frontBio, &event) != 1)
return -1;
/**
* Loop through and read all available PDUs. Since multiple
* PDUs can exist, it's important to deliver them all before
* returning. Otherwise we run the risk of having a thread
* wait for a socket to get signaled that data is available
* (which may never happen).
*/
#ifdef _WIN32
ResetEvent(event);
#endif
for (;;)
while(!freerdp_shall_disconnect(transport->context->instance))
{
/**
* Note: transport_read_pdu tries to read one PDU from

View File

@ -630,7 +630,9 @@ BOOL WSASetEvent(HANDLE hEvent)
BOOL WSAResetEvent(HANDLE hEvent)
{
return ResetEvent(hEvent);
/* POSIX systems auto reset the socket,
* if no more data is available. */
return TRUE;
}
BOOL WSACloseEvent(HANDLE hEvent)
@ -647,7 +649,7 @@ BOOL WSACloseEvent(HANDLE hEvent)
int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
{
u_long arg = lNetworkEvents ? 1 : 0;
u_long arg = 1;
ULONG mode = 0;
if (_ioctlsocket(s, FIONBIO, &arg) != 0)