libfreerdp-core: refactor fastpath fragmentation

This commit is contained in:
Marc-André Moreau 2013-04-29 23:55:44 -04:00
parent 51715636a5
commit 83af4266bf
4 changed files with 133 additions and 38 deletions

View File

@ -26,10 +26,10 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/api.h>
#include <freerdp/crypto/per.h>
#include <winpr/stream.h>
#include "orders.h"
#include "update.h"
@ -277,21 +277,34 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
return status;
}
const char* fastpath_get_fragmentation_string(BYTE fragmentation)
{
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
return "FASTPATH_FRAGMENT_SINGLE";
else if (fragmentation == FASTPATH_FRAGMENT_LAST)
return "FASTPATH_FRAGMENT_LAST";
else if (fragmentation == FASTPATH_FRAGMENT_FIRST)
return "FASTPATH_FRAGMENT_FIRST";
else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
return "FASTPATH_FRAGMENT_NEXT";
return "FASTPATH_FRAGMENT_UNKNOWN";
}
static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
{
int status;
UINT16 size;
UINT32 roff;
UINT32 rlen;
rdpRdp* rdp;
int next_pos;
UINT32 totalSize;
BYTE updateCode;
BYTE fragmentation;
BYTE compression;
BYTE compressionFlags;
wStream* update_stream;
wStream* comp_stream;
rdpRdp* rdp;
UINT32 roff;
UINT32 rlen;
status = 0;
rdp = fastpath->rdp;
@ -328,42 +341,107 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
}
update_stream = NULL;
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
{
totalSize = size;
update_stream = comp_stream;
}
else
{
if (fragmentation == FASTPATH_FRAGMENT_FIRST)
Stream_SetPosition(fastpath->updateData, 0);
stream_check_size(fastpath->updateData, size);
stream_copy(fastpath->updateData, comp_stream, size);
if (Stream_GetPosition(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize)
if (fastpath->fragmentation != -1)
{
fprintf(stderr, "fastpath PDU is bigger than MultifragMaxRequestSize\n");
fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_SINGLE\n");
return -1;
}
if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
update_stream = fastpath->updateData;
totalSize = Stream_GetPosition(update_stream);
Stream_SetPosition(update_stream, 0);
}
}
if (update_stream)
{
status = fastpath_recv_update(fastpath, updateCode, totalSize, update_stream);
totalSize = size;
status = fastpath_recv_update(fastpath, updateCode, totalSize, comp_stream);
if (status < 0)
return -1;
}
else
{
rdpTransport* transport = fastpath->rdp->transport;
if (fragmentation == FASTPATH_FRAGMENT_FIRST)
{
if (fastpath->fragmentation != -1)
{
fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_FIRST\n");
return -1;
}
fastpath->fragmentation = FASTPATH_FRAGMENT_FIRST;
totalSize = size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
totalSize, transport->settings->MultifragMaxRequestSize);
return -1;
}
fastpath->updateData = StreamPool_Take(transport->ReceivePool, size);
Stream_SetPosition(fastpath->updateData, 0);
Stream_Copy(fastpath->updateData, comp_stream, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
{
if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
(fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
{
fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_NEXT\n");
return -1;
}
fastpath->fragmentation = FASTPATH_FRAGMENT_NEXT;
totalSize = Stream_GetPosition(fastpath->updateData) + size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
totalSize, transport->settings->MultifragMaxRequestSize);
return -1;
}
Stream_EnsureCapacity(fastpath->updateData, totalSize);
Stream_Copy(fastpath->updateData, comp_stream, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
(fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
{
fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_LAST\n");
return -1;
}
fastpath->fragmentation = -1;
totalSize = Stream_GetPosition(fastpath->updateData) + size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
totalSize, transport->settings->MultifragMaxRequestSize);
return -1;
}
Stream_EnsureCapacity(fastpath->updateData, totalSize);
Stream_Copy(fastpath->updateData, comp_stream, size);
Stream_SealLength(fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
status = fastpath_recv_update(fastpath, updateCode, totalSize, fastpath->updateData);
Stream_Release(fastpath->updateData);
if (status < 0)
return -1;
}
}
Stream_SetPosition(s, next_pos);
@ -798,16 +876,22 @@ rdpFastPath* fastpath_new(rdpRdp* rdp)
rdpFastPath* fastpath;
fastpath = (rdpFastPath*) malloc(sizeof(rdpFastPath));
ZeroMemory(fastpath, sizeof(rdpFastPath));
fastpath->rdp = rdp;
fastpath->updateData = stream_new(4096);
if (fastpath)
{
ZeroMemory(fastpath, sizeof(rdpFastPath));
fastpath->rdp = rdp;
fastpath->fragmentation = -1;
}
return fastpath;
}
void fastpath_free(rdpFastPath* fastpath)
{
stream_free(fastpath->updateData);
free(fastpath);
if (fastpath)
{
free(fastpath);
}
}

View File

@ -101,6 +101,7 @@ struct rdp_fastpath
BYTE encryptionFlags;
BYTE numberEvents;
wStream* updateData;
int fragmentation;
};
UINT16 fastpath_header_length(wStream* s);

View File

@ -126,7 +126,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
{
s = pool->aArray[index];
if (s->capacity == size)
if (s->capacity >= size)
{
StreamPool_ShiftAvailable(pool, index, -1);
found = TRUE;
@ -135,9 +135,14 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
}
if (!found)
{
s = Stream_New(NULL, size);
}
else
{
Stream_EnsureCapacity(s, size);
Stream_Pointer(s) = Stream_Buffer(s);
}
s->pool = pool;
s->count = 1;

View File

@ -29,9 +29,14 @@ void Stream_EnsureCapacity(wStream* s, size_t size)
{
if (s->capacity < size)
{
size_t position;
position = Stream_GetPosition(s);
s->capacity = size;
s->buffer = (BYTE*) realloc(s->buffer, size);
s->pointer = s->buffer;
Stream_SetPosition(s, position);
}
}