From 695e38398d139fc7d44dd6b03f86b115790bd14e Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 17 Sep 2021 09:27:25 +0200 Subject: [PATCH] Refactored proxy * Removed unnecessary global data lists * Improved error handling * Do not initialize channel code in passthrough mode --- server/proxy/pf_channels.c | 15 +++ server/proxy/pf_client.c | 90 +++++++++------- server/proxy/pf_config.c | 4 +- server/proxy/pf_context.c | 22 ++-- server/proxy/pf_server.c | 207 +++++++++++++++++++++---------------- server/proxy/pf_server.h | 3 +- 6 files changed, 199 insertions(+), 142 deletions(-) diff --git a/server/proxy/pf_channels.c b/server/proxy/pf_channels.c index 145412bff..fc83db73e 100644 --- a/server/proxy/pf_channels.c +++ b/server/proxy/pf_channels.c @@ -81,8 +81,11 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs } else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) { + if (!ps->rail) + return; pc->rail = (RailClientContext*)e->pInterface; + WINPR_ASSERT(ps->rail->Start); if (ps->rail->Start(ps->rail) != CHANNEL_RC_OK) { WLog_ERR(TAG, "failed to start RAIL server"); @@ -94,9 +97,12 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { pf_channels_wait_for_server_dynvc(ps); + if (!ps->gfx) + return; pc->gfx_proxy = (RdpgfxClientContext*)e->pInterface; pf_rdpgfx_pipeline_init(pc->gfx_proxy, ps->gfx, pc->pdata); + WINPR_ASSERT(ps->gfx->Open); if (!ps->gfx->Open(ps->gfx)) { WLog_ERR(TAG, "failed to open GFX server"); @@ -109,6 +115,10 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs { UINT ret; + if (!ps->disp) + return; + + WINPR_ASSERT(ps->disp->Open); ret = ps->disp->Open(ps->disp); if (ret != CHANNEL_RC_OK) { @@ -133,6 +143,10 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs } else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) { + if (!ps->cliprdr) + return; + + WINPR_ASSERT(ps->cliprdr->Start); if (ps->cliprdr->Start(ps->cliprdr) != CHANNEL_RC_OK) { WLog_ERR(TAG, "failed to open cliprdr channel"); @@ -148,6 +162,7 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs if (ps->rdpsnd == NULL) return; + WINPR_ASSERT(ps->rdpsnd->Initialize); if (ps->rdpsnd->Initialize(ps->rdpsnd, TRUE) != CHANNEL_RC_OK) { WLog_ERR(TAG, "failed to open rdpsnd channel"); diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index e2ba40d28..b08680898 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -47,6 +47,7 @@ #define TAG PROXY_TAG("client") +static void channel_data_free(void* obj); static BOOL proxy_server_reactivate(rdpContext* ps, const rdpContext* pc) { WINPR_ASSERT(ps); @@ -231,10 +232,13 @@ static BOOL pf_client_pre_connect(freerdp* instance) * Register the channel listeners. * They are required to set up / tear down channels if they are loaded. */ - PubSub_SubscribeChannelConnected(instance->context->pubSub, - pf_channels_on_client_channel_connect); - PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - pf_channels_on_client_channel_disconnect); + if (!config->PassthroughIsBlacklist || (config->PassthroughCount != 0)) + { + PubSub_SubscribeChannelConnected(instance->context->pubSub, + pf_channels_on_client_channel_connect); + PubSub_SubscribeChannelDisconnected(instance->context->pubSub, + pf_channels_on_client_channel_disconnect); + } PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); PubSub_SubscribeActivated(instance->context->pubSub, pf_client_on_activated); /** @@ -416,35 +420,42 @@ static BOOL pf_client_send_channel_data(pClientContext* pc, const proxyChannelDa WINPR_ASSERT(pc); WINPR_ASSERT(ev); - if (!pc->connected) - { - ArrayList_Append(pc->cached_server_channel_data, ev); - return TRUE; - } - else - { - UINT16 channelId; - WINPR_ASSERT(pc->context.instance); - - channelId = freerdp_channels_get_id_by_name(pc->context.instance, ev->channel_name); - /* Ignore unmappable channels */ - if ((channelId == 0) || (channelId == UINT16_MAX)) - return TRUE; - WINPR_ASSERT(pc->context.instance->SendChannelPacket); - return pc->context.instance->SendChannelPacket( - pc->context.instance, channelId, ev->total_size, ev->flags, ev->data, ev->data_len); - } + return Queue_Enqueue(pc->cached_server_channel_data, ev); } - -static BOOL send_channel_data(void* data, size_t index, va_list ap) +static BOOL sendQueuedChannelData(pClientContext* pc) { - pClientContext* pc = va_arg(ap, pClientContext*); - proxyChannelDataEventInfo* ev = data; - WINPR_ASSERT(ev); - WINPR_ASSERT(pc); - WINPR_UNUSED(index); + BOOL rc = TRUE; - return pf_client_send_channel_data(pc, ev); + WINPR_ASSERT(pc); + + if (pc->connected) + { + proxyChannelDataEventInfo* ev; + + Queue_Lock(pc->cached_server_channel_data); + while (rc && (ev = Queue_Dequeue(pc->cached_server_channel_data))) + { + UINT16 channelId; + WINPR_ASSERT(pc->context.instance); + + channelId = freerdp_channels_get_id_by_name(pc->context.instance, ev->channel_name); + /* Ignore unmappable channels */ + if ((channelId == 0) || (channelId == UINT16_MAX)) + rc = TRUE; + else + { + WINPR_ASSERT(pc->context.instance->SendChannelPacket); + rc = pc->context.instance->SendChannelPacket(pc->context.instance, channelId, + ev->total_size, ev->flags, ev->data, + ev->data_len); + } + channel_data_free(ev); + } + + Queue_Unlock(pc->cached_server_channel_data); + } + + return rc; } /** @@ -516,10 +527,7 @@ static BOOL pf_client_post_connect(freerdp* instance) pc->connected = TRUE; /* Send cached channel data */ - ArrayList_Lock(pc->cached_server_channel_data); - ArrayList_ForEach(pc->cached_server_channel_data, send_channel_data, pc); - ArrayList_Clear(pc->cached_server_channel_data); - ArrayList_Unlock(pc->cached_server_channel_data); + sendQueuedChannelData(pc); /* * after the connection fully established and settings were negotiated with target server, @@ -630,7 +638,7 @@ static BOOL pf_client_connect_without_nla(pClientContext* pc) /* do not allow next connection failure */ pc->allow_next_conn_failure = FALSE; - return freerdp_connect(instance); + return freerdp_reconnect(instance); } static BOOL pf_client_connect(freerdp* instance) @@ -717,13 +725,14 @@ static DWORD WINAPI pf_client_thread_proc(pClientContext* pc) proxy_data_abort_connect(pdata); return FALSE; } + handles[nCount++] = Queue_Event(pc->cached_server_channel_data); while (!freerdp_shall_disconnect(instance)) { UINT32 tmp = freerdp_get_event_handles(instance->context, &handles[nCount], ARRAYSIZE(handles) - nCount); - if (tmp == 0) + if ((tmp == 0) || (nCount + tmp > ARRAYSIZE(handles))) { PROXY_LOG_ERR(TAG, pc, "freerdp_get_event_handles failed!"); break; @@ -755,6 +764,7 @@ static DWORD WINAPI pf_client_thread_proc(pClientContext* pc) break; } + sendQueuedChannelData(pc); } freerdp_disconnect(instance); @@ -785,7 +795,7 @@ static void pf_client_context_free(freerdp* instance, rdpContext* context) return; pc->sendChannelData = NULL; - ArrayList_Free(pc->cached_server_channel_data); + Queue_Free(pc->cached_server_channel_data); Stream_Free(pc->remote_pem, TRUE); free(pc->remote_hostname); } @@ -824,7 +834,7 @@ static int pf_client_verify_X509_certificate(freerdp* instance, const BYTE* data return 1; } -static void channel_data_free(void* obj) +void channel_data_free(void* obj) { proxyChannelDataEventInfo* dst = obj; if (dst) @@ -883,10 +893,10 @@ static BOOL pf_client_client_new(freerdp* instance, rdpContext* context) return FALSE; pc->sendChannelData = pf_client_send_channel_data; - pc->cached_server_channel_data = ArrayList_New(TRUE); + pc->cached_server_channel_data = Queue_New(TRUE, -1, -1); if (!pc->cached_server_channel_data) return FALSE; - obj = ArrayList_Object(pc->cached_server_channel_data); + obj = Queue_Object(pc->cached_server_channel_data); WINPR_ASSERT(obj); obj->fnObjectNew = channel_data_copy; obj->fnObjectFree = channel_data_free; diff --git a/server/proxy/pf_config.c b/server/proxy/pf_config.c index 2b5bba6df..1a3675800 100644 --- a/server/proxy/pf_config.c +++ b/server/proxy/pf_config.c @@ -266,8 +266,8 @@ static BOOL pf_config_load_modules(wIniFile* ini, proxyConfig* config) const char* modules_to_load; const char* required_modules; - modules_to_load = IniFile_GetKeyValueString(ini, "Plugins", "Modules"); - required_modules = IniFile_GetKeyValueString(ini, "Plugins", "Required"); + modules_to_load = pf_config_get_str(ini, "Plugins", "Modules", FALSE); + required_modules = pf_config_get_str(ini, "Plugins", "Required", FALSE); WINPR_ASSERT(config); config->Modules = pf_config_parse_comma_separated_list(modules_to_load, &config->ModulesCount); diff --git a/server/proxy/pf_context.c b/server/proxy/pf_context.c index 99b9f9620..293135dfc 100644 --- a/server/proxy/pf_context.c +++ b/server/proxy/pf_context.c @@ -30,6 +30,7 @@ #include /* Proxy context initialization callback */ +static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx); static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx) { pServerContext* context = (pServerContext*)ctx; @@ -50,27 +51,24 @@ static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx) return TRUE; error: - WTSCloseServer((HANDLE)context->vcm); - context->vcm = NULL; - - if (context->dynvcReady) - { - CloseHandle(context->dynvcReady); - context->dynvcReady = NULL; - } + client_to_proxy_context_free(client, ctx); return FALSE; } /* Proxy context free callback */ -static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx) +void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx) { pServerContext* context = (pServerContext*)ctx; - if (!client || !context) + WINPR_UNUSED(client); + + if (!context) return; - WTSCloseServer((HANDLE)context->vcm); + if (context->vcm && (context->vcm != INVALID_HANDLE_VALUE)) + WTSCloseServer((HANDLE)context->vcm); + context->vcm = NULL; if (context->dynvcReady) { @@ -270,6 +268,8 @@ void proxy_data_abort_connect(proxyData* pdata) WINPR_ASSERT(pdata); WINPR_ASSERT(pdata->abort_event); SetEvent(pdata->abort_event); + if (pdata->pc) + freerdp_abort_connect(pdata->pc->context.instance); } BOOL proxy_data_shall_disconnect(proxyData* pdata) diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c index 0cfe5961b..839279b5c 100644 --- a/server/proxy/pf_server.c +++ b/server/proxy/pf_server.c @@ -21,8 +21,12 @@ * limitations under the License. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include +#include #include #include #include @@ -377,9 +381,10 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) pdata = proxy_data_new(); if (!pdata) return FALSE; + server = (proxyServer*)peer->ContextExtra; + WINPR_ASSERT(server); proxy_data_set_server_context(pdata, ps); - server = (proxyServer*)peer->ContextExtra; pdata->module = server->module; config = pdata->config = server->config; @@ -390,6 +395,13 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) settings->SupportMonitorLayoutPdu = TRUE; settings->SupportGraphicsPipeline = config->GFX; + + if ((config->PassthroughCount > 0) || config->PassthroughIsBlacklist) + { + if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE)) + return FALSE; + } + if (!freerdp_settings_set_string(settings, FreeRDP_CertificateFile, config->CertificateFile) || !freerdp_settings_set_string(settings, FreeRDP_CertificateContent, config->CertificateContent) || @@ -433,10 +445,6 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) pdata->server_receive_channel_data_original = peer->ReceiveChannelData; peer->ReceiveChannelData = pf_server_receive_channel_data_hook; - if (!ArrayList_Append(server->clients, pdata)) - return FALSE; - - CountdownEvent_AddCount(server->waitGroup, 1); return TRUE; } @@ -447,21 +455,28 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) */ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) { - HANDLE eventHandles[32] = { 0 }; - HANDLE ChannelEvent; - DWORD eventCount; + HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = { 0 }; DWORD tmp; DWORD status; - pServerContext* ps; - proxyData* pdata; + pServerContext* ps = NULL; + proxyData* pdata = NULL; freerdp_peer* client = (freerdp_peer*)arg; proxyServer* server; + size_t count; + BOOL rc; WINPR_ASSERT(client); server = (proxyServer*)client->ContextExtra; WINPR_ASSERT(server); + ArrayList_Lock(server->peer_list); + rc = ArrayList_Append(server->peer_list, _GetCurrentThread()); + count = ArrayList_Count(server->peer_list); + ArrayList_Unlock(server->peer_list); + + if (!rc) + goto out_free_peer; if (!pf_context_init_server_context(client)) goto out_free_peer; @@ -470,6 +485,7 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) ps = (pServerContext*)client->context; WINPR_ASSERT(ps); + PROXY_LOG_DBG(TAG, ps, "Added peer, %" PRIuz " connected", count); pdata = ps->pdata; WINPR_ASSERT(pdata); @@ -479,17 +495,17 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) PROXY_LOG_INFO(TAG, ps, "new connection: proxy address: %s, client address: %s", pdata->config->Host, client->hostname); - /* Main client event handling loop */ - ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm); while (1) { - eventCount = 0; + HANDLE ChannelEvent = INVALID_HANDLE_VALUE; + DWORD eventCount = 0; { WINPR_ASSERT(client->GetEventHandles); - tmp = client->GetEventHandles(client, &eventHandles[eventCount], 32 - eventCount); + tmp = client->GetEventHandles(client, &eventHandles[eventCount], + ARRAYSIZE(eventHandles) - eventCount); - if (tmp == 0) + if ((tmp == 0) || (tmp >= ARRAYSIZE(eventHandles) - 2)) { WLog_ERR(TAG, "Failed to get FreeRDP transport event handles"); break; @@ -497,10 +513,17 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) eventCount += tmp; } + /* Main client event handling loop */ + ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm); + + WINPR_ASSERT(ChannelEvent && (ChannelEvent != INVALID_HANDLE_VALUE)); + WINPR_ASSERT(pdata->abort_event && (pdata->abort_event != INVALID_HANDLE_VALUE)); eventHandles[eventCount++] = ChannelEvent; eventHandles[eventCount++] = pdata->abort_event; - eventHandles[eventCount++] = WTSVirtualChannelManagerGetEventHandle(ps->vcm); - status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, INFINITE); + eventHandles[eventCount++] = server->stopEvent; + + status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, + 1000); /* Do periodic polling to avoid client hang */ if (status == WAIT_FAILED) { @@ -528,6 +551,12 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) break; } + if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0) + { + WLog_INFO(TAG, "Server shutting down, terminating peer"); + break; + } + switch (WTSVirtualChannelManagerGetDrdynvcState(ps->vcm)) { /* Dynamic channel status may have been changed after processing */ @@ -560,45 +589,14 @@ fail: PROXY_LOG_INFO(TAG, ps, "starting shutdown of connection"); PROXY_LOG_INFO(TAG, ps, "stopping proxy's client"); - if (pdata->client_thread) - { - if (pdata->pc) - freerdp_abort_connect(pdata->pc->context.instance); - /* - * Wait for client thread to finish. No need to call CloseHandle() here, as - * it is the responsibility of `proxy_data_free`. - */ - PROXY_LOG_DBG(TAG, pdata->pc, "waiting for client thread to finish"); - WaitForSingleObject(pdata->client_thread, INFINITE); - PROXY_LOG_DBG(TAG, pdata->pc, "thread finished"); - } + /* Abort the client. */ + proxy_data_abort_connect(pdata); pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_END, pdata, client); - if (pdata->client_thread) - { - if (pdata->pc) - freerdp_abort_connect(pdata->pc->context.instance); - /* - * Wait for client thread to finish. No need to call CloseHandle() here, as - * it is the responsibility of `proxy_data_free`. - */ - PROXY_LOG_DBG(TAG, pdata->pc, "waiting for client thread to finish"); - WaitForSingleObject(pdata->client_thread, INFINITE); - PROXY_LOG_DBG(TAG, pdata->pc, "thread finished"); - - if (pdata->pc) - { - freerdp_client_context_free(&pdata->pc->context); - pdata->pc = NULL; - } - } PROXY_LOG_INFO(TAG, ps, "freeing server's channels"); pf_server_channels_free(ps, client); - PROXY_LOG_INFO(TAG, ps, "freeing proxy data"); - ArrayList_Remove(server->clients, pdata); - proxy_data_free(pdata); WINPR_ASSERT(client->Close); client->Close(client); @@ -607,9 +605,26 @@ fail: client->Disconnect(client); out_free_peer: + PROXY_LOG_INFO(TAG, ps, "freeing proxy data"); + + if (pdata && pdata->client_thread) + { + proxy_data_abort_connect(pdata); + WaitForSingleObject(pdata->client_thread, INFINITE); + } + + ArrayList_Lock(server->peer_list); + ArrayList_Remove(server->peer_list, _GetCurrentThread()); + count = ArrayList_Count(server->peer_list); + ArrayList_Unlock(server->peer_list); + PROXY_LOG_DBG(TAG, ps, "Removed peer, %" PRIuz " connected", count); freerdp_peer_context_free(client); freerdp_peer_free(client); - CountdownEvent_Signal(server->waitGroup, 1); + proxy_data_free(pdata); + +#if defined(WITH_DEBUG_EVENTS) + DumpEventHandles(); +#endif ExitThread(0); return 0; } @@ -617,13 +632,17 @@ out_free_peer: static BOOL pf_server_start_peer(freerdp_peer* client) { HANDLE hThread; + proxyServer* server; WINPR_ASSERT(client); - if (!(hThread = CreateThread(NULL, 0, pf_server_handle_peer, (void*)client, 0, NULL))) + server = (proxyServer*)client->ContextExtra; + WINPR_ASSERT(server); + + hThread = CreateThread(NULL, 0, pf_server_handle_peer, (void*)client, 0, NULL); + if (!hThread) return FALSE; - CloseHandle(hThread); return TRUE; } @@ -746,12 +765,6 @@ fail: return FALSE; } -static void pf_server_clients_list_client_free(void* obj) -{ - proxyData* pdata = (proxyData*)obj; - proxy_data_abort_connect(pdata); -} - static BOOL are_all_required_modules_loaded(proxyModule* module, const proxyConfig* config) { size_t i; @@ -770,6 +783,17 @@ static BOOL are_all_required_modules_loaded(proxyModule* module, const proxyConf return TRUE; } +static void peer_free(void* obj) +{ + HANDLE hdl = (HANDLE)obj; + + // TODO: Stop thread + + if (hdl != _GetCurrentThread()) + WaitForSingleObject(hdl, INFINITE); + CloseHandle(hdl); +} + proxyServer* pf_server_new(const proxyConfig* config) { wObject* obj; @@ -800,21 +824,19 @@ proxyServer* pf_server_new(const proxyConfig* config) if (!server->stopEvent) goto out; - server->clients = ArrayList_New(TRUE); - if (!server->clients) - goto out; - - obj = ArrayList_Object(server->clients); - obj->fnObjectFree = pf_server_clients_list_client_free; - - server->waitGroup = CountdownEvent_New(0); - if (!server->waitGroup) - goto out; - server->listener = freerdp_listener_new(); if (!server->listener) goto out; + server->peer_list = ArrayList_New(TRUE); + if (!server->peer_list) + goto out; + + obj = ArrayList_Object(server->peer_list); + WINPR_ASSERT(obj); + + obj->fnObjectFree = peer_free; + server->listener->info = server; server->listener->PeerAccepted = pf_server_peer_accepted; return server; @@ -827,7 +849,7 @@ out: BOOL pf_server_run(proxyServer* server) { BOOL rc = TRUE; - HANDLE eventHandles[32] = { 0 }; + HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = { 0 }; DWORD eventCount; DWORD status; freerdp_listener* listener; @@ -840,9 +862,9 @@ BOOL pf_server_run(proxyServer* server) while (1) { WINPR_ASSERT(listener->GetEventHandles); - eventCount = listener->GetEventHandles(listener, eventHandles, 32); + eventCount = listener->GetEventHandles(listener, eventHandles, ARRAYSIZE(eventHandles)); - if (0 == eventCount) + if ((0 == eventCount) || (eventCount >= ARRAYSIZE(eventHandles))) { WLog_ERR(TAG, "Failed to get FreeRDP event handles"); break; @@ -850,7 +872,10 @@ BOOL pf_server_run(proxyServer* server) WINPR_ASSERT(server->stopEvent); eventHandles[eventCount++] = server->stopEvent; - status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, INFINITE); + status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, 1000); + + if (WAIT_FAILED == status) + break; if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0) break; @@ -865,9 +890,9 @@ BOOL pf_server_run(proxyServer* server) WINPR_ASSERT(listener->CheckFileDescriptor); if (listener->CheckFileDescriptor(listener) != TRUE) { - WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); - rc = FALSE; - break; + WLog_ERR(TAG, "Failed to accept new peer"); + // TODO: Set out of resource error + continue; } } @@ -876,20 +901,23 @@ BOOL pf_server_run(proxyServer* server) return rc; } +static BOOL disconnect_client(void* data, size_t index, va_list ap) +{ + proxyData* pdata = data; + + WINPR_UNUSED(index); + WINPR_UNUSED(ap); + + proxy_data_abort_connect(pdata); + return TRUE; +} + void pf_server_stop(proxyServer* server) { - HANDLE waitHandle = INVALID_HANDLE_VALUE; if (!server) return; - /* clear clients list, also disconnects every client */ - ArrayList_Clear(server->clients); - - /* block until all clients are disconnected */ - waitHandle = CountdownEvent_WaitHandle(server->waitGroup); - if (WaitForSingleObject(waitHandle, INFINITE) != WAIT_OBJECT_0) - WLog_ERR(TAG, "[%s]: WaitForSingleObject failed!", __FUNCTION__); /* signal main thread to stop and wait for the thread to exit */ SetEvent(server->stopEvent); @@ -900,9 +928,10 @@ void pf_server_free(proxyServer* server) if (!server) return; + pf_server_stop(server); + + ArrayList_Free(server->peer_list); freerdp_listener_free(server->listener); - ArrayList_Free(server->clients); - CountdownEvent_Free(server->waitGroup); if (server->stopEvent) CloseHandle(server->stopEvent); @@ -910,6 +939,10 @@ void pf_server_free(proxyServer* server) pf_server_config_free(server->config); pf_modules_free(server->module); free(server); + +#if defined(WITH_DEBUG_EVENTS) + DumpEventHandles(); +#endif } BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep, void* userdata) diff --git a/server/proxy/pf_server.h b/server/proxy/pf_server.h index de7ce6e3e..a4138e1d4 100644 --- a/server/proxy/pf_server.h +++ b/server/proxy/pf_server.h @@ -36,9 +36,8 @@ struct proxy_server proxyConfig* config; freerdp_listener* listener; - wArrayList* clients; /* maintain a list of active sessions, for stats */ - wCountdownEvent* waitGroup; /* wait group used for gracefull shutdown */ HANDLE stopEvent; /* an event used to signal the main thread to stop */ + wArrayList* peer_list; }; #endif /* INT_FREERDP_SERVER_PROXY_SERVER_H */