From a8c5926154183a3b2a7b60acfd000b4625a75f0e Mon Sep 17 00:00:00 2001 From: David Fort Date: Tue, 3 Oct 2023 21:41:39 +0200 Subject: [PATCH] [server,drdynvc] use a hashtable for dynamic channels instead of an arrayList This speeds up all operations around dynamic channels. --- libfreerdp/core/server.c | 59 ++++++++++++++++++++-------------------- libfreerdp/core/server.h | 2 +- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index 9eb589a22..5e02d90d5 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -64,29 +64,8 @@ static wHashTable* g_ServerHandles = NULL; static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, UINT32 ChannelId) { - int index; - int count; - BOOL found = FALSE; - rdpPeerChannel* channel = NULL; - WINPR_ASSERT(vcm); - - ArrayList_Lock(vcm->dynamicVirtualChannels); - count = ArrayList_Count(vcm->dynamicVirtualChannels); - - for (index = 0; index < count; index++) - { - channel = (rdpPeerChannel*)ArrayList_GetItem(vcm->dynamicVirtualChannels, index); - WINPR_ASSERT(channel); - if (channel->channelId == ChannelId) - { - found = TRUE; - break; - } - } - - ArrayList_Unlock(vcm->dynamicVirtualChannels); - return found ? channel : NULL; + return HashTable_GetItemValue(vcm->dynamicVirtualChannels, &ChannelId); } static BOOL wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* Buffer, UINT32 Length) @@ -338,7 +317,7 @@ static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel) dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId); if (!dvc) { - DEBUG_DVC("ChannelId %" PRIu32 " not exists.", ChannelId); + DEBUG_DVC("ChannelId %" PRIu32 " does not exist.", ChannelId); return TRUE; } } @@ -973,6 +952,19 @@ static void array_channel_free(void* ptr) channel_free(channel); } +static BOOL dynChannelMatch(const void* v1, const void* v2) +{ + const UINT32* p1 = (const UINT32*)v1; + const UINT32* p2 = (const UINT32*)v2; + return *p1 == *p2; +} + +static UINT32 channelId_Hash(const void* key) +{ + const UINT32* v = (const UINT32*)key; + return *v; +} + HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName) { rdpContext* context; @@ -1021,19 +1013,28 @@ HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName) goto error_queue; vcm->dvc_channel_id_seq = 0; - vcm->dynamicVirtualChannels = ArrayList_New(TRUE); + vcm->dynamicVirtualChannels = HashTable_New(TRUE); if (!vcm->dynamicVirtualChannels) goto error_dynamicVirtualChannels; + if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash)) + goto error_hashFunction; + { - wObject* obj = ArrayList_Object(vcm->dynamicVirtualChannels); + wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels); WINPR_ASSERT(obj); obj->fnObjectFree = array_channel_free; + + obj = HashTable_KeyObject(vcm->dynamicVirtualChannels); + obj->fnObjectEquals = dynChannelMatch; } client->ReceiveChannelData = WTSReceiveChannelData; hServer = (HANDLE)vcm; return hServer; + +error_hashFunction: + HashTable_Free(vcm->dynamicVirtualChannels); error_dynamicVirtualChannels: MessageQueue_Free(vcm->queue); error_queue: @@ -1064,7 +1065,7 @@ VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer) { HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId); - ArrayList_Free(vcm->dynamicVirtualChannels); + HashTable_Free(vcm->dynamicVirtualChannels); if (vcm->drdynvc_channel) { @@ -1426,7 +1427,7 @@ HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualNam channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq); - if (!ArrayList_Append(vcm->dynamicVirtualChannels, channel)) + if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel)) { channel_free(channel); channel = NULL; @@ -1449,7 +1450,7 @@ HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualNam fail: Stream_Free(s, TRUE); if (channel) - ArrayList_Remove(vcm->dynamicVirtualChannels, channel); + HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; @@ -1504,7 +1505,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) Stream_Free(s, TRUE); } } - ArrayList_Remove(vcm->dynamicVirtualChannels, channel); + HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId); } } diff --git a/libfreerdp/core/server.h b/libfreerdp/core/server.h index a91875f6b..bcefa49f1 100644 --- a/libfreerdp/core/server.h +++ b/libfreerdp/core/server.h @@ -87,7 +87,7 @@ struct WTSVirtualChannelManager psDVCCreationStatusCallback dvc_creation_status; void* dvc_creation_status_userdata; - wArrayList* dynamicVirtualChannels; + wHashTable* dynamicVirtualChannels; }; FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName,