mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 09:54:26 +08:00
[core,server] lock FreeRDP_WTSVirtualChannelWrite
* FreeRDP_WTSVirtualChannelWrite might be called from different threads, so lock the function execution to keep split packets in order * unify DVC and SVC channel creation/deletion to avoid duplicate code
This commit is contained in:
parent
6e1bb4e1c3
commit
6c26980585
@ -93,14 +93,11 @@ static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char
|
||||
return (HANDLE)peerChannel;
|
||||
}
|
||||
|
||||
peerChannel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
|
||||
peerChannel = server_channel_common_new(client, index, mcsChannel->ChannelId, 128, NULL, name);
|
||||
|
||||
if (peerChannel)
|
||||
{
|
||||
peerChannel->index = index;
|
||||
peerChannel->client = client;
|
||||
peerChannel->channelFlags = flags;
|
||||
peerChannel->channelId = mcsChannel->ChannelId;
|
||||
peerChannel->mcsChannel = mcsChannel;
|
||||
mcsChannel->handle = (void*)peerChannel;
|
||||
}
|
||||
@ -122,7 +119,7 @@ static BOOL freerdp_peer_virtual_channel_close(freerdp_peer* client, HANDLE hCha
|
||||
mcsChannel = peerChannel->mcsChannel;
|
||||
WINPR_ASSERT(mcsChannel);
|
||||
mcsChannel->handle = NULL;
|
||||
free(peerChannel);
|
||||
server_channel_common_free(peerChannel);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -944,7 +944,10 @@ static void wts_virtual_channel_manager_free_message(void* obj)
|
||||
}
|
||||
}
|
||||
|
||||
static void channel_free(rdpPeerChannel* channel);
|
||||
static void channel_free(rdpPeerChannel* channel)
|
||||
{
|
||||
server_channel_common_free(channel);
|
||||
}
|
||||
|
||||
static void array_channel_free(void* ptr)
|
||||
{
|
||||
@ -1230,23 +1233,15 @@ static void peer_channel_queue_free_message(void* obj)
|
||||
msg->context = NULL;
|
||||
}
|
||||
|
||||
void channel_free(rdpPeerChannel* channel)
|
||||
{
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
MessageQueue_Free(channel->queue);
|
||||
Stream_Free(channel->receiveData, TRUE);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* client,
|
||||
UINT32 ChannelId, UINT16 index, UINT16 type, size_t chunkSize,
|
||||
const char* name)
|
||||
{
|
||||
size_t len;
|
||||
wObject queueCallbacks = { 0 };
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
|
||||
queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
|
||||
|
||||
rdpPeerChannel* channel =
|
||||
server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
|
||||
|
||||
WINPR_ASSERT(vcm);
|
||||
WINPR_ASSERT(client);
|
||||
@ -1254,27 +1249,10 @@ static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer*
|
||||
if (!channel)
|
||||
goto fail;
|
||||
|
||||
len = strnlen(name, sizeof(channel->channelName) - 1);
|
||||
strncpy(channel->channelName, name, len);
|
||||
|
||||
channel->vcm = vcm;
|
||||
channel->client = client;
|
||||
channel->channelId = ChannelId;
|
||||
channel->index = index;
|
||||
channel->channelType = type;
|
||||
channel->creationStatus =
|
||||
(type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
|
||||
channel->receiveData = Stream_New(NULL, chunkSize);
|
||||
|
||||
if (!channel->receiveData)
|
||||
goto fail;
|
||||
|
||||
queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
|
||||
|
||||
channel->queue = MessageQueue_New(&queueCallbacks);
|
||||
|
||||
if (!channel->queue)
|
||||
goto fail;
|
||||
|
||||
return channel;
|
||||
fail:
|
||||
@ -1479,8 +1457,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
|
||||
{
|
||||
rdpMcsChannel* cur = &mcs->channels[channel->index];
|
||||
rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
|
||||
if (peerChannel)
|
||||
channel_free(peerChannel);
|
||||
channel_free(peerChannel);
|
||||
cur->handle = NULL;
|
||||
}
|
||||
}
|
||||
@ -1568,11 +1545,12 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
UINT32 written;
|
||||
UINT32 totalWritten = 0;
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
|
||||
BOOL ret = TRUE;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!channel)
|
||||
return FALSE;
|
||||
|
||||
EnterCriticalSection(&channel->writeLock);
|
||||
WINPR_ASSERT(channel->vcm);
|
||||
if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
{
|
||||
@ -1582,7 +1560,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
if (!buffer)
|
||||
{
|
||||
SetLastError(E_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CopyMemory(buffer, Buffer, length);
|
||||
@ -1592,7 +1570,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
|
||||
{
|
||||
DEBUG_DVC("drdynvc not ready");
|
||||
return FALSE;
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1610,7 +1588,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
SetLastError(E_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buffer = Stream_Buffer(s);
|
||||
@ -1639,13 +1617,17 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
Length -= written;
|
||||
Buffer += written;
|
||||
totalWritten += written;
|
||||
ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length);
|
||||
if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBytesWritten)
|
||||
*pBytesWritten = totalWritten;
|
||||
|
||||
ret = TRUE;
|
||||
fail:
|
||||
LeaveCriticalSection(&channel->writeLock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1936,3 +1918,41 @@ BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR passwor
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void server_channel_common_free(rdpPeerChannel* channel)
|
||||
{
|
||||
if (!channel)
|
||||
return;
|
||||
MessageQueue_Free(channel->queue);
|
||||
Stream_Free(channel->receiveData, TRUE);
|
||||
DeleteCriticalSection(&channel->writeLock);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
|
||||
size_t chunkSize, const wObject* callback,
|
||||
const char* name)
|
||||
{
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
InitializeCriticalSection(&channel->writeLock);
|
||||
|
||||
channel->receiveData = Stream_New(NULL, chunkSize);
|
||||
if (!channel->receiveData)
|
||||
goto fail;
|
||||
|
||||
channel->queue = MessageQueue_New(callback);
|
||||
if (!channel->queue)
|
||||
goto fail;
|
||||
|
||||
channel->index = index;
|
||||
channel->client = client;
|
||||
channel->channelId = channelId;
|
||||
strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
|
||||
return channel;
|
||||
fail:
|
||||
server_channel_common_free(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ struct rdp_peer_channel
|
||||
rdpMcsChannel* mcsChannel;
|
||||
|
||||
char channelName[128];
|
||||
CRITICAL_SECTION writeLock;
|
||||
};
|
||||
|
||||
struct WTSVirtualChannelManager
|
||||
@ -264,4 +265,9 @@ FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer);
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password,
|
||||
LPCSTR domain);
|
||||
|
||||
FREERDP_LOCAL rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index,
|
||||
UINT32 channelId, size_t chunkSize,
|
||||
const wObject* callback, const char* name);
|
||||
FREERDP_LOCAL void server_channel_common_free(rdpPeerChannel*);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_SERVER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user