/* 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,
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;
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;
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;
+}
proxyData* pdata;
HANDLE vcm;
- HANDLE thread;
HANDLE dynvcReady;
RdpgfxServerContext* gfx;
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 */
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;
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);
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;
}
}
+ /* 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 */