diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 05520d2dd..0752dde52 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -1210,6 +1210,7 @@ int xfreerdp_run(freerdp* instance) BOOL async_update; BOOL async_input; BOOL async_channels; + BOOL async_transport; HANDLE update_thread; HANDLE input_thread; HANDLE channels_thread; @@ -1245,6 +1246,7 @@ int xfreerdp_run(freerdp* instance) async_update = settings->AsyncUpdate; async_input = settings->AsyncInput; async_channels = settings->AsyncChannels; + async_transport = settings->AsyncTransport; if (async_update) { @@ -1266,11 +1268,14 @@ int xfreerdp_run(freerdp* instance) rcount = 0; wcount = 0; - if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + if (!async_transport) { - printf("Failed to get FreeRDP file descriptor\n"); - ret = XF_EXIT_CONN_FAILED; - break; + if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + { + printf("Failed to get FreeRDP file descriptor\n"); + ret = XF_EXIT_CONN_FAILED; + break; + } } if (!async_channels) @@ -1336,10 +1341,13 @@ int xfreerdp_run(freerdp* instance) } } - if (freerdp_check_fds(instance) != TRUE) + if (!async_transport) { - printf("Failed to check FreeRDP file descriptor\n"); - break; + if (freerdp_check_fds(instance) != TRUE) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } } if (!async_channels) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 28ab422aa..2aa4c8a66 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -123,6 +123,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "fast-path input/output" }, { "async-input", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous input" }, { "async-update", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous update" }, + { "async-transport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous transport (unstable)" }, { "async-channels", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous channels (unstable)" }, { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" }, { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" }, @@ -1511,6 +1512,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin { settings->AsyncChannels = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "async-transport") + { + settings->AsyncTransport = arg->Value ? TRUE : FALSE; + } CommandLineSwitchDefault(arg) { diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index e6a2c7a7d..dcc52062b 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -944,8 +944,9 @@ struct rdp_settings ALIGN64 BOOL AsyncInput; /* 1544 */ ALIGN64 BOOL AsyncUpdate; /* 1545 */ ALIGN64 BOOL AsyncChannels; /* 1546 */ - ALIGN64 BOOL ToggleFullscreen; /* 1547 */ - UINT64 padding1600[1600 - 1548]; /* 1548 */ + ALIGN64 BOOL AsyncTransport; /* 1547 */ + ALIGN64 BOOL ToggleFullscreen; /* 1548 */ + UINT64 padding1600[1600 - 1549]; /* 1549 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 2d2a384d3..ae4025a13 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -48,6 +48,8 @@ #define BUFFER_SIZE 16384 +static void* transport_client_thread(void* arg); + wStream* transport_recv_stream_init(rdpTransport* transport, int size) { wStream* s = transport->ReceiveStream; @@ -118,6 +120,7 @@ BOOL transport_connect_tls(rdpTransport* transport) connectErrorCode = TLSCONNECTERROR; tls_free(transport->TlsIn); + if (transport->TlsIn == transport->TlsOut) transport->TlsIn = transport->TlsOut = NULL; else @@ -203,6 +206,16 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por BOOL status = FALSE; rdpSettings* settings = transport->settings; + transport->async = transport->settings->AsyncTransport; + + if (transport->async) + { + transport->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + transport->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL); + } + if (transport->settings->GatewayUsageMethod) { transport->layer = TRANSPORT_LAYER_TSG; @@ -736,6 +749,47 @@ BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking) return status; } +static void* transport_client_thread(void* arg) +{ + DWORD status; + DWORD nCount; + HANDLE events[3]; + HANDLE ReadEvent; + freerdp* instance; + rdpTransport* transport; + + transport = (rdpTransport*) arg; + instance = (freerdp*) transport->settings->instance; + + ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, transport->TcpIn->sockfd); + + nCount = 0; + events[nCount++] = transport->stopEvent; + events[nCount++] = ReadEvent; + + while (1) + { + printf("transport_client_thread\n"); + + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0) + { + if (!freerdp_check_fds(instance)) + break; + } + } + + CloseHandle(ReadEvent); + + return NULL; +} + wStream* transport_receive_buffer_pool_new() { wStream* pdu = NULL; diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index 909a70d45..ee225bfe1 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -36,6 +36,9 @@ typedef struct rdp_transport rdpTransport; #include "gateway/tsg.h" #include +#include +#include +#include #include #include @@ -44,8 +47,6 @@ typedef struct rdp_transport rdpTransport; #include #include -#include - typedef int (*TransportRecv) (rdpTransport* transport, wStream* stream, void* extra); struct rdp_transport @@ -68,6 +69,9 @@ struct rdp_transport BOOL blocking; BOOL SplitInputOutput; wObjectPool* ReceivePool; + HANDLE stopEvent; + HANDLE thread; + BOOL async; }; wStream* transport_recv_stream_init(rdpTransport* transport, int size);