libfreerdp-core: expose new API to allow FreeRDS virtual channel hooking

This commit is contained in:
Marc-André Moreau 2014-10-10 16:11:42 -04:00
parent 8865077b40
commit 11ae267518
8 changed files with 174 additions and 5 deletions

View File

@ -48,9 +48,15 @@ typedef BOOL (*psPeerLogon)(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* ident
typedef int (*psPeerSendChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size);
typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size, int flags, int totalSize);
typedef HANDLE (*psPeerVirtualChannelOpen)(freerdp_peer* client, const char* name, UINT32 flags);
typedef BOOL (*psPeerVirtualChannelClose)(freerdp_peer* client, HANDLE hChannel);
typedef int (*psPeerVirtualChannelRead)(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length);
typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length);
struct rdp_freerdp_peer
{
rdpContext* context;
int sockfd;
char hostname[50];
@ -79,6 +85,11 @@ struct rdp_freerdp_peer
psPeerSendChannelData SendChannelData;
psPeerReceiveChannelData ReceiveChannelData;
psPeerVirtualChannelOpen VirtualChannelOpen;
psPeerVirtualChannelClose VirtualChannelClose;
psPeerVirtualChannelRead VirtualChannelRead;
psPeerVirtualChannelWrite VirtualChannelWrite;
int pId;
UINT32 ack_frame_id;
BOOL local;

View File

@ -1060,6 +1060,7 @@ rdpMcs* mcs_new(rdpTransport* transport)
rdpMcs* mcs;
mcs = (rdpMcs*) calloc(1, sizeof(rdpMcs));
if (!mcs)
return NULL;
@ -1073,7 +1074,11 @@ rdpMcs* mcs_new(rdpTransport* transport)
mcs->channelCount = 0;
mcs->channelMaxCount = CHANNEL_MAX_COUNT;
mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
mcs->channels = (rdpMcsChannel*) calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel));
if (!mcs->channels)
goto out_free;

View File

@ -139,6 +139,7 @@ struct rdp_mcs
rdpSettings* settings;
UINT16 userId;
UINT16 baseChannelId;
UINT16 messageChannelId;
DomainParameters domainParameters;

View File

@ -37,6 +37,139 @@
extern const char* DATA_PDU_TYPE_STRINGS[80];
#endif
static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char* name, UINT32 flags)
{
int length;
UINT32 index;
BOOL joined = FALSE;
rdpMcsChannel* mcsChannel = NULL;
rdpPeerChannel* peerChannel = NULL;
rdpMcs* mcs = client->context->rdp->mcs;
if (flags & WTS_CHANNEL_OPTION_DYNAMIC)
return NULL; /* not yet supported */
length = strlen(name);
if (length > 8)
return NULL; /* SVC maximum name length is 8 */
for (index = 0; index < mcs->channelCount; index++)
{
mcsChannel = &(mcs->channels[index]);
if (!mcsChannel->joined)
continue;
if (strncmp(name, mcsChannel->Name, length) == 0)
{
joined = TRUE;
break;
}
}
if (!joined)
return NULL; /* channel is not joined */
peerChannel = (rdpPeerChannel*) mcsChannel->handle;
if (peerChannel)
{
/* channel is already open */
return (HANDLE) peerChannel;
}
peerChannel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel));
if (peerChannel)
{
peerChannel->index = index;
peerChannel->client = client;
peerChannel->channelFlags = flags;
peerChannel->channelId = mcsChannel->ChannelId;
peerChannel->mcsChannel = mcsChannel;
mcsChannel->handle = (void*) peerChannel;
}
return (HANDLE) peerChannel;
}
static BOOL freerdp_peer_virtual_channel_close(freerdp_peer* client, HANDLE hChannel)
{
rdpMcsChannel* mcsChannel = NULL;
rdpPeerChannel* peerChannel = NULL;
if (!hChannel)
return FALSE;
peerChannel = (rdpPeerChannel*) hChannel;
mcsChannel = peerChannel->mcsChannel;
mcsChannel->handle = NULL;
free(peerChannel);
return TRUE;
}
int freerdp_peer_virtual_channel_read(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length)
{
return 1;
}
static int freerdp_peer_virtual_channel_write(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length)
{
wStream* s;
UINT32 flags;
UINT32 chunkSize;
UINT32 maxChunkSize;
UINT32 totalLength;
rdpRdp* rdp = client->context->rdp;
rdpPeerChannel* peerChannel = (rdpPeerChannel*) hChannel;
rdpMcsChannel* mcsChannel = peerChannel->mcsChannel;
if (!hChannel)
return -1;
if (peerChannel->channelFlags & WTS_CHANNEL_OPTION_DYNAMIC)
return -1; /* not yet supported */
maxChunkSize = rdp->settings->VirtualChannelChunkSize;
totalLength = length;
flags = CHANNEL_FLAG_FIRST;
while (length > 0)
{
s = rdp_send_stream_init(rdp);
if (length > maxChunkSize)
{
chunkSize = rdp->settings->VirtualChannelChunkSize;
}
else
{
chunkSize = length;
flags |= CHANNEL_FLAG_LAST;
}
if (mcsChannel->options & CHANNEL_OPTION_SHOW_PROTOCOL)
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
Stream_Write_UINT32(s, totalLength);
Stream_Write_UINT32(s, flags);
Stream_EnsureRemainingCapacity(s, chunkSize);
Stream_Write(s, buffer, chunkSize);
rdp_send(rdp, s, peerChannel->channelId);
buffer += chunkSize;
length -= chunkSize;
flags = 0;
}
return 1;
}
static BOOL freerdp_peer_initialize(freerdp_peer* client)
{
rdpRdp* rdp = client->context->rdp;
@ -427,7 +560,6 @@ static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
{
rdpTransport* transport = peer->context->rdp->transport;
return tranport_drain_output_buffer(transport);
@ -500,6 +632,9 @@ freerdp_peer* freerdp_peer_new(int sockfd)
client->SendChannelData = freerdp_peer_send_channel_data;
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
client->VirtualChannelOpen = freerdp_peer_virtual_channel_open;
client->VirtualChannelClose = freerdp_peer_virtual_channel_close;
client->VirtualChannelWrite = freerdp_peer_virtual_channel_write;
}
return client;

View File

@ -21,6 +21,9 @@
#define __PEER
#include "rdp.h"
#include "mcs.h"
#include "server.h"
#include <freerdp/peer.h>
#endif /* __PEER */

View File

@ -32,6 +32,7 @@ typedef struct rdp_peer_channel rdpPeerChannel;
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
#include "rdp.h"
#include "mcs.h"
#define CREATE_REQUEST_PDU 0x01
#define DATA_FIRST_PDU 0x02
@ -65,15 +66,17 @@ struct rdp_peer_channel
WTSVirtualChannelManager* vcm;
freerdp_peer* client;
UINT16 index;
UINT32 channelId;
UINT16 channelType;
UINT16 index;
UINT32 channelFlags;
wStream* receiveData;
wMessageQueue* queue;
BYTE dvc_open_state;
UINT32 dvc_total_length;
rdpMcsChannel* mcsChannel;
};
struct WTSVirtualChannelManager

View File

@ -138,6 +138,7 @@ typedef struct _wArrayList wArrayList;
WINPR_API int ArrayList_Capacity(wArrayList* arrayList);
WINPR_API int ArrayList_Count(wArrayList* arrayList);
WINPR_API int ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems);
WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);

View File

@ -52,6 +52,16 @@ int ArrayList_Count(wArrayList *arrayList)
return arrayList->size;
}
/**
* Gets the internal list of items contained in the ArrayList.
*/
int ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems)
{
*ppItems = (ULONG_PTR*) arrayList->array;
return arrayList->size;
}
/**
* Gets a value indicating whether the ArrayList has a fixed size.
*/