xfreerdp: initial remote assistance controls (ctrl+alt+c to request/release control)

This commit is contained in:
Marc-André Moreau 2014-06-30 17:17:06 -04:00
parent 5606c64f61
commit e42465372a
8 changed files with 212 additions and 41 deletions

View File

@ -21,6 +21,9 @@
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/client/encomsp.h>
#include "encomsp_main.h"
@ -32,6 +35,30 @@ EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
return pInterface;
}
int encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
{
UINT32 status = 0;
if (!encomsp)
return -1;
#if 0
printf("EncomspWrite (%d)\n", Stream_Length(s));
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
#endif
status = encomsp->channelEntryPoints.pVirtualChannelWrite(encomsp->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "encomsp_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
return -1;
}
return 1;
}
int encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
{
if (Stream_GetRemainingLength(s) < ENCOMSP_ORDER_HEADER_SIZE)
@ -43,6 +70,14 @@ int encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
return 1;
}
int encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
{
Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
return 1;
}
int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
{
ZeroMemory(str, sizeof(ENCOMSP_UNICODE_STRING));
@ -449,6 +484,30 @@ int encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wS
return 1;
}
int encomsp_send_change_participant_control_level_pdu(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu)
{
wStream* s;
encomspPlugin* encomsp;
encomsp = (encomspPlugin*) context->handle;
pdu->Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
pdu->Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
s = Stream_New(NULL, pdu->Length);
encomsp_write_header(s, (ENCOMSP_ORDER_HEADER*) pdu);
Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */
Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */
Stream_SealLength(s);
encomsp_virtual_channel_write(encomsp, s);
return 1;
}
int encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
@ -531,6 +590,8 @@ static int encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
if (encomsp_read_header(s, &header) < 0)
return -1;
//printf("EncomspReceive: Type: %d Length: %d\n", header.Type, header.Length);
switch (header.Type)
{
case ODTYPE_FILTER_STATE_UPDATED:
@ -866,7 +927,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->ShowWindow = NULL;
context->ParticipantCreated = NULL;
context->ParticipantRemoved = NULL;
context->ChangeParticipantControlLevel = NULL;
context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
context->GraphicsStreamPaused = NULL;
context->GraphicsStreamResumed = NULL;
@ -878,6 +939,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
&encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, encomsp_virtual_channel_init_event);
encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface);
encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface);
encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp);
return 1;

View File

@ -44,9 +44,6 @@ int remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
if (!remdesk)
return -1;
printf("RemdeskWrite (%d)\n", Stream_Length(s));
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
@ -176,8 +173,6 @@ int remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UI
int remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
printf("RemdeskServerAnnounce\n");
return 1;
}
@ -192,9 +187,6 @@ int remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDES
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
printf("RemdeskVersionInfo: versionMajor: 0x%04X versionMinor: 0x%04X\n",
versionMajor, versionMinor);
return 1;
}
@ -233,7 +225,7 @@ int remdesk_recv_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_
*pResult = result;
printf("RemdeskRecvResult: 0x%04X\n", result);
//printf("RemdeskRecvResult: 0x%04X\n", result);
return 1;
}
@ -404,7 +396,7 @@ int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEA
Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */
printf("msgType: %d\n", msgType);
//printf("msgType: %d\n", msgType);
switch (msgType)
{
@ -482,8 +474,10 @@ int remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
int status = 1;
REMDESK_CHANNEL_HEADER header;
#if 0
printf("RemdeskReceive: %d\n", Stream_GetRemainingLength(s));
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
#endif
remdesk_read_channel_header(s, &header);
@ -521,8 +515,6 @@ int remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
static void remdesk_process_connect(remdeskPlugin* remdesk)
{
printf("RemdeskProcessConnect\n");
remdesk->settings = (rdpSettings*) remdesk->channelEntryPoints.pExtendedData;
}
@ -803,6 +795,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, remdesk_virtual_channel_init_event);
remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface);
remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface);
remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk);
return 1;

View File

@ -40,6 +40,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
{
xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
xf_encomsp_init(xfc, (EncomspClientContext*) e->pInterface);
}
}
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
@ -54,4 +58,8 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect
{
xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
xf_encomsp_uninit(xfc, (EncomspClientContext*) e->pInterface);
}
}

View File

@ -24,6 +24,7 @@
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);

View File

@ -468,7 +468,7 @@ void xf_create_window(xfContext *xfc)
}
}
void xf_toggle_fullscreen(xfContext *xfc)
void xf_toggle_fullscreen(xfContext* xfc)
{
Pixmap contents = 0;
WindowStateChangeEventArgs e;
@ -486,6 +486,53 @@ void xf_toggle_fullscreen(xfContext *xfc)
PubSub_OnWindowStateChange(((rdpContext *) xfc)->pubSub, xfc, &e);
}
void xf_toggle_control(xfContext* xfc)
{
EncomspClientContext* encomsp;
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
encomsp = xfc->encomsp;
if (!encomsp)
return;
pdu.ParticipantId = 0;
pdu.Flags = ENCOMSP_REQUEST_VIEW;
if (!xfc->controlToggle)
pdu.Flags |= ENCOMSP_REQUEST_INTERACT;
encomsp->ChangeParticipantControlLevel(encomsp, &pdu);
xfc->controlToggle = !xfc->controlToggle;
}
int xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated)
{
#if 0
xfContext* xfc = (xfContext*) context->custom;
printf("ParticipantCreated: ParticipantId: %d GroupId: %d Flags: 0x%04X xfc: %p\n",
(int) participantCreated->ParticipantId, (int) participantCreated->GroupId,
(int) participantCreated->Flags, xfc);
#endif
return 1;
}
void xf_encomsp_init(xfContext* xfc, EncomspClientContext* encomsp)
{
xfc->encomsp = encomsp;
encomsp->custom = (void*) xfc;
encomsp->ParticipantCreated = xf_encomsp_participant_created;
}
void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp)
{
xfc->encomsp = NULL;
}
void xf_lock_x11(xfContext *xfc, BOOL display)
{
if(!xfc->UseXThreads)

View File

@ -415,6 +415,16 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
}
}
if ((keysym == XK_c) || (keysym == XK_C))
{
if (mod.Ctrl && mod.Alt)
{
/* Ctrl-Alt-C: toggle control */
xf_toggle_control(xfc);
return TRUE;
}
}
if (keysym == XK_period)
{
if (mod.Ctrl && mod.Alt)

View File

@ -137,6 +137,7 @@ struct xf_context
BOOL mouse_active;
BOOL suppress_output;
BOOL fullscreen_toggle;
BOOL controlToggle;
UINT32 KeyboardLayout;
BOOL KeyboardState[256];
XModifierKeymap* modifierMap;
@ -182,12 +183,17 @@ struct xf_context
/* Channels */
RdpeiClientContext* rdpei;
RdpgfxClientContext* gfx;
EncomspClientContext* encomsp;
};
void xf_create_window(xfContext* xfc);
void xf_toggle_fullscreen(xfContext* xfc);
void xf_toggle_control(xfContext* xfc);
BOOL xf_post_connect(freerdp* instance);
void xf_encomsp_init(xfContext* xfc, EncomspClientContext* encomsp);
void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp);
enum XF_EXIT_CODE
{
/* section 0-15: protocol-independent codes */

View File

@ -112,7 +112,7 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k
return 1;
}
int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list)
{
int i;
char* p;
@ -120,7 +120,71 @@ int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
char* str;
int count;
int length;
char* list;
char** tokens;
count = 1;
str = _strdup(list);
if (!str)
return -1;
length = strlen(str);
for (i = 0; i < length; i++)
{
if (str[i] == ';')
count++;
}
tokens = (char**) malloc(sizeof(char*) * count);
count = 0;
tokens[count++] = str;
for (i = 0; i < length; i++)
{
if (str[i] == ';')
{
str[i] = '\0';
tokens[count++] = &str[i + 1];
}
}
for (i = 0; i < count; i++)
{
length = strlen(tokens[i]);
if (length > 8)
{
if (strncmp(tokens[i], "169.254.", 8) == 0)
continue;
}
p = tokens[i];
q = strchr(p, ':');
if (!q)
return -1;
q[0] = '\0';
q++;
file->MachineAddress = _strdup(p);
file->MachinePort = (UINT32) atoi(q);
break;
}
return 1;
}
int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
{
int i;
char* str;
int count;
int length;
char* tokens[8];
/**
@ -182,25 +246,7 @@ int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
if (!file->RASpecificParams)
return -1;
list = tokens[2];
q = strchr(list, ';');
if (q)
q[0] = '\0';
p = list;
q = strchr(p, ':');
if (!q)
return -1;
q[0] = '\0';
q++;
file->MachineAddress = _strdup(p);
file->MachinePort = (UINT32) atoi(q);
freerdp_assistance_parse_address_list(file, tokens[2]);
free(str);
@ -374,9 +420,6 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
*((UINT32*) pbIn) = cbPassStubW;
CopyMemory(&pbIn[4], PassStubW, cbPassStubW);
printf("PlainBlob (%d)\n", EncryptedSize);
winpr_HexDump(pbIn, EncryptedSize);
EVP_CIPHER_CTX_init(&rc4Ctx);
status = EVP_EncryptInit_ex(&rc4Ctx, EVP_rc4(), NULL, NULL, NULL);
@ -416,9 +459,6 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
EVP_CIPHER_CTX_cleanup(&rc4Ctx);
printf("EncryptedBlob (%d):\n", EncryptedSize);
winpr_HexDump(pbOut, EncryptedSize);
free(pbIn);
free(PasswordW);
free(PassStubW);