From e88b59c32c4bdfab4b819d84b40693920f229367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 30 Apr 2013 17:16:38 -0400 Subject: [PATCH] libfreerdp-core: improve async-transport mode --- client/X11/xf_interface.c | 8 +++--- libfreerdp/core/tcp.c | 15 ++++++++++- libfreerdp/core/tcp.h | 4 +++ libfreerdp/core/transport.c | 50 ++++++++++++++++++++++++++---------- libfreerdp/core/transport.h | 1 + winpr/include/winpr/synch.h | 2 ++ winpr/libwinpr/synch/event.c | 25 ++++++++++++++++++ 7 files changed, 87 insertions(+), 18 deletions(-) diff --git a/client/X11/xf_interface.c b/client/X11/xf_interface.c index 775f428a1..ce4c26d01 100644 --- a/client/X11/xf_interface.c +++ b/client/X11/xf_interface.c @@ -106,9 +106,9 @@ void xf_sw_end_paint(rdpContext* context) xfi = ((xfContext*) context)->xfi; gdi = context->gdi; - if (xfi->remote_app != TRUE) + if (!xfi->remote_app) { - if (xfi->complex_regions != TRUE) + if (!xfi->complex_regions) { if (gdi->primary->hdc->hwnd->invalid->null) return; @@ -183,7 +183,7 @@ void xf_sw_desktop_resize(rdpContext* context) xf_lock_x11(xfi, TRUE); - if (xfi->fullscreen != TRUE) + if (!xfi->fullscreen) { rdpGdi* gdi = context->gdi; gdi_resize(gdi, xfi->width, xfi->height); @@ -293,7 +293,7 @@ void xf_hw_desktop_resize(rdpContext* context) xf_lock_x11(xfi, TRUE); - if (xfi->fullscreen != TRUE) + if (!xfi->fullscreen) { xfi->width = settings->DesktopWidth; xfi->height = settings->DesktopHeight; diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index cb63b4241..a9331106a 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -134,6 +134,8 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, UINT16 port) if (tcp->sockfd < 0) return FALSE; + SetEventFileDescriptor(tcp->event, tcp->sockfd); + tcp_get_ip_address(tcp); tcp_get_mac_address(tcp); @@ -248,6 +250,15 @@ BOOL tcp_set_keep_alive_mode(rdpTcp* tcp) return TRUE; } +HANDLE tcp_get_event_handle(rdpTcp* tcp) +{ +#ifndef _WIN32 + return tcp->event; +#else + return (HANDLE) tcp->wsa_event; +#endif +} + rdpTcp* tcp_new(rdpSettings* settings) { rdpTcp* tcp; @@ -260,6 +271,7 @@ rdpTcp* tcp_new(rdpSettings* settings) tcp->sockfd = -1; tcp->settings = settings; + tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd); } return tcp; @@ -267,8 +279,9 @@ rdpTcp* tcp_new(rdpSettings* settings) void tcp_free(rdpTcp* tcp) { - if (tcp != NULL) + if (tcp) { + CloseHandle(tcp->event); free(tcp); } } diff --git a/libfreerdp/core/tcp.h b/libfreerdp/core/tcp.h index baede4524..539d77673 100644 --- a/libfreerdp/core/tcp.h +++ b/libfreerdp/core/tcp.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include #ifndef MSG_NOSIGNAL @@ -43,6 +45,7 @@ struct rdp_tcp #ifdef _WIN32 WSAEVENT wsa_event; #endif + HANDLE event; }; BOOL tcp_connect(rdpTcp* tcp, const char* hostname, UINT16 port); @@ -53,6 +56,7 @@ int tcp_wait_read(rdpTcp* tcp); int tcp_wait_write(rdpTcp* tcp); BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking); BOOL tcp_set_keep_alive_mode(rdpTcp* tcp); +HANDLE tcp_get_event_handle(rdpTcp* tcp); rdpTcp* tcp_new(rdpSettings* settings); void tcp_free(rdpTcp* tcp); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index a2a2b7e8f..51f5d9108 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -568,6 +568,7 @@ int transport_write(rdpTransport* transport, wStream* s) return status; } + void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount) { void* pfd; @@ -612,6 +613,30 @@ void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount) } } +void transport_get_read_handles(rdpTransport* transport, HANDLE* events, DWORD* count) +{ + events[*count] = tcp_get_event_handle(transport->TcpIn); + (*count)++; + + if (transport->SplitInputOutput) + { + events[*count] = tcp_get_event_handle(transport->TcpOut); + (*count)++; + } + + if (transport->ReceiveEvent) + { + events[*count] = transport->ReceiveEvent; + (*count)++; + } + + if (transport->GatewayEvent) + { + events[*count] = transport->GatewayEvent; + (*count)++; + } +} + int transport_check_fds(rdpTransport** ptransport) { int pos; @@ -763,22 +788,26 @@ static void* transport_client_thread(void* arg) { DWORD status; DWORD nCount; - HANDLE events[3]; - HANDLE ReadEvent; + HANDLE events[32]; freerdp* instance; rdpTransport* transport; transport = (rdpTransport*) arg; instance = (freerdp*) transport->settings->instance; - ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, transport->TcpIn->sockfd); + /** + * Ugly temporary hack to start thread after connection + */ - nCount = 0; - events[nCount++] = transport->stopEvent; - events[nCount++] = ReadEvent; + Sleep(2000); while (1) { + nCount = 0; + events[nCount++] = transport->stopEvent; + + transport_get_read_handles(transport, (HANDLE*) &events, &nCount); + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) @@ -786,15 +815,10 @@ static void* transport_client_thread(void* arg) break; } - if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0) - { - if (!freerdp_check_fds(instance)) - break; - } + if (!freerdp_check_fds(instance)) + break; } - CloseHandle(ReadEvent); - return NULL; } diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index 67a2e2783..831291c1b 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -92,6 +92,7 @@ int transport_write(rdpTransport* transport, wStream* s); void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount); int transport_check_fds(rdpTransport** ptransport); BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking); +void transport_get_read_handles(rdpTransport* transport, HANDLE* events, DWORD* count); wStream* transport_receive_pool_take(rdpTransport* transport); int transport_receive_pool_return(rdpTransport* transport, wStream* pdu); diff --git a/winpr/include/winpr/synch.h b/winpr/include/winpr/synch.h index dd9bd13b4..c9bb0ad39 100644 --- a/winpr/include/winpr/synch.h +++ b/winpr/include/winpr/synch.h @@ -273,6 +273,8 @@ WINPR_API HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, #endif WINPR_API int GetEventFileDescriptor(HANDLE hEvent); +WINPR_API int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor); + WINPR_API void* GetEventWaitObject(HANDLE hEvent); #ifdef __cplusplus diff --git a/winpr/libwinpr/synch/event.c b/winpr/libwinpr/synch/event.c index 7298cb56c..8eb8a4aec 100644 --- a/winpr/libwinpr/synch/event.c +++ b/winpr/libwinpr/synch/event.c @@ -273,6 +273,31 @@ int GetEventFileDescriptor(HANDLE hEvent) #endif } +/* + * Set inner file descriptor for usage with select() + * This file descriptor is not usable on Windows + */ + +int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor) +{ +#ifndef _WIN32 + ULONG Type; + PVOID Object; + WINPR_EVENT* event; + + if (!winpr_Handle_GetInfo(hEvent, &Type, &Object)) + return -1; + + event = (WINPR_EVENT*) Object; + + event->pipe_fd[0] = FileDescriptor; + + return 0; +#else + return -1; +#endif +} + /** * Returns platform-specific wait object as a void pointer *