libfreerdp-core: expose new API to allow FreeRDS virtual channel hooking
This commit is contained in:
parent
8865077b40
commit
11ae267518
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -139,6 +139,7 @@ struct rdp_mcs
|
||||
rdpSettings* settings;
|
||||
|
||||
UINT16 userId;
|
||||
UINT16 baseChannelId;
|
||||
UINT16 messageChannelId;
|
||||
|
||||
DomainParameters domainParameters;
|
||||
|
@ -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;
|
||||
|
@ -21,6 +21,9 @@
|
||||
#define __PEER
|
||||
|
||||
#include "rdp.h"
|
||||
#include "mcs.h"
|
||||
#include "server.h"
|
||||
|
||||
#include <freerdp/peer.h>
|
||||
|
||||
#endif /* __PEER */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user