diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index ad1a13529..ea945e9d3 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -213,7 +213,7 @@ static void pf_client_post_disconnect(freerdp* instance) /* proxy's client failed to connect, and now it's trying to connect without NLA, no need to shutdown * the connection between proxy's server and the original client. */ - SetEvent(pdata->connectionClosed); + proxy_data_abort_connect(pdata); } /* It's important to avoid calling `freerdp_peer_context_free` and `freerdp_peer_free` here, @@ -396,14 +396,18 @@ static BOOL pf_client_client_new(freerdp* instance, rdpContext* context) static int pf_client_client_stop(rdpContext* context) { pClientContext* pc = (pClientContext*) context; - pServerContext* ps = pc->pdata->ps; + proxyData* pdata = pc->pdata; + WLog_DBG(TAG, "aborting client connection"); freerdp_abort_connect(context->instance); - if (ps->thread) + if (pdata->client_thread) { - WaitForSingleObject(ps->thread, INFINITE); - CloseHandle(ps->thread); - ps->thread = NULL; + /* Wait for client thread to finish. No need to call CloseHandle() here, as + * it is the responsibility of `proxy_data_free`. + */ + WLog_DBG(TAG, "pf_client_client_stop(): waiting for thread to finish"); + WaitForSingleObject(pdata->client_thread, INFINITE); + WLog_DBG(TAG, "pf_client_client_stop(): thread finished"); } return 0; diff --git a/server/proxy/pf_context.c b/server/proxy/pf_context.c index 3729d9db8..bcca78e4a 100644 --- a/server/proxy/pf_context.c +++ b/server/proxy/pf_context.c @@ -161,7 +161,7 @@ proxyData* proxy_data_new() return NULL; } - if (!(pdata->connectionClosed = CreateEvent(NULL, TRUE, FALSE, NULL))) + if (!(pdata->abort_event = CreateEvent(NULL, TRUE, FALSE, NULL))) { proxy_data_free(pdata); return NULL; @@ -191,11 +191,27 @@ out_fail: void proxy_data_free(proxyData* pdata) { connection_info_free(pdata->info); - if (pdata->connectionClosed) + if (pdata->abort_event) { - CloseHandle(pdata->connectionClosed); - pdata->connectionClosed = NULL; + CloseHandle(pdata->abort_event); + pdata->abort_event = NULL; + } + + if (pdata->client_thread) + { + CloseHandle(pdata->client_thread); + pdata->client_thread = NULL; } free(pdata); } + +void proxy_data_abort_connect(proxyData* pdata) +{ + SetEvent(pdata->abort_event); +} + +BOOL proxy_data_shall_disconnect(proxyData* pdata) +{ + return WaitForSingleObject(pdata->abort_event, 0) == WAIT_OBJECT_0; +} diff --git a/server/proxy/pf_context.h b/server/proxy/pf_context.h index 015a88bf7..7777500c0 100644 --- a/server/proxy/pf_context.h +++ b/server/proxy/pf_context.h @@ -46,7 +46,6 @@ struct p_server_context proxyData* pdata; HANDLE vcm; - HANDLE thread; HANDLE dynvcReady; RdpgfxServerContext* gfx; @@ -91,17 +90,25 @@ struct proxy_data pServerContext* ps; pClientContext* pc; - HANDLE connectionClosed; + HANDLE abort_event; + HANDLE client_thread; connectionInfo* info; filters_list* filters; }; -BOOL init_p_server_context(freerdp_peer* client); +/* client */ rdpContext* p_client_context_create(rdpSettings* clientSettings); + +/* pdata */ proxyData* proxy_data_new(); BOOL proxy_data_set_connection_info(proxyData* pdata, rdpSettings* ps, rdpSettings* pc); void proxy_data_free(proxyData* pdata); void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_server); +void proxy_data_abort_connect(proxyData* pdata); +BOOL proxy_data_shall_disconnect(proxyData* pdata); + +/* server */ +BOOL init_p_server_context(freerdp_peer* client); #endif /* FREERDP_SERVER_PROXY_PFCONTEXT_H */ diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c index 4a69864be..de55c3da1 100644 --- a/server/proxy/pf_server.c +++ b/server/proxy/pf_server.c @@ -182,7 +182,7 @@ static BOOL pf_server_post_connect(freerdp_peer* client) pf_server_disp_init(ps); /* Start a proxy's client in it's own thread */ - if (!(ps->thread = CreateThread(NULL, 0, pf_client_start, pc, 0, NULL))) + if (!(pdata->client_thread = CreateThread(NULL, 0, pf_client_start, pc, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); return FALSE; @@ -295,7 +295,7 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg) eventCount += tmp; } eventHandles[eventCount++] = ChannelEvent; - eventHandles[eventCount++] = pdata->connectionClosed; + eventHandles[eventCount++] = pdata->abort_event; eventHandles[eventCount++] = WTSVirtualChannelManagerGetEventHandle(ps->vcm); status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, INFINITE); @@ -305,12 +305,6 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg) break; } - if (pf_common_connection_aborted_by_peer(pdata)) - { - WLog_INFO(TAG, "proxy's client disconnected, closing connection with client %s", client->hostname); - break; - } - if (client->CheckFileDescriptor(client) != TRUE) break; @@ -323,6 +317,13 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg) } } + /* only disconnect after checking client's and vcm's file descriptors */ + if (proxy_data_shall_disconnect(pdata)) + { + WLog_INFO(TAG, "abort_event is set, closing connection with client %s", client->hostname); + break; + } + switch (WTSVirtualChannelManagerGetDrdynvcState(ps->vcm)) { /* Dynamic channel status may have been changed after processing */