geometry: change the channel API to mutualize things

Try to mutualize things that are platform independant in the geometry client
channel.

Sponsored by: Rangee GmbH (http://www.rangee.de)
This commit is contained in:
David Fort 2017-12-15 11:16:34 +01:00
parent c44605299f
commit adac409d1b
3 changed files with 154 additions and 37 deletions

View File

@ -72,7 +72,29 @@ struct _GEOMETRY_PLUGIN
typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN;
static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgndata)
static UINT32 mappedGeometryHash(UINT64 *g)
{
return (UINT32)((*g >> 32) + (*g & 0xffffffff));
}
static BOOL mappedGeometryKeyCompare(UINT64 *g1, UINT64 *g2)
{
return *g1 == *g2;
}
static void mappedGeometryFree(MAPPED_GEOMETRY *g)
{
free(g->geometry.rects);
free(g);
}
void freerdp_rgndata_reset(FREERDP_RGNDATA *data)
{
data->nRectCount = 0;
}
static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgndata)
{
UINT32 dwSize, iType;
INT32 right, bottom;
@ -117,12 +139,14 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn
if (rgndata->nRectCount)
{
int i;
RDP_RECT *tmp = realloc(rgndata->rects, rgndata->nRectCount * sizeof(RDP_RECT));
if (!(rgndata->rects = calloc(rgndata->nRectCount, sizeof(RDP_RECT))))
if (!tmp)
{
WLog_ERR(TAG, "unable to allocate memory for %"PRIu32" RECTs", rgndata->nRectCount);
return CHANNEL_RC_NO_MEMORY;
}
rgndata->rects = tmp;
for (i = 0; i < rgndata->nRectCount; i++)
{
@ -146,10 +170,13 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn
static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT32 length, cbGeometryBuffer;
MAPPED_GEOMETRY_PACKET packet;
MAPPED_GEOMETRY *mappedGeometry;
GEOMETRY_PLUGIN* geometry;
GeometryClientContext* context;
UINT ret;
GeometryClientContext *context;
UINT ret = CHANNEL_RC_OK;
UINT32 version, updateType, geometryType;
UINT64 id;
geometry = (GEOMETRY_PLUGIN*) callback->plugin;
context = (GeometryClientContext*)geometry->iface.pInterface;
@ -167,44 +194,107 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, packet.version);
Stream_Read_UINT64(s, packet.mappingId);
Stream_Read_UINT32(s, packet.updateType);
Stream_Read_UINT32(s, version);
Stream_Read_UINT64(s, id);
Stream_Read_UINT32(s, updateType);
Stream_Seek_UINT32(s); /* flags */
Stream_Read_UINT64(s, packet.topLevelId);
Stream_Read_INT32(s, packet.left);
Stream_Read_INT32(s, packet.top);
Stream_Read_INT32(s, packet.right);
Stream_Read_INT32(s, packet.bottom);
Stream_Read_INT32(s, packet.topLevelLeft);
Stream_Read_INT32(s, packet.topLevelTop);
Stream_Read_INT32(s, packet.topLevelRight);
Stream_Read_INT32(s, packet.topLevelBottom);
Stream_Read_UINT32(s, packet.geometryType);
Stream_Read_UINT32(s, cbGeometryBuffer);
if (Stream_GetRemainingLength(s) < cbGeometryBuffer)
mappedGeometry = HashTable_GetItemValue(context->geometries, &id);
if (updateType == GEOMETRY_CLEAR )
{
WLog_ERR(TAG, "invalid packet length");
return ERROR_INVALID_DATA;
if (!mappedGeometry)
{
WLog_ERR(TAG, "geometry 0x%"PRIx64" not found here, ignoring clear command", id);
return CHANNEL_RC_OK;
}
WLog_DBG(TAG, "clearing geometry 0x%"PRIx64"", id);
if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry))
return ERROR_INTERNAL_ERROR;
HashTable_Remove(context->geometries, &id);
}
ZeroMemory(&packet.geometry, sizeof(packet.geometry));
if (cbGeometryBuffer)
else if (updateType == GEOMETRY_UPDATE)
{
ret = geometry_read_RGNDATA(s, cbGeometryBuffer, &packet.geometry);
BOOL newOne = FALSE;
if (ret != CHANNEL_RC_OK)
return ret;
if (!mappedGeometry)
{
newOne = TRUE;
WLog_DBG(TAG, "creating geometry 0x%"PRIx64"", id);
mappedGeometry = calloc(1, sizeof(MAPPED_GEOMETRY));
if (!mappedGeometry)
return CHANNEL_RC_NO_MEMORY;
mappedGeometry->mappingId = id;
if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < 0)
{
WLog_ERR(TAG, "unable to register geometry 0x%"PRIx64" in the table", id);
free(mappedGeometry);
return CHANNEL_RC_NO_MEMORY;
}
}
else
{
WLog_DBG(TAG, "updating geometry 0x%"PRIx64"", id);
}
Stream_Read_UINT64(s, mappedGeometry->topLevelId);
Stream_Read_INT32(s, mappedGeometry->left);
Stream_Read_INT32(s, mappedGeometry->top);
Stream_Read_INT32(s, mappedGeometry->right);
Stream_Read_INT32(s, mappedGeometry->bottom);
Stream_Read_INT32(s, mappedGeometry->topLevelLeft);
Stream_Read_INT32(s, mappedGeometry->topLevelTop);
Stream_Read_INT32(s, mappedGeometry->topLevelRight);
Stream_Read_INT32(s, mappedGeometry->topLevelBottom);
Stream_Read_UINT32(s, geometryType);
Stream_Read_UINT32(s, cbGeometryBuffer);
if (Stream_GetRemainingLength(s) < cbGeometryBuffer)
{
WLog_ERR(TAG, "invalid packet length");
return ERROR_INVALID_DATA;
}
if (cbGeometryBuffer)
{
ret = geometry_read_RGNDATA(s, cbGeometryBuffer, &mappedGeometry->geometry);
if (ret != CHANNEL_RC_OK)
return ret;
}
else
{
freerdp_rgndata_reset(&mappedGeometry->geometry);
}
if (newOne)
{
if (context->MappedGeometryAdded && !context->MappedGeometryAdded(context, mappedGeometry))
{
WLog_ERR(TAG, "geometry added callback failed");
ret = ERROR_INTERNAL_ERROR;
}
}
else
{
if (mappedGeometry->MappedGeometryUpdate && !mappedGeometry->MappedGeometryUpdate(mappedGeometry))
{
WLog_ERR(TAG, "geometry update callback failed");
ret = ERROR_INTERNAL_ERROR;
}
}
}
else
ret = CHANNEL_RC_OK;
if (context->MappedGeometryPacket)
ret = context->MappedGeometryPacket(context, &packet);
free(packet.geometry.rects);
return ret;
}
@ -304,7 +394,6 @@ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin)
* Channel Client Interface
*/
#ifdef BUILTIN_CHANNELS
#define DVCPluginEntry geometry_DVCPluginEntry
#else
@ -342,10 +431,14 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
free(geometry);
return CHANNEL_RC_NO_MEMORY;
goto error_context;
}
context->geometries = HashTable_New(FALSE);
context->geometries->hash = (HASH_TABLE_HASH_FN)mappedGeometryHash;
context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare;
context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryFree;
context->handle = (void*) geometry;
geometry->iface.pInterface = (void*) context;
geometry->context = context;
@ -358,4 +451,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
return error;
error_context:
free(geometry);
return CHANNEL_RC_NO_MEMORY;
}

View File

@ -45,6 +45,7 @@ struct _FREERDP_RGNDATA
typedef struct _FREERDP_RGNDATA FREERDP_RGNDATA;
struct _MAPPED_GEOMETRY_PACKET
{
UINT32 version;

View File

@ -20,6 +20,7 @@
#ifndef FREERDP_CHANNELS_CLIENT_GEOMETRY_H
#define FREERDP_CHANNELS_CLIENT_GEOMETRY_H
#include <winpr/collections.h>
#include <freerdp/channels/geometry.h>
/**
@ -28,14 +29,31 @@
typedef struct _geometry_client_context GeometryClientContext;
typedef UINT (*pcMappedGeometryPacket)(GeometryClientContext* context, MAPPED_GEOMETRY_PACKET *packet);
typedef struct _MAPPED_GEOMETRY MAPPED_GEOMETRY;
typedef BOOL (*pcMappedGeometryAdded)(GeometryClientContext* context, MAPPED_GEOMETRY *geometry);
typedef BOOL (*pcMappedGeometryUpdate)(MAPPED_GEOMETRY *geometry);
typedef BOOL (*pcMappedGeometryClear)(MAPPED_GEOMETRY *geometry);
struct _MAPPED_GEOMETRY
{
UINT64 mappingId;
UINT64 topLevelId;
INT32 left, top, right, bottom;
INT32 topLevelLeft, topLevelTop, topLevelRight, topLevelBottom;
FREERDP_RGNDATA geometry;
void *custom;
pcMappedGeometryUpdate MappedGeometryUpdate;
pcMappedGeometryClear MappedGeometryClear;
};
struct _geometry_client_context
{
wHashTable *geometries;
void* handle;
void* custom;
pcMappedGeometryPacket MappedGeometryPacket;
pcMappedGeometryAdded MappedGeometryAdded;
};
#endif /* FREERDP_CHANNELS_CLIENT_GEOMETRY_H */