proxy: correctly handle dynamic channel fragmentation

This big patch fixes fragmentation handling in the dynamic channel. We used to
have a single state to handle fragmentation at the main dynamic channel level, but
in fact packets can be fragmented per sub channel. So we have to maintain a fragmentation
state per sub channel, this involve treating dynamic and static channels differentely
(so the size of the patch that has to implement state tracking per dynamic channels).
This commit is contained in:
David Fort 2022-06-15 10:21:29 +02:00 коммит произвёл akallabeth
Родитель cfe80694da
Коммит aff8fdac26
9 изменённых файлов: 147 добавлений и 84 удалений

Просмотреть файл

@ -36,7 +36,7 @@ extern "C"
typedef struct proxy_data proxyData;
typedef struct proxy_module proxyModule;
typedef struct p_server_channel_context pServerChannelContext;
typedef struct p_server_static_channel_context pServerStaticChannelContext;
typedef struct s_InterceptContextMapEntry
{
@ -56,16 +56,6 @@ extern "C"
PF_UTILS_CHANNEL_INTERCEPT, /*!< inspect traffic from this channel */
} pf_utils_channel_mode;
/** @brief channel opened status */
typedef enum
{
CHANNEL_OPENSTATE_WAITING_OPEN_STATUS, /*!< dynamic channel waiting for create response */
CHANNEL_OPENSTATE_OPENED, /*!< opened */
CHANNEL_OPENSTATE_CLOSED /*!< dynamic channel has been opened then closed */
} PfChannelOpenStatus;
#define PF_DYNAMIC_CHANNEL_MASK 0xFFFF000000000000
/** @brief result of a channel treatment */
typedef enum
{
@ -74,18 +64,16 @@ extern "C"
PF_CHANNEL_RESULT_ERROR /*!< error during packet treatment */
} PfChannelResult;
typedef PfChannelResult (*proxyChannelDataFn)(proxyData* pdata, const pServerChannelContext* channel,
typedef PfChannelResult (*proxyChannelDataFn)(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSizepServer);
typedef void (*proxyChannelContextDtor)(void *context);
/** @brief per channel configuration */
struct p_server_channel_context
struct p_server_static_channel_context
{
char* channel_name;
UINT64 channel_id;
PfChannelOpenStatus openStatus;
BOOL isDynamic;
UINT32 channel_id;
pf_utils_channel_mode channelMode;
proxyChannelDataFn onFrontData;
proxyChannelDataFn onBackData;
@ -93,7 +81,7 @@ extern "C"
void *context;
};
void ChannelContext_free(pServerChannelContext* ctx);
void StaticChannelContext_free(pServerStaticChannelContext* ctx);
/**
* Wraps rdpContext and holds the state for the proxy's server.
@ -112,7 +100,7 @@ extern "C"
};
typedef struct p_server_context pServerContext;
pServerChannelContext* ChannelContext_new(pServerContext* ps, const char* name, UINT64 id);
pServerStaticChannelContext* StaticChannelContext_new(pServerContext* ps, const char* name, UINT32 id);
/**
* Wraps rdpContext and holds the state for the proxy's client.

Просмотреть файл

@ -24,24 +24,46 @@
#include "pf_channel_drdynvc.h"
#include "../pf_channel.h"
#include "../proxy_modules.h"
#include "../pf_utils.h"
#define TAG PROXY_TAG("drdynvc")
/** @brief channel opened status */
typedef enum
{
CHANNEL_OPENSTATE_WAITING_OPEN_STATUS, /*!< dynamic channel waiting for create response */
CHANNEL_OPENSTATE_OPENED, /*!< opened */
CHANNEL_OPENSTATE_CLOSED /*!< dynamic channel has been opened then closed */
} PfDynChannelOpenStatus;
/** @brief tracker state for a drdynvc stream */
typedef struct
{
ChannelStateTracker* tracker;
UINT32 currentDataLength;
UINT32 CurrentDataReceived;
UINT32 CurrentDataFragments;
} DynChannelTrackerState;
typedef struct p_server_dynamic_channel_context pServerDynamicChannelContext;
struct p_server_dynamic_channel_context
{
char* channel_name;
UINT32 channel_id;
PfDynChannelOpenStatus openStatus;
pf_utils_channel_mode channelMode;
DynChannelTrackerState backTracker;
DynChannelTrackerState frontTracker;
};
/** @brief context for the dynamic channel */
typedef struct
{
DynChannelTrackerState backTracker;
DynChannelTrackerState frontTracker;
wHashTable *channels;
ChannelStateTracker* backTracker;
ChannelStateTracker* frontTracker;
} DynChannelContext;
@ -52,6 +74,49 @@ typedef enum {
DYNCVC_READ_INCOMPLETE /*!< missing bytes to read the complete packet */
} DynvcReadResult;
static pServerDynamicChannelContext* DynamicChannelContext_new(pServerContext* ps, const char* name, UINT32 id)
{
pServerDynamicChannelContext* ret = calloc(1, sizeof(*ret));
if (!ret)
{
PROXY_LOG_ERR(TAG, ps, "error allocating dynamic channel context '%s'", name);
return NULL;
}
ret->channel_id = id;
ret->channel_name = _strdup(name);
if (!ret->channel_name)
{
PROXY_LOG_ERR(TAG, ps, "error allocating name in dynamic channel context '%s'", name);
free(ret);
return NULL;
}
ret->channelMode = pf_utils_get_channel_mode(ps->pdata->config, name);
ret->openStatus = CHANNEL_OPENSTATE_OPENED;
return ret;
}
static void DynamicChannelContext_free(pServerDynamicChannelContext* c)
{
if (c)
{
free(c->channel_name);
free(c);
}
}
static UINT32 ChannelId_Hash(const void* key)
{
const UINT32* v = (const UINT32*)key;
return *v;
}
static BOOL ChannelId_Compare(const UINT32* v1, const UINT32* v2)
{
return (*v1 == *v2);
}
static DynvcReadResult dynvc_read_varInt(wStream* s, size_t len, UINT64* varInt, BOOL last)
{
WINPR_ASSERT(varInt);
@ -89,16 +154,15 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
BOOL haveLength;
UINT64 dynChannelId = 0;
UINT64 Length = 0;
pServerChannelContext* dynChannel = NULL;
pServerDynamicChannelContext* dynChannel = NULL;
WINPR_ASSERT(tracker);
DynChannelContext* dynChannelContext = (DynChannelContext*)tracker->trackerData;
WINPR_ASSERT(dynChannelContext);
BOOL isBackData = (tracker == dynChannelContext->backTracker.tracker);
DynChannelTrackerState* trackerState = isBackData ? &dynChannelContext->backTracker : &dynChannelContext->frontTracker;
WINPR_ASSERT(trackerState);
BOOL isBackData = (tracker == dynChannelContext->backTracker);
DynChannelTrackerState* trackerState = NULL;
UINT32 flags = lastPacket ? CHANNEL_FLAG_LAST : 0;
proxyData* pdata = tracker->pdata;
@ -135,7 +199,6 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
if (haveChannelId)
{
UINT64 maskedDynChannelId;
BYTE cbId = byte0 & 0x03;
switch (dynvc_read_varInt(s, cbId, &dynChannelId, lastPacket))
@ -153,9 +216,7 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
/* we always try to retrieve the dynamic channel in case it would have been opened
* and closed
*/
maskedDynChannelId = dynChannelId | PF_DYNAMIC_CHANNEL_MASK;
dynChannel = (pServerChannelContext*)HashTable_GetItemValue(pdata->ps->channelsById, &maskedDynChannelId);
dynChannel = (pServerDynamicChannelContext*)HashTable_GetItemValue(dynChannelContext->channels, &dynChannelId);
if (cmd != CREATE_REQUEST_PDU || !isBackData)
{
if (!dynChannel)
@ -222,18 +283,17 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
if (!dynChannel)
{
dynChannel = ChannelContext_new(pdata->ps, name, dynChannelId | PF_DYNAMIC_CHANNEL_MASK);
dynChannel = DynamicChannelContext_new(pdata->ps, name, dynChannelId);
if (!dynChannel)
{
WLog_ERR(TAG, "unable to create dynamic channel context data");
return PF_CHANNEL_RESULT_ERROR;
}
dynChannel->isDynamic = TRUE;
if (!HashTable_Insert(pdata->ps->channelsById, &dynChannel->channel_id, dynChannel))
if (!HashTable_Insert(dynChannelContext->channels, &dynChannel->channel_id, dynChannel))
{
WLog_ERR(TAG, "unable register dynamic channel context data");
ChannelContext_free(dynChannel);
DynamicChannelContext_free(dynChannel);
return PF_CHANNEL_RESULT_ERROR;
}
}
@ -255,7 +315,7 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
/* we remove it from the channels map, as it happens that server reused channel ids when
* the channel can't be opened
*/
HashTable_Remove(pdata->ps->channelsById, &dynChannel->channel_id);
HashTable_Remove(dynChannelContext->channels, &dynChannel->channel_id);
}
else
{
@ -290,6 +350,7 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
case DATA_FIRST_PDU:
case DATA_PDU:
/* treat these below */
trackerState = isBackData ? &dynChannel->backTracker : &dynChannel->frontTracker;
break;
case DATA_FIRST_COMPRESSED_PDU:
@ -302,6 +363,12 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
return PF_CHANNEL_RESULT_ERROR;
}
if (dynChannel->openStatus != CHANNEL_OPENSTATE_OPENED)
{
WLog_ERR(TAG, "DynvcTracker(%s): channel is not opened", dynChannel->channel_name);
return PF_CHANNEL_RESULT_ERROR;
}
if ((cmd == DATA_FIRST_PDU) || (cmd == DATA_FIRST_COMPRESSED_PDU))
{
WLog_DBG(TAG, "DynvcTracker(%s): %s DATA_FIRST currentPacketLength=%d", dynChannel->channel_name, direction, Length);
@ -344,12 +411,6 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
}
}
if (dynChannel->openStatus != CHANNEL_OPENSTATE_OPENED)
{
WLog_ERR(TAG, "DynvcTracker(%s): channel is not opened", dynChannel->channel_name);
return PF_CHANNEL_RESULT_ERROR;
}
switch(dynChannel->channelMode)
{
case PF_UTILS_CHANNEL_PASSTHROUGH:
@ -371,26 +432,41 @@ static void DynChannelContext_free(void* context)
DynChannelContext* c = context;
if (!c)
return;
channelTracker_free(c->backTracker.tracker);
channelTracker_free(c->frontTracker.tracker);
channelTracker_free(c->backTracker);
channelTracker_free(c->frontTracker);
HashTable_Free(c->channels);
free(c);
}
static DynChannelContext* DynChannelContext_new(proxyData* pdata, pServerChannelContext* channel)
static DynChannelContext* DynChannelContext_new(proxyData* pdata, pServerStaticChannelContext* channel)
{
wObject* obj;
DynChannelContext* dyn = calloc(1, sizeof(DynChannelContext));
if (!dyn)
return FALSE;
dyn->backTracker.tracker = channelTracker_new(channel, DynvcTrackerPeekFn, dyn);
if (!dyn->backTracker.tracker)
dyn->backTracker = channelTracker_new(channel, DynvcTrackerPeekFn, dyn);
if (!dyn->backTracker)
goto fail;
dyn->backTracker.tracker->pdata = pdata;
dyn->backTracker->pdata = pdata;
dyn->frontTracker.tracker = channelTracker_new(channel, DynvcTrackerPeekFn, dyn);
if (!dyn->frontTracker.tracker)
dyn->frontTracker = channelTracker_new(channel, DynvcTrackerPeekFn, dyn);
if (!dyn->frontTracker)
goto fail;
dyn->frontTracker.tracker->pdata = pdata;
dyn->frontTracker->pdata = pdata;
dyn->channels = HashTable_New(FALSE);
if (!dyn->channels)
goto fail;
if (!HashTable_SetHashFunction(dyn->channels, ChannelId_Hash))
goto fail;
obj = HashTable_KeyObject(dyn->channels);
obj->fnObjectEquals = (OBJECT_EQUALS_FN)ChannelId_Compare;
obj = HashTable_ValueObject(dyn->channels);
obj->fnObjectFree = (OBJECT_FREE_FN)DynamicChannelContext_free;
return dyn;
@ -399,7 +475,7 @@ fail:
return NULL;
}
static PfChannelResult pf_dynvc_back_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_dynvc_back_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -407,10 +483,10 @@ static PfChannelResult pf_dynvc_back_data(proxyData* pdata, const pServerChannel
DynChannelContext* dyn = (DynChannelContext*)channel->context;
WINPR_UNUSED(pdata);
WINPR_ASSERT(dyn);
return channelTracker_update(dyn->backTracker.tracker, xdata, xsize, flags, totalSize);
return channelTracker_update(dyn->backTracker, xdata, xsize, flags, totalSize);
}
static PfChannelResult pf_dynvc_front_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_dynvc_front_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -418,11 +494,11 @@ static PfChannelResult pf_dynvc_front_data(proxyData* pdata, const pServerChanne
DynChannelContext* dyn = (DynChannelContext*)channel->context;
WINPR_UNUSED(pdata);
WINPR_ASSERT(dyn);
return channelTracker_update(dyn->frontTracker.tracker, xdata, xsize, flags, totalSize);
return channelTracker_update(dyn->frontTracker, xdata, xsize, flags, totalSize);
}
BOOL pf_channel_setup_drdynvc(proxyData* pdata, pServerChannelContext* channel)
BOOL pf_channel_setup_drdynvc(proxyData* pdata, pServerStaticChannelContext* channel)
{
DynChannelContext* ret = DynChannelContext_new(pdata, channel);
if (!ret)

Просмотреть файл

@ -22,6 +22,6 @@
#include <freerdp/server/proxy/proxy_context.h>
BOOL pf_channel_setup_drdynvc(proxyData* pdata, pServerChannelContext* channel);
BOOL pf_channel_setup_drdynvc(proxyData* pdata, pServerStaticChannelContext* channel);
#endif /* SERVER_PROXY_CHANNELS_PF_CHANNEL_DRDYNVC_H_ */

Просмотреть файл

@ -1714,7 +1714,7 @@ BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
return TRUE;
}
static PfChannelResult pf_rdpdr_back_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_rdpdr_back_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -1730,7 +1730,7 @@ static PfChannelResult pf_rdpdr_back_data(proxyData* pdata, const pServerChannel
return PF_CHANNEL_RESULT_PASS;
}
static PfChannelResult pf_rdpdr_front_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_rdpdr_front_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -1746,7 +1746,7 @@ static PfChannelResult pf_rdpdr_front_data(proxyData* pdata, const pServerChanne
return PF_CHANNEL_RESULT_PASS;
}
BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerChannelContext* channel)
BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
{
channel->onBackData = pf_rdpdr_back_data;
channel->onFrontData = pf_rdpdr_front_data;

Просмотреть файл

@ -25,7 +25,7 @@
#define TAG PROXY_TAG("channel")
ChannelStateTracker* channelTracker_new(pServerChannelContext* channel, ChannelTrackerPeekFn fn, void* data)
ChannelStateTracker* channelTracker_new(pServerStaticChannelContext* channel, ChannelTrackerPeekFn fn, void* data)
{
ChannelStateTracker* ret = calloc(1, sizeof(ChannelStateTracker));
if (!ret)
@ -134,7 +134,7 @@ PfChannelResult channelTracker_flushCurrent(ChannelStateTracker* t, BOOL first,
{
proxyData* pdata;
pServerContext* ps;
pServerChannelContext* channel;
pServerStaticChannelContext* channel;
UINT32 flags = CHANNEL_FLAG_FIRST;
BOOL r;
const char* direction = toBack ? "F->B" : "B->F";
@ -178,7 +178,7 @@ PfChannelResult channelTracker_flushCurrent(ChannelStateTracker* t, BOOL first,
static PfChannelResult pf_channel_generic_back_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_channel_generic_back_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -209,7 +209,7 @@ static PfChannelResult pf_channel_generic_back_data(proxyData* pdata, const pSer
}
}
static PfChannelResult pf_channel_generic_front_data(proxyData* pdata, const pServerChannelContext* channel,
static PfChannelResult pf_channel_generic_front_data(proxyData* pdata, const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSize)
{
@ -241,7 +241,7 @@ static PfChannelResult pf_channel_generic_front_data(proxyData* pdata, const pSe
}
BOOL pf_channel_setup_generic(pServerChannelContext* channel)
BOOL pf_channel_setup_generic(pServerStaticChannelContext* channel)
{
channel->onBackData = pf_channel_generic_back_data;
channel->onFrontData = pf_channel_generic_front_data;

Просмотреть файл

@ -35,7 +35,7 @@ typedef PfChannelResult (*ChannelTrackerPeekFn)(ChannelStateTracker* tracker, BO
/** @brief a tracker for channel packets */
struct _ChannelStateTracker {
pServerChannelContext* channel;
pServerStaticChannelContext* channel;
ChannelTrackerMode mode;
wStream* currentPacket;
size_t currentPacketReceived;
@ -47,7 +47,7 @@ struct _ChannelStateTracker {
proxyData* pdata;
};
ChannelStateTracker* channelTracker_new(pServerChannelContext* channel, ChannelTrackerPeekFn fn, void* data);
ChannelStateTracker* channelTracker_new(pServerStaticChannelContext* channel, ChannelTrackerPeekFn fn, void* data);
void channelTracker_free(ChannelStateTracker* t);
@ -57,8 +57,8 @@ PfChannelResult channelTracker_update(ChannelStateTracker* tracker, const BYTE*
PfChannelResult channelTracker_flushCurrent(ChannelStateTracker* t, BOOL first, BOOL last, BOOL toFront);
BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerChannelContext* channel);
BOOL pf_channel_setup_generic(pServerChannelContext* channel);
BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel);
BOOL pf_channel_setup_generic(pServerStaticChannelContext* channel);
#endif /* SERVER_PROXY_PF_CHANNEL_H_ */

Просмотреть файл

@ -381,7 +381,7 @@ static BOOL pf_client_receive_channel_data_hook(freerdp* instance, UINT16 channe
pClientContext* pc;
pServerContext* ps;
proxyData* pdata;
pServerChannelContext* channel;
pServerStaticChannelContext* channel;
UINT16 server_channel_id;
UINT64 channelId64 = channelId;

Просмотреть файл

@ -37,30 +37,29 @@
static UINT32 ChannelId_Hash(const void* key)
{
const UINT64* v = (const UINT64*)key;
return (*v & 0xFFFFFFFF) + (*v >> 32);
const UINT32* v = (const UINT32*)key;
return *v;
}
static BOOL ChannelId_Compare(const UINT64* v1, const UINT64* v2)
static BOOL ChannelId_Compare(const UINT32* v1, const UINT32* v2)
{
return (*v1 == *v2);
}
pServerChannelContext* ChannelContext_new(pServerContext* ps, const char* name, UINT64 id)
pServerStaticChannelContext* StaticChannelContext_new(pServerContext* ps, const char* name, UINT32 id)
{
pServerChannelContext* ret = calloc(1, sizeof(*ret));
pServerStaticChannelContext* ret = calloc(1, sizeof(*ret));
if (!ret)
{
PROXY_LOG_ERR(TAG, ps, "error allocating channel context for '%s'", name);
return NULL;
}
ret->openStatus = CHANNEL_OPENSTATE_OPENED;
ret->channel_id = id;
ret->channel_name = _strdup(name);
if (!ret->channel_name)
{
PROXY_LOG_ERR(TAG, ps, "error allocating name in channel context for '%s'", ret);
PROXY_LOG_ERR(TAG, ps, "error allocating name in channel context for '%s'", name);
free(ret);
return NULL;
}
@ -69,7 +68,7 @@ pServerChannelContext* ChannelContext_new(pServerContext* ps, const char* name,
return ret;
}
void ChannelContext_free(pServerChannelContext* ctx)
void StaticChannelContext_free(pServerStaticChannelContext* ctx)
{
if (!ctx)
return;
@ -120,7 +119,7 @@ static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
obj->fnObjectEquals = (OBJECT_EQUALS_FN)ChannelId_Compare;
obj = HashTable_ValueObject(context->channelsById);
obj->fnObjectFree = (OBJECT_FREE_FN)ChannelContext_free;
obj->fnObjectFree = (OBJECT_FREE_FN)StaticChannelContext_free;
return TRUE;
error:

Просмотреть файл

@ -202,12 +202,12 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
for (i = 0; i < accepted_channels_count; i++)
{
pServerChannelContext* channelContext;
pServerStaticChannelContext* channelContext;
const char* cname = accepted_channels[i];
UINT16 channelId = WTSChannelGetId(peer, cname);
PROXY_LOG_INFO(TAG, ps, "Accepted channel: %s (%d)", cname, channelId);
channelContext = ChannelContext_new(ps, cname, channelId);
channelContext = StaticChannelContext_new(ps, cname, channelId);
if (!channelContext)
{
PROXY_LOG_ERR(TAG, ps, "error seting up channelContext for '%s'", cname);
@ -219,7 +219,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
if (!pf_channel_setup_drdynvc(ps->pdata, channelContext))
{
PROXY_LOG_ERR(TAG, ps, "error while setting up dynamic channel");
ChannelContext_free(channelContext);
StaticChannelContext_free(channelContext);
return FALSE;
}
}
@ -228,7 +228,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
if (!pf_channel_setup_rdpdr(ps, channelContext))
{
PROXY_LOG_ERR(TAG, ps, "error while setting up redirection channel");
ChannelContext_free(channelContext);
StaticChannelContext_free(channelContext);
return FALSE;
}
}
@ -237,14 +237,14 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
if (!pf_channel_setup_generic(channelContext))
{
PROXY_LOG_ERR(TAG, ps, "error while setting up generic channel");
ChannelContext_free(channelContext);
StaticChannelContext_free(channelContext);
return FALSE;
}
}
if (!HashTable_Insert(byId, &channelContext->channel_id, channelContext))
{
ChannelContext_free(channelContext);
StaticChannelContext_free(channelContext);
PROXY_LOG_ERR(TAG, ps, "error inserting channelContext in byId table for '%s'", cname);
return FALSE;
}
@ -385,7 +385,7 @@ static BOOL pf_server_receive_channel_data_hook(freerdp_peer* peer, UINT16 chann
pClientContext* pc;
proxyData* pdata;
const proxyConfig* config;
const pServerChannelContext* channel;
const pServerStaticChannelContext* channel;
UINT64 channelId64 = channelId;
WINPR_ASSERT(peer);