[proxy,drdynvc] remove dynamic channels on open
dynamic channels can be opened at any time during a session. If we receive a CREATE_REQUEST_PDU and the channel id is already in use, print out a warning with the existing channel details and discard it before creating the newly requested channel.
This commit is contained in:
parent
1dfe7878f6
commit
133585cd5e
@ -87,6 +87,21 @@ typedef enum
|
||||
DYNCVC_READ_INCOMPLETE /*!< missing bytes to read the complete packet */
|
||||
} DynvcReadResult;
|
||||
|
||||
static const char* openstatus2str(PfDynChannelOpenStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case CHANNEL_OPENSTATE_WAITING_OPEN_STATUS:
|
||||
return "CHANNEL_OPENSTATE_WAITING_OPEN_STATUS";
|
||||
case CHANNEL_OPENSTATE_CLOSED:
|
||||
return "CHANNEL_OPENSTATE_CLOSED";
|
||||
case CHANNEL_OPENSTATE_OPENED:
|
||||
return "CHANNEL_OPENSTATE_OPENED";
|
||||
default:
|
||||
return "CHANNEL_OPENSTATE_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static PfChannelResult data_cb(pServerContext* ps, pServerDynamicChannelContext* channel,
|
||||
BOOL isBackData, ChannelStateTracker* tracker, BOOL firstPacket,
|
||||
BOOL lastPacket)
|
||||
@ -351,28 +366,41 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
|
||||
dev.flags = flags;
|
||||
dev.total_size = Stream_GetPosition(currentPacket);
|
||||
|
||||
if (dynChannel)
|
||||
{
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"Reusing channel id %" PRIu32 ", previously %s [state %s, mode %s], now %s",
|
||||
dynChannel->channelId, dynChannel->channelName,
|
||||
openstatus2str(dynChannel->openStatus),
|
||||
pf_utils_channel_mode_string(dynChannel->channelMode), dev.channel_name);
|
||||
|
||||
HashTable_Remove(dynChannelContext->channels, &dynChannel->channelId);
|
||||
dynChannel = NULL;
|
||||
}
|
||||
|
||||
if (!pf_modules_run_filter(pdata->module,
|
||||
FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE, pdata,
|
||||
&dev))
|
||||
return PF_CHANNEL_RESULT_DROP; /* Silently drop */
|
||||
|
||||
dynChannel = DynamicChannelContext_new(pdata->ps, name, dynChannelId);
|
||||
if (!dynChannel)
|
||||
{
|
||||
dynChannel = DynamicChannelContext_new(pdata->ps, name, dynChannelId);
|
||||
if (!dynChannel)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to create dynamic channel context data");
|
||||
return PF_CHANNEL_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if (!HashTable_Insert(dynChannelContext->channels, &dynChannel->channelId,
|
||||
dynChannel))
|
||||
{
|
||||
WLog_ERR(TAG, "unable register dynamic channel context data");
|
||||
DynamicChannelContext_free(dynChannel);
|
||||
return PF_CHANNEL_RESULT_ERROR;
|
||||
}
|
||||
WLog_ERR(TAG, "unable to create dynamic channel context data");
|
||||
return PF_CHANNEL_RESULT_ERROR;
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "Adding channel '%s'[%d]", dynChannel->channelName,
|
||||
dynChannel->channelId);
|
||||
if (!HashTable_Insert(dynChannelContext->channels, &dynChannel->channelId,
|
||||
dynChannel))
|
||||
{
|
||||
WLog_ERR(TAG, "unable register dynamic channel context data");
|
||||
DynamicChannelContext_free(dynChannel);
|
||||
return PF_CHANNEL_RESULT_ERROR;
|
||||
}
|
||||
|
||||
dynChannel->openStatus = CHANNEL_OPENSTATE_WAITING_OPEN_STATUS;
|
||||
|
||||
return channelTracker_flushCurrent(tracker, firstPacket, lastPacket, FALSE);
|
||||
@ -386,17 +414,8 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
|
||||
WLog_DBG(TAG, "DynvcTracker(%" PRIu64 ",%s): %s CREATE_RESPONSE openStatus=%" PRIu32,
|
||||
dynChannelId, dynChannel->channelName, direction, creationStatus);
|
||||
|
||||
if (creationStatus != 0)
|
||||
{
|
||||
/* we remove it from the channels map, as it happens that server reused channel ids
|
||||
* when the channel can't be opened
|
||||
*/
|
||||
HashTable_Remove(dynChannelContext->channels, &dynChannel->channelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (creationStatus == 0)
|
||||
dynChannel->openStatus = CHANNEL_OPENSTATE_OPENED;
|
||||
}
|
||||
|
||||
return channelTracker_flushCurrent(tracker, firstPacket, lastPacket, TRUE);
|
||||
}
|
||||
@ -408,6 +427,12 @@ static PfChannelResult DynvcTrackerPeekFn(ChannelStateTracker* tracker, BOOL fir
|
||||
WLog_DBG(TAG, "DynvcTracker(%s): %s Close request on channel", dynChannel->channelName,
|
||||
direction);
|
||||
channelTracker_setMode(tracker, CHANNEL_TRACKER_PASS);
|
||||
if (dynChannel->openStatus != CHANNEL_OPENSTATE_OPENED)
|
||||
{
|
||||
WLog_WARN(TAG, "DynvcTracker(%s): %s is in state %s, expected %s",
|
||||
dynChannel->channelName, openstatus2str(dynChannel->openStatus),
|
||||
openstatus2str(CHANNEL_OPENSTATE_OPENED));
|
||||
}
|
||||
dynChannel->openStatus = CHANNEL_OPENSTATE_CLOSED;
|
||||
return channelTracker_flushCurrent(tracker, firstPacket, lastPacket, !isBackData);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user