Merge pull request #15 from llyzs/cliprdr
New UI-independent cliprdr implementation using plugin event system.
This commit is contained in:
commit
e10a46ba65
@ -17,5 +17,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
add_subdirectory(cliprdr)
|
||||||
add_subdirectory(rdpdbg)
|
add_subdirectory(rdpdbg)
|
||||||
|
|
||||||
|
33
channels/cliprdr/CMakeLists.txt
Normal file
33
channels/cliprdr/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
# FreeRDP cmake build script
|
||||||
|
#
|
||||||
|
# Copyright 2011 O.S. Systems Software Ltda.
|
||||||
|
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||||
|
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set(CLIPRDR_SRCS
|
||||||
|
cliprdr_constants.h
|
||||||
|
cliprdr_format.c
|
||||||
|
cliprdr_format.h
|
||||||
|
cliprdr_main.c
|
||||||
|
cliprdr_main.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(cliprdr SHARED ${CLIPRDR_SRCS})
|
||||||
|
set_target_properties(cliprdr PROPERTIES PREFIX "")
|
||||||
|
|
||||||
|
target_link_libraries(cliprdr freerdp-utils)
|
||||||
|
|
||||||
|
install(TARGETS cliprdr DESTINATION ${FREERDP_PLUGIN_PATH})
|
58
channels/cliprdr/cliprdr_constants.h
Normal file
58
channels/cliprdr/cliprdr_constants.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Clipboard Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Jay Sorg
|
||||||
|
* Copyright 2010-2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLIPRDR_CONSTANTS
|
||||||
|
#define __CLIPRDR_CONSTANTS
|
||||||
|
|
||||||
|
/* CLIPRDR_HEADER.msgType */
|
||||||
|
#define CB_MONITOR_READY 1
|
||||||
|
#define CB_FORMAT_LIST 2
|
||||||
|
#define CB_FORMAT_LIST_RESPONSE 3
|
||||||
|
#define CB_FORMAT_DATA_REQUEST 4
|
||||||
|
#define CB_FORMAT_DATA_RESPONSE 5
|
||||||
|
#define CB_TEMP_DIRECTORY 6
|
||||||
|
#define CB_CLIP_CAPS 7
|
||||||
|
#define CB_FILECONTENTS_REQUEST 8
|
||||||
|
#define CB_FILECONTENTS_RESPONSE 9
|
||||||
|
#define CB_LOCK_CLIPDATA 10
|
||||||
|
#define CB_UNLOCK_CLIPDATA 11
|
||||||
|
|
||||||
|
/* CLIPRDR_HEADER.msgFlags */
|
||||||
|
#define CB_RESPONSE_OK 1
|
||||||
|
#define CB_RESPONSE_FAIL 2
|
||||||
|
#define CB_ASCII_NAMES 4
|
||||||
|
|
||||||
|
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||||
|
#define CB_CAPSTYPE_GENERAL 1
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||||
|
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||||
|
#define CB_CAPS_VERSION_1 1
|
||||||
|
#define CB_CAPS_VERSION_2 2
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||||
|
#define CB_USE_LONG_FORMAT_NAMES 2
|
||||||
|
#define CB_STREAM_FILECLIP_ENABLED 4
|
||||||
|
#define CB_FILECLIP_NO_FILE_PATHS 8
|
||||||
|
#define CB_CAN_LOCK_CLIPDATA 16
|
||||||
|
|
||||||
|
#endif /* __CLIPRDR_CONSTANTS */
|
172
channels/cliprdr/cliprdr_format.c
Normal file
172
channels/cliprdr/cliprdr_format.c
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Clipboard Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Jay Sorg
|
||||||
|
* Copyright 2010-2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <freerdp/constants.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
|
|
||||||
|
#include "cliprdr_constants.h"
|
||||||
|
#include "cliprdr_main.h"
|
||||||
|
#include "cliprdr_format.h"
|
||||||
|
|
||||||
|
#define CFSTR_HTML "H\0T\0M\0L\0 \0F\0o\0r\0m\0a\0t\0\0"
|
||||||
|
#define CFSTR_PNG "P\0N\0G\0\0"
|
||||||
|
#define CFSTR_JPEG "J\0F\0I\0F\0\0"
|
||||||
|
#define CFSTR_GIF "G\0I\0F\0\0"
|
||||||
|
|
||||||
|
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LIST_EVENT* cb_event)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
data_out = cliprdr_packet_new(CB_FORMAT_LIST, 0, 36 * cb_event->num_formats);
|
||||||
|
|
||||||
|
for (i = 0; i < cb_event->num_formats; i++)
|
||||||
|
{
|
||||||
|
stream_write_uint32(data_out, cb_event->formats[i]);
|
||||||
|
switch (cb_event->formats[i])
|
||||||
|
{
|
||||||
|
case CB_FORMAT_HTML:
|
||||||
|
memcpy(stream_get_tail(data_out), CFSTR_HTML, sizeof(CFSTR_HTML));
|
||||||
|
break;
|
||||||
|
case CB_FORMAT_PNG:
|
||||||
|
memcpy(stream_get_tail(data_out), CFSTR_PNG, sizeof(CFSTR_PNG));
|
||||||
|
break;
|
||||||
|
case CB_FORMAT_JPEG:
|
||||||
|
memcpy(stream_get_tail(data_out), CFSTR_JPEG, sizeof(CFSTR_JPEG));
|
||||||
|
break;
|
||||||
|
case CB_FORMAT_GIF:
|
||||||
|
memcpy(stream_get_tail(data_out), CFSTR_GIF, sizeof(CFSTR_GIF));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream_seek(data_out, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_send_format_list_response(cliprdrPlugin* cliprdr)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
|
||||||
|
data_out = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0);
|
||||||
|
cliprdr_packet_send(cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen)
|
||||||
|
{
|
||||||
|
FRDP_CB_FORMAT_LIST_EVENT* cb_event;
|
||||||
|
uint32 format;
|
||||||
|
int num_formats;
|
||||||
|
int supported;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cb_event = (FRDP_CB_FORMAT_LIST_EVENT*)freerdp_event_new(FRDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL);
|
||||||
|
num_formats = dataLen / 36;
|
||||||
|
cb_event->formats = (uint32*)xmalloc(sizeof(uint32) * num_formats);
|
||||||
|
cb_event->num_formats = 0;
|
||||||
|
if (num_formats * 36 != dataLen)
|
||||||
|
DEBUG_WARN("dataLen %d not devided by 36!");
|
||||||
|
for (i = 0; i < num_formats; i++)
|
||||||
|
{
|
||||||
|
stream_read_uint32(data_in, format);
|
||||||
|
supported = 1;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case CB_FORMAT_TEXT:
|
||||||
|
case CB_FORMAT_DIB:
|
||||||
|
case CB_FORMAT_UNICODETEXT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (memcmp(stream_get_tail(data_in), CFSTR_HTML, sizeof(CFSTR_HTML)) == 0)
|
||||||
|
{
|
||||||
|
format = CB_FORMAT_HTML;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memcmp(stream_get_tail(data_in), CFSTR_PNG, sizeof(CFSTR_PNG)) == 0)
|
||||||
|
{
|
||||||
|
format = CB_FORMAT_PNG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memcmp(stream_get_tail(data_in), CFSTR_JPEG, sizeof(CFSTR_JPEG)) == 0)
|
||||||
|
{
|
||||||
|
format = CB_FORMAT_JPEG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memcmp(stream_get_tail(data_in), CFSTR_GIF, sizeof(CFSTR_GIF)) == 0)
|
||||||
|
{
|
||||||
|
format = CB_FORMAT_GIF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
supported = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream_seek(data_in, 32);
|
||||||
|
|
||||||
|
if (supported)
|
||||||
|
cb_event->formats[cb_event->num_formats++] = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (FRDP_EVENT*)cb_event);
|
||||||
|
cliprdr_send_format_list_response(cliprdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* data_in)
|
||||||
|
{
|
||||||
|
FRDP_CB_DATA_REQUEST_EVENT* cb_event;
|
||||||
|
|
||||||
|
cb_event = (FRDP_CB_DATA_REQUEST_EVENT*)freerdp_event_new(FRDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL);
|
||||||
|
stream_read_uint32(data_in, cb_event->format);
|
||||||
|
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (FRDP_EVENT*)cb_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
|
||||||
|
data_out = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_OK, cb_event->size);
|
||||||
|
stream_write(data_out, cb_event->data, cb_event->size);
|
||||||
|
cliprdr_packet_send(cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_REQUEST_EVENT* cb_event)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
|
||||||
|
data_out = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
|
||||||
|
stream_write_uint32(data_out, cb_event->format);
|
||||||
|
cliprdr_packet_send(cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen)
|
||||||
|
{
|
||||||
|
FRDP_CB_DATA_RESPONSE_EVENT* cb_event;
|
||||||
|
|
||||||
|
cb_event = (FRDP_CB_DATA_RESPONSE_EVENT*)freerdp_event_new(FRDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL);
|
||||||
|
cb_event->size = dataLen;
|
||||||
|
cb_event->data = (uint8*)xmalloc(dataLen);
|
||||||
|
memcpy(cb_event->data, stream_get_tail(data_in), dataLen);
|
||||||
|
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (FRDP_EVENT*)cb_event);
|
||||||
|
}
|
33
channels/cliprdr/cliprdr_format.h
Normal file
33
channels/cliprdr/cliprdr_format.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Clipboard Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Jay Sorg
|
||||||
|
* Copyright 2010-2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLIPRDR_FORMAT_H
|
||||||
|
#define __CLIPRDR_FORMAT_H
|
||||||
|
|
||||||
|
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LIST_EVENT* cb_event);
|
||||||
|
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen);
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* data_in);
|
||||||
|
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event);
|
||||||
|
|
||||||
|
void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_REQUEST_EVENT* cb_event);
|
||||||
|
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen);
|
||||||
|
|
||||||
|
#endif /* __CLIPRDR_FORMAT_H */
|
193
channels/cliprdr/cliprdr_main.c
Normal file
193
channels/cliprdr/cliprdr_main.c
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Clipboard Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Jay Sorg
|
||||||
|
* Copyright 2010-2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <freerdp/constants.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
|
|
||||||
|
#include "cliprdr_constants.h"
|
||||||
|
#include "cliprdr_main.h"
|
||||||
|
#include "cliprdr_format.h"
|
||||||
|
|
||||||
|
STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
|
||||||
|
data_out = stream_new(dataLen + 8);
|
||||||
|
stream_write_uint16(data_out, msgType);
|
||||||
|
stream_write_uint16(data_out, msgFlags);
|
||||||
|
/* Write actual length after the entire packet has been constructed. */
|
||||||
|
stream_seek(data_out, 4);
|
||||||
|
|
||||||
|
return data_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* data_out)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
uint32 dataLen;
|
||||||
|
|
||||||
|
pos = stream_get_pos(data_out);
|
||||||
|
dataLen = pos - 8;
|
||||||
|
stream_set_pos(data_out, 4);
|
||||||
|
stream_write_uint32(data_out, dataLen);
|
||||||
|
stream_set_pos(data_out, pos);
|
||||||
|
|
||||||
|
svc_plugin_send((rdpSvcPlugin*)cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_connect(rdpSvcPlugin* plugin)
|
||||||
|
{
|
||||||
|
DEBUG_SVC("connecting");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* data_in)
|
||||||
|
{
|
||||||
|
uint16 cCapabilitiesSets;
|
||||||
|
|
||||||
|
stream_read_uint16(data_in, cCapabilitiesSets);
|
||||||
|
DEBUG_SVC("cCapabilitiesSets %d", cCapabilitiesSets);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
|
||||||
|
{
|
||||||
|
STREAM* data_out;
|
||||||
|
|
||||||
|
data_out = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
|
||||||
|
|
||||||
|
stream_write_uint16(data_out, 1); /* cCapabilitiesSets */
|
||||||
|
stream_write_uint16(data_out, 0); /* pad1 */
|
||||||
|
stream_write_uint16(data_out, CB_CAPSTYPE_GENERAL); /* capabilitySetType */
|
||||||
|
stream_write_uint16(data_out, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */
|
||||||
|
stream_write_uint32(data_out, CB_CAPS_VERSION_2); /* version */
|
||||||
|
stream_write_uint32(data_out, 0); /* generalFlags */
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr)
|
||||||
|
{
|
||||||
|
FRDP_EVENT* event;
|
||||||
|
|
||||||
|
cliprdr_send_clip_caps(cliprdr);
|
||||||
|
|
||||||
|
event = freerdp_event_new(FRDP_EVENT_TYPE_CB_SYNC, NULL, NULL);
|
||||||
|
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||||
|
{
|
||||||
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*)plugin;
|
||||||
|
uint16 msgType;
|
||||||
|
uint16 msgFlags;
|
||||||
|
uint32 dataLen;
|
||||||
|
|
||||||
|
stream_read_uint16(data_in, msgType);
|
||||||
|
stream_read_uint16(data_in, msgFlags);
|
||||||
|
stream_read_uint32(data_in, dataLen);
|
||||||
|
|
||||||
|
DEBUG_SVC("msgType %d msgFlags %d dataLen %d", msgType, msgFlags, dataLen);
|
||||||
|
|
||||||
|
switch (msgType)
|
||||||
|
{
|
||||||
|
case CB_CLIP_CAPS:
|
||||||
|
cliprdr_process_clip_caps(cliprdr, data_in);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_MONITOR_READY:
|
||||||
|
cliprdr_process_monitor_ready(cliprdr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_FORMAT_LIST:
|
||||||
|
cliprdr_process_format_list(cliprdr, data_in, dataLen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_FORMAT_LIST_RESPONSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_FORMAT_DATA_REQUEST:
|
||||||
|
cliprdr_process_format_data_request(cliprdr, data_in);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_FORMAT_DATA_RESPONSE:
|
||||||
|
cliprdr_process_format_data_response(cliprdr, data_in, dataLen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_WARN("unknown msgType %d", msgType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_free(data_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
||||||
|
{
|
||||||
|
switch (event->event_type)
|
||||||
|
{
|
||||||
|
case FRDP_EVENT_TYPE_CB_FORMAT_LIST:
|
||||||
|
cliprdr_process_format_list_event((cliprdrPlugin*)plugin, (FRDP_CB_FORMAT_LIST_EVENT*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRDP_EVENT_TYPE_CB_DATA_REQUEST:
|
||||||
|
cliprdr_process_format_data_request_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_REQUEST_EVENT*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRDP_EVENT_TYPE_CB_DATA_RESPONSE:
|
||||||
|
cliprdr_process_format_data_response_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_RESPONSE_EVENT*)event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_WARN("unknown event type %d", event->event_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
freerdp_event_free(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_process_terminate(rdpSvcPlugin* plugin)
|
||||||
|
{
|
||||||
|
xfree(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||||
|
{
|
||||||
|
cliprdrPlugin* cliprdr;
|
||||||
|
|
||||||
|
cliprdr = (cliprdrPlugin*)xmalloc(sizeof(cliprdrPlugin));
|
||||||
|
memset(cliprdr, 0, sizeof(cliprdrPlugin));
|
||||||
|
|
||||||
|
cliprdr->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED |
|
||||||
|
CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP |
|
||||||
|
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||||
|
strcpy(cliprdr->plugin.channel_def.name, "cliprdr");
|
||||||
|
|
||||||
|
cliprdr->plugin.connect_callback = cliprdr_process_connect;
|
||||||
|
cliprdr->plugin.receive_callback = cliprdr_process_receive;
|
||||||
|
cliprdr->plugin.event_callback = cliprdr_process_event;
|
||||||
|
cliprdr->plugin.terminate_callback = cliprdr_process_terminate;
|
||||||
|
|
||||||
|
svc_plugin_init((rdpSvcPlugin*)cliprdr, pEntryPoints);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
35
channels/cliprdr/cliprdr_main.h
Normal file
35
channels/cliprdr/cliprdr_main.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Clipboard Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Jay Sorg
|
||||||
|
* Copyright 2010-2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLIPRDR_MAIN_H
|
||||||
|
#define __CLIPRDR_MAIN_H
|
||||||
|
|
||||||
|
#include <freerdp/utils/stream.h>
|
||||||
|
|
||||||
|
typedef struct cliprdr_plugin cliprdrPlugin;
|
||||||
|
struct cliprdr_plugin
|
||||||
|
{
|
||||||
|
rdpSvcPlugin plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen);
|
||||||
|
void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* data_out);
|
||||||
|
|
||||||
|
#endif /* __CLIPRDR_MAIN_H */
|
@ -34,14 +34,14 @@ struct rdpdbg_plugin
|
|||||||
|
|
||||||
static void rdpdbg_process_connect(rdpSvcPlugin* plugin)
|
static void rdpdbg_process_connect(rdpSvcPlugin* plugin)
|
||||||
{
|
{
|
||||||
printf("rdpdbg_process_connect\n");
|
DEBUG_WARN("connecting");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||||
{
|
{
|
||||||
STREAM* data_out;
|
STREAM* data_out;
|
||||||
|
|
||||||
printf("rdpdbg_process_receive: size %d\n", stream_get_size(data_in));
|
DEBUG_WARN("size %d", stream_get_size(data_in));
|
||||||
stream_free(data_in);
|
stream_free(data_in);
|
||||||
|
|
||||||
data_out = stream_new(8);
|
data_out = stream_new(8);
|
||||||
@ -51,7 +51,7 @@ static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
|||||||
|
|
||||||
static void rdpdbg_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
static void rdpdbg_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
||||||
{
|
{
|
||||||
printf("rdpdbg_process_event: event_type %d\n", event->event_type);
|
DEBUG_WARN("event_type %d", event->event_type);
|
||||||
freerdp_event_free(event);
|
freerdp_event_free(event);
|
||||||
|
|
||||||
event = freerdp_event_new(FRDP_EVENT_TYPE_DEBUG, NULL, NULL);
|
event = freerdp_event_new(FRDP_EVENT_TYPE_DEBUG, NULL, NULL);
|
||||||
@ -60,7 +60,7 @@ static void rdpdbg_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
|||||||
|
|
||||||
static void rdpdbg_process_terminate(rdpSvcPlugin* plugin)
|
static void rdpdbg_process_terminate(rdpSvcPlugin* plugin)
|
||||||
{
|
{
|
||||||
printf("rdpdbg_process_terminate\n");
|
DEBUG_WARN("terminating");
|
||||||
xfree(plugin);
|
xfree(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#ifndef __CONFIG_H
|
||||||
|
#define __CONFIG_H
|
||||||
|
|
||||||
/* Include files */
|
/* Include files */
|
||||||
#cmakedefine HAVE_SYS_PARAM_H
|
#cmakedefine HAVE_SYS_PARAM_H
|
||||||
#cmakedefine HAVE_SYS_SOCKET_H
|
#cmakedefine HAVE_SYS_SOCKET_H
|
||||||
@ -12,3 +15,5 @@
|
|||||||
#cmakedefine WITH_DEBUG_TRANSPORT
|
#cmakedefine WITH_DEBUG_TRANSPORT
|
||||||
#cmakedefine WITH_DEBUG_CHANMAN
|
#cmakedefine WITH_DEBUG_CHANMAN
|
||||||
#cmakedefine WITH_DEBUG_SVC
|
#cmakedefine WITH_DEBUG_SVC
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -47,6 +47,8 @@ add_executable(test_freerdp
|
|||||||
test_transport.h
|
test_transport.h
|
||||||
test_chanman.c
|
test_chanman.c
|
||||||
test_chanman.h
|
test_chanman.h
|
||||||
|
test_cliprdr.c
|
||||||
|
test_cliprdr.h
|
||||||
test_freerdp.c
|
test_freerdp.c
|
||||||
test_freerdp.h)
|
test_freerdp.h)
|
||||||
|
|
||||||
|
@ -71,16 +71,20 @@ void test_chanman(void)
|
|||||||
freerdp_chanman_post_connect(chan_man, &inst);
|
freerdp_chanman_post_connect(chan_man, &inst);
|
||||||
|
|
||||||
freerdp_chanman_data(&inst, 0, "testdata", 8, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 8);
|
freerdp_chanman_data(&inst, 0, "testdata", 8, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 8);
|
||||||
|
freerdp_chanman_data(&inst, 0, "testdata1", 9, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 9);
|
||||||
freerdp_chanman_check_fds(chan_man, &inst);
|
freerdp_chanman_data(&inst, 0, "testdata11", 10, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 10);
|
||||||
|
freerdp_chanman_data(&inst, 0, "testdata111", 11, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 11);
|
||||||
|
|
||||||
event = freerdp_event_new(FRDP_EVENT_TYPE_DEBUG, NULL, NULL);
|
event = freerdp_event_new(FRDP_EVENT_TYPE_DEBUG, NULL, NULL);
|
||||||
freerdp_chanman_send_event(chan_man, "rdpdbg", event);
|
freerdp_chanman_send_event(chan_man, "rdpdbg", event);
|
||||||
|
|
||||||
event = freerdp_chanman_pop_event(chan_man);
|
while ((event = freerdp_chanman_pop_event(chan_man)) == NULL)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
printf("responded event_type %d\n", event->event_type);
|
printf("responded event_type %d\n", event->event_type);
|
||||||
freerdp_event_free(event);
|
freerdp_event_free(event);
|
||||||
|
|
||||||
freerdp_chanman_close(chan_man, NULL);
|
freerdp_chanman_close(chan_man, &inst);
|
||||||
freerdp_chanman_free(chan_man);
|
freerdp_chanman_free(chan_man);
|
||||||
}
|
}
|
||||||
|
246
cunit/test_cliprdr.c
Normal file
246
cunit/test_cliprdr.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* Clipboard Virtual Channel Unit Tests
|
||||||
|
*
|
||||||
|
* Copyright 2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <freerdp/constants.h>
|
||||||
|
#include <freerdp/chanman.h>
|
||||||
|
#include <freerdp/utils/event.h>
|
||||||
|
#include <freerdp/utils/hexdump.h>
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
|
||||||
|
#include "test_cliprdr.h"
|
||||||
|
|
||||||
|
int init_cliprdr_suite(void)
|
||||||
|
{
|
||||||
|
freerdp_chanman_global_init();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clean_cliprdr_suite(void)
|
||||||
|
{
|
||||||
|
freerdp_chanman_global_uninit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_cliprdr_suite(void)
|
||||||
|
{
|
||||||
|
add_test_suite(cliprdr);
|
||||||
|
|
||||||
|
add_test_function(cliprdr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8 test_clip_caps_data[] =
|
||||||
|
{
|
||||||
|
"\x07\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x01\x00\x0C\x00"
|
||||||
|
"\x02\x00\x00\x00\x0E\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 test_monitor_ready_data[] =
|
||||||
|
{
|
||||||
|
"\x01\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 test_format_list_data[] =
|
||||||
|
{
|
||||||
|
"\x02\x00\x00\x00\x48\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\xd0\x00\x00"
|
||||||
|
"\x48\x00\x54\x00\x4D\x00\x4C\x00\x20\x00\x46\x00\x6F\x00\x72\x00"
|
||||||
|
"\x6D\x00\x61\x00\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 test_format_list_response_data[] =
|
||||||
|
{
|
||||||
|
"\x03\x00\x01\x00\x00\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 test_data_request_data[] =
|
||||||
|
{
|
||||||
|
"\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 test_data_response_data[] =
|
||||||
|
{
|
||||||
|
"\x05\x00\x01\x00\x18\x00\x00\x00\x68\x00\x65\x00\x6C\x00\x6C\x00"
|
||||||
|
"\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6c\x00\x64\x00\x00\x00"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int test_rdp_channel_data(rdpInst* inst, int chan_id, char* data, int data_size)
|
||||||
|
{
|
||||||
|
printf("chan_id %d data_size %d\n", chan_id, data_size);
|
||||||
|
freerdp_hexdump(data, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int event_processed;
|
||||||
|
|
||||||
|
static void event_process_callback(FRDP_EVENT* event)
|
||||||
|
{
|
||||||
|
printf("Event %d processed.\n", event->event_type);
|
||||||
|
event_processed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cliprdr(void)
|
||||||
|
{
|
||||||
|
rdpChanMan* chan_man;
|
||||||
|
rdpSettings settings = { 0 };
|
||||||
|
rdpInst inst = { 0 };
|
||||||
|
FRDP_EVENT* event;
|
||||||
|
FRDP_CB_FORMAT_LIST_EVENT* format_list_event;
|
||||||
|
FRDP_CB_DATA_REQUEST_EVENT* data_request_event;
|
||||||
|
FRDP_CB_DATA_RESPONSE_EVENT* data_response_event;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
settings.hostname = "testhost";
|
||||||
|
inst.settings = &settings;
|
||||||
|
inst.rdp_channel_data = test_rdp_channel_data;
|
||||||
|
|
||||||
|
chan_man = freerdp_chanman_new();
|
||||||
|
|
||||||
|
freerdp_chanman_load_plugin(chan_man, &settings, "../channels/cliprdr/cliprdr.so", NULL);
|
||||||
|
freerdp_chanman_pre_connect(chan_man, &inst);
|
||||||
|
freerdp_chanman_post_connect(chan_man, &inst);
|
||||||
|
|
||||||
|
/* server sends cliprdr capabilities and monitor ready PDU */
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_clip_caps_data, sizeof(test_clip_caps_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_clip_caps_data) - 1);
|
||||||
|
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_monitor_ready_data, sizeof(test_monitor_ready_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_monitor_ready_data) - 1);
|
||||||
|
|
||||||
|
/* cliprdr sends clipboard_sync event to UI */
|
||||||
|
while ((event = freerdp_chanman_pop_event(chan_man)) == NULL)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
printf("Got event %d\n", event->event_type);
|
||||||
|
CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_SYNC);
|
||||||
|
freerdp_event_free(event);
|
||||||
|
|
||||||
|
/* UI sends format_list event to cliprdr */
|
||||||
|
event = freerdp_event_new(FRDP_EVENT_TYPE_CB_FORMAT_LIST, event_process_callback, NULL);
|
||||||
|
format_list_event = (FRDP_CB_FORMAT_LIST_EVENT*)event;
|
||||||
|
format_list_event->num_formats = 2;
|
||||||
|
format_list_event->formats = (uint32*)xmalloc(sizeof(uint32) * 2);
|
||||||
|
format_list_event->formats[0] = CB_FORMAT_TEXT;
|
||||||
|
format_list_event->formats[1] = CB_FORMAT_HTML;
|
||||||
|
event_processed = 0;
|
||||||
|
freerdp_chanman_send_event(chan_man, "cliprdr", event);
|
||||||
|
|
||||||
|
/* cliprdr sends format list PDU to server */
|
||||||
|
while (!event_processed)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server sends format list response PDU to cliprdr */
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_format_list_response_data, sizeof(test_format_list_response_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_response_data) - 1);
|
||||||
|
|
||||||
|
/* server sends format list PDU to cliprdr */
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_format_list_data, sizeof(test_format_list_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_data) - 1);
|
||||||
|
|
||||||
|
/* cliprdr sends format_list event to UI */
|
||||||
|
while ((event = freerdp_chanman_pop_event(chan_man)) == NULL)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
printf("Got event %d\n", event->event_type);
|
||||||
|
CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_FORMAT_LIST);
|
||||||
|
if (event->event_type == FRDP_EVENT_TYPE_CB_FORMAT_LIST)
|
||||||
|
{
|
||||||
|
format_list_event = (FRDP_CB_FORMAT_LIST_EVENT*)event;
|
||||||
|
for (i = 0; i < format_list_event->num_formats; i++)
|
||||||
|
printf("Format: 0x%X\n", format_list_event->formats[i]);
|
||||||
|
}
|
||||||
|
freerdp_event_free(event);
|
||||||
|
|
||||||
|
/* server sends data request PDU to cliprdr */
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_data_request_data, sizeof(test_data_request_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_request_data) - 1);
|
||||||
|
|
||||||
|
/* cliprdr sends data request event to UI */
|
||||||
|
while ((event = freerdp_chanman_pop_event(chan_man)) == NULL)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
printf("Got event %d\n", event->event_type);
|
||||||
|
CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_DATA_REQUEST);
|
||||||
|
if (event->event_type == FRDP_EVENT_TYPE_CB_DATA_REQUEST)
|
||||||
|
{
|
||||||
|
data_request_event = (FRDP_CB_DATA_REQUEST_EVENT*)event;
|
||||||
|
printf("Requested format: 0x%X\n", data_request_event->format);
|
||||||
|
}
|
||||||
|
freerdp_event_free(event);
|
||||||
|
|
||||||
|
/* UI sends data response event to cliprdr */
|
||||||
|
event = freerdp_event_new(FRDP_EVENT_TYPE_CB_DATA_RESPONSE, event_process_callback, NULL);
|
||||||
|
data_response_event = (FRDP_CB_DATA_RESPONSE_EVENT*)event;
|
||||||
|
data_response_event->data = (uint8*)xmalloc(6);
|
||||||
|
strcpy(data_response_event->data, "hello");
|
||||||
|
data_response_event->size = 6;
|
||||||
|
event_processed = 0;
|
||||||
|
freerdp_chanman_send_event(chan_man, "cliprdr", event);
|
||||||
|
|
||||||
|
/* cliprdr sends data response PDU to server */
|
||||||
|
while (!event_processed)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UI sends data request event to cliprdr */
|
||||||
|
event = freerdp_event_new(FRDP_EVENT_TYPE_CB_DATA_REQUEST, event_process_callback, NULL);
|
||||||
|
data_request_event = (FRDP_CB_DATA_REQUEST_EVENT*)event;
|
||||||
|
data_request_event->format = CB_FORMAT_UNICODETEXT;
|
||||||
|
event_processed = 0;
|
||||||
|
freerdp_chanman_send_event(chan_man, "cliprdr", event);
|
||||||
|
|
||||||
|
/* cliprdr sends data request PDU to server */
|
||||||
|
while (!event_processed)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server sends data response PDU to cliprdr */
|
||||||
|
freerdp_chanman_data(&inst, 0, (char*)test_data_response_data, sizeof(test_data_response_data) - 1,
|
||||||
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_response_data) - 1);
|
||||||
|
|
||||||
|
/* cliprdr sends data response event to UI */
|
||||||
|
while ((event = freerdp_chanman_pop_event(chan_man)) == NULL)
|
||||||
|
{
|
||||||
|
freerdp_chanman_check_fds(chan_man, &inst);
|
||||||
|
}
|
||||||
|
printf("Got event %d\n", event->event_type);
|
||||||
|
CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_DATA_RESPONSE);
|
||||||
|
if (event->event_type == FRDP_EVENT_TYPE_CB_DATA_RESPONSE)
|
||||||
|
{
|
||||||
|
data_response_event = (FRDP_CB_DATA_RESPONSE_EVENT*)event;
|
||||||
|
printf("Data response size: %d\n", data_response_event->size);
|
||||||
|
freerdp_hexdump(data_response_event->data, data_response_event->size);
|
||||||
|
}
|
||||||
|
freerdp_event_free(event);
|
||||||
|
|
||||||
|
freerdp_chanman_close(chan_man, &inst);
|
||||||
|
freerdp_chanman_free(chan_man);
|
||||||
|
}
|
26
cunit/test_cliprdr.h
Normal file
26
cunit/test_cliprdr.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* Clipboard Virtual Channel Unit Tests
|
||||||
|
*
|
||||||
|
* Copyright 2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_freerdp.h"
|
||||||
|
|
||||||
|
int init_cliprdr_suite(void);
|
||||||
|
int clean_cliprdr_suite(void);
|
||||||
|
int add_cliprdr_suite(void);
|
||||||
|
|
||||||
|
void test_cliprdr(void);
|
@ -31,6 +31,7 @@
|
|||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
#include "test_transport.h"
|
#include "test_transport.h"
|
||||||
#include "test_chanman.h"
|
#include "test_chanman.h"
|
||||||
|
#include "test_cliprdr.h"
|
||||||
#include "test_freerdp.h"
|
#include "test_freerdp.h"
|
||||||
|
|
||||||
void dump_data(unsigned char * p, int len, int width, char* name)
|
void dump_data(unsigned char * p, int len, int width, char* name)
|
||||||
@ -123,6 +124,7 @@ int main(int argc, char* argv[])
|
|||||||
add_utils_suite();
|
add_utils_suite();
|
||||||
add_transport_suite();
|
add_transport_suite();
|
||||||
add_chanman_suite();
|
add_chanman_suite();
|
||||||
|
add_cliprdr_suite();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -160,6 +162,10 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
add_chanman_suite();
|
add_chanman_suite();
|
||||||
}
|
}
|
||||||
|
else if (strcmp("cliprdr", argv[*pindex]) == 0)
|
||||||
|
{
|
||||||
|
add_cliprdr_suite();
|
||||||
|
}
|
||||||
else if (strcmp("per", argv[*pindex]) == 0)
|
else if (strcmp("per", argv[*pindex]) == 0)
|
||||||
{
|
{
|
||||||
add_per_suite();
|
add_per_suite();
|
||||||
|
@ -99,7 +99,26 @@ enum FRDP_EVENT_TYPE
|
|||||||
{
|
{
|
||||||
FRDP_EVENT_TYPE_DEBUG = 0,
|
FRDP_EVENT_TYPE_DEBUG = 0,
|
||||||
FRDP_EVENT_TYPE_VIDEO_FRAME = 1,
|
FRDP_EVENT_TYPE_VIDEO_FRAME = 1,
|
||||||
FRDP_EVENT_TYPE_REDRAW = 2
|
FRDP_EVENT_TYPE_REDRAW = 2,
|
||||||
|
FRDP_EVENT_TYPE_CB_SYNC = 3,
|
||||||
|
FRDP_EVENT_TYPE_CB_FORMAT_LIST = 4,
|
||||||
|
FRDP_EVENT_TYPE_CB_DATA_REQUEST = 5,
|
||||||
|
FRDP_EVENT_TYPE_CB_DATA_RESPONSE = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clipboard Formats
|
||||||
|
*/
|
||||||
|
enum FRDP_CB_FORMAT
|
||||||
|
{
|
||||||
|
CB_FORMAT_RAW = 0,
|
||||||
|
CB_FORMAT_TEXT = 1,
|
||||||
|
CB_FORMAT_DIB = 8,
|
||||||
|
CB_FORMAT_UNICODETEXT = 13,
|
||||||
|
CB_FORMAT_HTML = 0xD010,
|
||||||
|
CB_FORMAT_PNG = 0xD011,
|
||||||
|
CB_FORMAT_JPEG = 0xD012,
|
||||||
|
CB_FORMAT_GIF = 0xD013
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -164,6 +164,31 @@ struct _FRDP_REDRAW_EVENT
|
|||||||
};
|
};
|
||||||
typedef struct _FRDP_REDRAW_EVENT FRDP_REDRAW_EVENT;
|
typedef struct _FRDP_REDRAW_EVENT FRDP_REDRAW_EVENT;
|
||||||
|
|
||||||
|
typedef FRDP_EVENT FRDP_CB_SYNC_EVENT;
|
||||||
|
|
||||||
|
struct _FRDP_CB_FORMAT_LIST_EVENT
|
||||||
|
{
|
||||||
|
FRDP_EVENT event;
|
||||||
|
uint32* formats;
|
||||||
|
uint16 num_formats;
|
||||||
|
};
|
||||||
|
typedef struct _FRDP_CB_FORMAT_LIST_EVENT FRDP_CB_FORMAT_LIST_EVENT;
|
||||||
|
|
||||||
|
struct _FRDP_CB_DATA_REQUEST_EVENT
|
||||||
|
{
|
||||||
|
FRDP_EVENT event;
|
||||||
|
uint32 format;
|
||||||
|
};
|
||||||
|
typedef struct _FRDP_CB_DATA_REQUEST_EVENT FRDP_CB_DATA_REQUEST_EVENT;
|
||||||
|
|
||||||
|
struct _FRDP_CB_DATA_RESPONSE_EVENT
|
||||||
|
{
|
||||||
|
FRDP_EVENT event;
|
||||||
|
uint8* data;
|
||||||
|
uint32 size;
|
||||||
|
};
|
||||||
|
typedef struct _FRDP_CB_DATA_RESPONSE_EVENT FRDP_CB_DATA_RESPONSE_EVENT;
|
||||||
|
|
||||||
typedef struct rdp_inst rdpInst;
|
typedef struct rdp_inst rdpInst;
|
||||||
|
|
||||||
#endif /* __RDP_TYPES_H */
|
#endif /* __RDP_TYPES_H */
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
#ifndef __UTILS_DEBUG_H
|
#ifndef __UTILS_DEBUG_H
|
||||||
#define __UTILS_DEBUG_H
|
#define __UTILS_DEBUG_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_DEBUG_ASSERT
|
#ifdef WITH_DEBUG_ASSERT
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -36,6 +34,7 @@
|
|||||||
#define DEBUG_NULL(fmt, ...) do { } while (0)
|
#define DEBUG_NULL(fmt, ...) do { } while (0)
|
||||||
#define DEBUG_PRINT(_dbg_str, fmt, ...) printf(_dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
|
#define DEBUG_PRINT(_dbg_str, fmt, ...) printf(_dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
|
||||||
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
|
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
|
||||||
|
#define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%d): ", fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
#ifdef WITH_DEBUG
|
#ifdef WITH_DEBUG
|
||||||
#define DEBUG(fmt, ...) DEBUG_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
|
#define DEBUG(fmt, ...) DEBUG_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef __LIST_UTILS_H
|
#ifndef __LIST_UTILS_H
|
||||||
#define __LIST_UTILS_H
|
#define __LIST_UTILS_H
|
||||||
|
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
|
||||||
#define DEFINE_LIST_TYPE(_list_type, _item_type) \
|
#define DEFINE_LIST_TYPE(_list_type, _item_type) \
|
||||||
\
|
\
|
||||||
struct _item_type##_full \
|
struct _item_type##_full \
|
||||||
@ -32,7 +34,7 @@ struct _item_type##_full \
|
|||||||
static struct _item_type* _item_type##_new(void) \
|
static struct _item_type* _item_type##_new(void) \
|
||||||
{ \
|
{ \
|
||||||
struct _item_type* item; \
|
struct _item_type* item; \
|
||||||
item = (struct _item_type*)malloc(sizeof(struct _item_type##_full));\
|
item = (struct _item_type*)xmalloc(sizeof(struct _item_type##_full));\
|
||||||
memset(item, 0, sizeof(struct _item_type##_full)); \
|
memset(item, 0, sizeof(struct _item_type##_full)); \
|
||||||
return item; \
|
return item; \
|
||||||
} \
|
} \
|
||||||
@ -58,7 +60,7 @@ struct _list_type \
|
|||||||
static struct _list_type* _list_type##_new(void) \
|
static struct _list_type* _list_type##_new(void) \
|
||||||
{ \
|
{ \
|
||||||
struct _list_type* list; \
|
struct _list_type* list; \
|
||||||
list = (struct _list_type*)malloc(sizeof(struct _list_type)); \
|
list = (struct _list_type*)xmalloc(sizeof(struct _list_type)); \
|
||||||
memset(list, 0, sizeof(struct _list_type)); \
|
memset(list, 0, sizeof(struct _list_type)); \
|
||||||
return list; \
|
return list; \
|
||||||
} \
|
} \
|
||||||
@ -101,9 +103,9 @@ void _list_type##_free(struct _list_type* list) \
|
|||||||
{ \
|
{ \
|
||||||
item = _list_type##_dequeue(list); \
|
item = _list_type##_dequeue(list); \
|
||||||
_item_type##_free(item); \
|
_item_type##_free(item); \
|
||||||
free(item); \
|
xfree(item); \
|
||||||
} \
|
} \
|
||||||
free(list); \
|
xfree(list); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <freerdp/svc.h>
|
#include <freerdp/svc.h>
|
||||||
#include <freerdp/utils/stream.h>
|
#include <freerdp/utils/stream.h>
|
||||||
#include <freerdp/utils/event.h>
|
#include <freerdp/utils/event.h>
|
||||||
|
#include <freerdp/utils/debug.h>
|
||||||
|
|
||||||
typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate;
|
typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate;
|
||||||
typedef struct rdp_svc_plugin rdpSvcPlugin;
|
typedef struct rdp_svc_plugin rdpSvcPlugin;
|
||||||
@ -46,4 +47,10 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints);
|
|||||||
int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out);
|
int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out);
|
||||||
int svc_plugin_send_event(rdpSvcPlugin* plugin, FRDP_EVENT* event);
|
int svc_plugin_send_event(rdpSvcPlugin* plugin, FRDP_EVENT* event);
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_SVC
|
||||||
|
#define DEBUG_SVC(fmt, ...) DEBUG_CLASS(SVC, fmt, ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_SVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __SVC_PLUGIN_UTILS_H */
|
#endif /* __SVC_PLUGIN_UTILS_H */
|
||||||
|
41
include/freerdp/utils/thread.h
Normal file
41
include/freerdp/utils/thread.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol client.
|
||||||
|
* Thread Utils
|
||||||
|
*
|
||||||
|
* Copyright 2011 Vic Lee
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __THREAD_UTILS_H
|
||||||
|
#define __THREAD_UTILS_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#define freerdp_thread_create(_proc, _arg) do { \
|
||||||
|
DWORD thread; \
|
||||||
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_proc, _arg, 0, &thread); \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#define freerdp_thread_create(_proc, _arg) do { \
|
||||||
|
pthread_t thread; \
|
||||||
|
pthread_create(&thread, 0, _proc, _arg); \
|
||||||
|
pthread_detach(thread); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __THREAD_UTILS_H */
|
@ -40,6 +40,22 @@ FRDP_EVENT* freerdp_event_new(uint32 event_type, FRDP_EVENT_CALLBACK on_event_fr
|
|||||||
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_REDRAW_EVENT));
|
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_REDRAW_EVENT));
|
||||||
memset(event, 0, sizeof(FRDP_REDRAW_EVENT));
|
memset(event, 0, sizeof(FRDP_REDRAW_EVENT));
|
||||||
break;
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_SYNC:
|
||||||
|
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_CB_SYNC_EVENT));
|
||||||
|
memset(event, 0, sizeof(FRDP_CB_SYNC_EVENT));
|
||||||
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_FORMAT_LIST:
|
||||||
|
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_CB_FORMAT_LIST_EVENT));
|
||||||
|
memset(event, 0, sizeof(FRDP_CB_FORMAT_LIST_EVENT));
|
||||||
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_DATA_REQUEST:
|
||||||
|
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_CB_DATA_REQUEST_EVENT));
|
||||||
|
memset(event, 0, sizeof(FRDP_CB_DATA_REQUEST_EVENT));
|
||||||
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_DATA_RESPONSE:
|
||||||
|
event = (FRDP_EVENT*)xmalloc(sizeof(FRDP_CB_DATA_RESPONSE_EVENT));
|
||||||
|
memset(event, 0, sizeof(FRDP_CB_DATA_RESPONSE_EVENT));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (event != NULL)
|
if (event != NULL)
|
||||||
{
|
{
|
||||||
@ -68,6 +84,20 @@ void freerdp_event_free(FRDP_EVENT* event)
|
|||||||
xfree(vevent->visible_rects);
|
xfree(vevent->visible_rects);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_FORMAT_LIST:
|
||||||
|
{
|
||||||
|
FRDP_CB_FORMAT_LIST_EVENT* cb_event = (FRDP_CB_FORMAT_LIST_EVENT*)event;
|
||||||
|
|
||||||
|
xfree(cb_event->formats);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FRDP_EVENT_TYPE_CB_DATA_RESPONSE:
|
||||||
|
{
|
||||||
|
FRDP_CB_DATA_RESPONSE_EVENT* cb_event = (FRDP_CB_DATA_RESPONSE_EVENT*)event;
|
||||||
|
|
||||||
|
xfree(cb_event->data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
xfree(event);
|
xfree(event);
|
||||||
}
|
}
|
||||||
|
@ -22,19 +22,18 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <freerdp/constants.h>
|
#include <freerdp/constants.h>
|
||||||
#include <freerdp/utils/memory.h>
|
#include <freerdp/utils/memory.h>
|
||||||
#include <freerdp/utils/mutex.h>
|
#include <freerdp/utils/mutex.h>
|
||||||
#include <freerdp/utils/debug.h>
|
#include <freerdp/utils/debug.h>
|
||||||
#include <freerdp/utils/stream.h>
|
#include <freerdp/utils/stream.h>
|
||||||
|
#include <freerdp/utils/list.h>
|
||||||
|
#include <freerdp/utils/thread.h>
|
||||||
|
#include <freerdp/utils/wait_obj.h>
|
||||||
|
#include <freerdp/utils/event.h>
|
||||||
#include <freerdp/utils/svc_plugin.h>
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
|
|
||||||
#ifdef WITH_DEBUG_SVC
|
|
||||||
#define DEBUG_SVC(fmt, ...) DEBUG_CLASS(SVC, fmt, ## __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define DEBUG_SVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The list of all plugin instances. */
|
/* The list of all plugin instances. */
|
||||||
typedef struct rdp_svc_plugin_list rdpSvcPluginList;
|
typedef struct rdp_svc_plugin_list rdpSvcPluginList;
|
||||||
struct rdp_svc_plugin_list
|
struct rdp_svc_plugin_list
|
||||||
@ -48,11 +47,42 @@ static rdpSvcPluginList* g_svc_plugin_list = NULL;
|
|||||||
/* For locking the global resources */
|
/* For locking the global resources */
|
||||||
static freerdp_mutex g_mutex = NULL;
|
static freerdp_mutex g_mutex = NULL;
|
||||||
|
|
||||||
|
/* Queue for receiving packets */
|
||||||
|
struct svc_data_in_item
|
||||||
|
{
|
||||||
|
STREAM* data_in;
|
||||||
|
FRDP_EVENT* event_in;
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_LIST_TYPE(svc_data_in_list, svc_data_in_item);
|
||||||
|
|
||||||
|
void svc_data_in_item_free(struct svc_data_in_item* item)
|
||||||
|
{
|
||||||
|
if (item->data_in)
|
||||||
|
{
|
||||||
|
stream_free(item->data_in);
|
||||||
|
item->data_in = NULL;
|
||||||
|
}
|
||||||
|
if (item->event_in)
|
||||||
|
{
|
||||||
|
freerdp_event_free(item->event_in);
|
||||||
|
item->event_in = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct rdp_svc_plugin_private
|
struct rdp_svc_plugin_private
|
||||||
{
|
{
|
||||||
void* init_handle;
|
void* init_handle;
|
||||||
uint32 open_handle;
|
uint32 open_handle;
|
||||||
STREAM* data_in;
|
STREAM* data_in;
|
||||||
|
|
||||||
|
struct svc_data_in_list* data_in_list;
|
||||||
|
freerdp_mutex* data_in_mutex;
|
||||||
|
|
||||||
|
struct wait_obj* signals[5];
|
||||||
|
int num_signals;
|
||||||
|
|
||||||
|
int thread_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle)
|
static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle)
|
||||||
@ -120,6 +150,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
|||||||
uint32 totalLength, uint32 dataFlags)
|
uint32 totalLength, uint32 dataFlags)
|
||||||
{
|
{
|
||||||
STREAM* data_in;
|
STREAM* data_in;
|
||||||
|
struct svc_data_in_item* item;
|
||||||
|
|
||||||
if (dataFlags & CHANNEL_FLAG_FIRST)
|
if (dataFlags & CHANNEL_FLAG_FIRST)
|
||||||
{
|
{
|
||||||
@ -138,13 +169,35 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
|||||||
{
|
{
|
||||||
printf("svc_plugin_process_received: read error\n");
|
printf("svc_plugin_process_received: read error\n");
|
||||||
}
|
}
|
||||||
/* the stream ownership is passed to the callback who is responsible for freeing it. */
|
|
||||||
plugin->priv->data_in = NULL;
|
plugin->priv->data_in = NULL;
|
||||||
stream_set_pos(data_in, 0);
|
stream_set_pos(data_in, 0);
|
||||||
plugin->receive_callback(plugin, data_in);
|
|
||||||
|
item = svc_data_in_item_new();
|
||||||
|
item->data_in = data_in;
|
||||||
|
|
||||||
|
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||||
|
svc_data_in_list_enqueue(plugin->priv->data_in_list, item);
|
||||||
|
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||||
|
|
||||||
|
wait_obj_set(plugin->priv->signals[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void svc_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event_in)
|
||||||
|
{
|
||||||
|
struct svc_data_in_item* item;
|
||||||
|
|
||||||
|
item = svc_data_in_item_new();
|
||||||
|
item->event_in = event_in;
|
||||||
|
|
||||||
|
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||||
|
svc_data_in_list_enqueue(plugin->priv->data_in_list, item);
|
||||||
|
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||||
|
|
||||||
|
wait_obj_set(plugin->priv->signals[1]);
|
||||||
|
}
|
||||||
|
|
||||||
static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength,
|
static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength,
|
||||||
uint32 totalLength, uint32 dataFlags)
|
uint32 totalLength, uint32 dataFlags)
|
||||||
{
|
{
|
||||||
@ -168,11 +221,71 @@ static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData,
|
|||||||
stream_free((STREAM*)pData);
|
stream_free((STREAM*)pData);
|
||||||
break;
|
break;
|
||||||
case CHANNEL_EVENT_USER:
|
case CHANNEL_EVENT_USER:
|
||||||
plugin->event_callback(plugin, (FRDP_EVENT*)pData);
|
svc_plugin_process_event(plugin, (FRDP_EVENT*)pData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void svc_plugin_process_data_in(rdpSvcPlugin* plugin)
|
||||||
|
{
|
||||||
|
struct svc_data_in_item* item;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* terminate signal */
|
||||||
|
if (wait_obj_is_set(plugin->priv->signals[0]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||||
|
item = svc_data_in_list_dequeue(plugin->priv->data_in_list);
|
||||||
|
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||||
|
|
||||||
|
if (item != NULL)
|
||||||
|
{
|
||||||
|
/* the ownership of the data is passed to the callback */
|
||||||
|
if (item->data_in)
|
||||||
|
plugin->receive_callback(plugin, item->data_in);
|
||||||
|
if (item->event_in)
|
||||||
|
plugin->event_callback(plugin, item->event_in);
|
||||||
|
xfree(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* svc_plugin_thread_func(void* arg)
|
||||||
|
{
|
||||||
|
rdpSvcPlugin* plugin = (rdpSvcPlugin*)arg;
|
||||||
|
|
||||||
|
DEBUG_SVC("in");
|
||||||
|
|
||||||
|
plugin->connect_callback(plugin);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
wait_obj_select(plugin->priv->signals, plugin->priv->num_signals, -1);
|
||||||
|
|
||||||
|
/* terminate signal */
|
||||||
|
if (wait_obj_is_set(plugin->priv->signals[0]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* data_in signal */
|
||||||
|
if (wait_obj_is_set(plugin->priv->signals[1]))
|
||||||
|
{
|
||||||
|
wait_obj_clear(plugin->priv->signals[1]);
|
||||||
|
/* process data in */
|
||||||
|
svc_plugin_process_data_in(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->priv->thread_status = -1;
|
||||||
|
|
||||||
|
DEBUG_SVC("out");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint32 dataLength)
|
static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint32 dataLength)
|
||||||
{
|
{
|
||||||
uint32 error;
|
uint32 error;
|
||||||
@ -184,15 +297,46 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint
|
|||||||
printf("svc_plugin_process_connected: open failed\n");
|
printf("svc_plugin_process_connected: open failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
plugin->connect_callback(plugin);
|
|
||||||
|
plugin->priv->data_in_list = svc_data_in_list_new();
|
||||||
|
plugin->priv->data_in_mutex = freerdp_mutex_new();
|
||||||
|
|
||||||
|
/* terminate signal */
|
||||||
|
plugin->priv->signals[plugin->priv->num_signals++] = wait_obj_new();
|
||||||
|
/* data_in signal */
|
||||||
|
plugin->priv->signals[plugin->priv->num_signals++] = wait_obj_new();
|
||||||
|
|
||||||
|
plugin->priv->thread_status = 1;
|
||||||
|
|
||||||
|
freerdp_thread_create(svc_plugin_thread_func, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||||
{
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wait_obj_set(plugin->priv->signals[0]);
|
||||||
|
i = 0;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 10000000;
|
||||||
|
while (plugin->priv->thread_status > 0 && i < 1000)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle);
|
plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle);
|
||||||
|
|
||||||
svc_plugin_remove(plugin);
|
svc_plugin_remove(plugin);
|
||||||
|
|
||||||
|
for (i = 0; i < plugin->priv->num_signals; i++)
|
||||||
|
wait_obj_free(plugin->priv->signals[i]);
|
||||||
|
plugin->priv->num_signals = 0;
|
||||||
|
|
||||||
|
freerdp_mutex_free(plugin->priv->data_in_mutex);
|
||||||
|
svc_data_in_list_free(plugin->priv->data_in_list);
|
||||||
|
|
||||||
if (plugin->priv->data_in != NULL)
|
if (plugin->priv->data_in != NULL)
|
||||||
{
|
{
|
||||||
stream_free(plugin->priv->data_in);
|
stream_free(plugin->priv->data_in);
|
||||||
@ -267,7 +411,10 @@ int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out)
|
|||||||
error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
|
error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
|
||||||
stream_get_data(data_out), stream_get_length(data_out), data_out);
|
stream_get_data(data_out), stream_get_length(data_out), data_out);
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
|
{
|
||||||
|
stream_free(data_out);
|
||||||
printf("svc_plugin_send: VirtualChannelWrite failed %d\n", error);
|
printf("svc_plugin_send: VirtualChannelWrite failed %d\n", error);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user