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
|
||||
# limitations under the License.
|
||||
|
||||
add_subdirectory(cliprdr)
|
||||
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)
|
||||
{
|
||||
printf("rdpdbg_process_connect\n");
|
||||
DEBUG_WARN("connecting");
|
||||
}
|
||||
|
||||
static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
printf("rdpdbg_process_event: event_type %d\n", event->event_type);
|
||||
DEBUG_WARN("event_type %d", event->event_type);
|
||||
freerdp_event_free(event);
|
||||
|
||||
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)
|
||||
{
|
||||
printf("rdpdbg_process_terminate\n");
|
||||
DEBUG_WARN("terminating");
|
||||
xfree(plugin);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
/* Include files */
|
||||
#cmakedefine HAVE_SYS_PARAM_H
|
||||
#cmakedefine HAVE_SYS_SOCKET_H
|
||||
@ -12,3 +15,5 @@
|
||||
#cmakedefine WITH_DEBUG_TRANSPORT
|
||||
#cmakedefine WITH_DEBUG_CHANMAN
|
||||
#cmakedefine WITH_DEBUG_SVC
|
||||
|
||||
#endif
|
||||
|
@ -47,6 +47,8 @@ add_executable(test_freerdp
|
||||
test_transport.h
|
||||
test_chanman.c
|
||||
test_chanman.h
|
||||
test_cliprdr.c
|
||||
test_cliprdr.h
|
||||
test_freerdp.c
|
||||
test_freerdp.h)
|
||||
|
||||
|
@ -71,16 +71,20 @@ void test_chanman(void)
|
||||
freerdp_chanman_post_connect(chan_man, &inst);
|
||||
|
||||
freerdp_chanman_data(&inst, 0, "testdata", 8, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 8);
|
||||
|
||||
freerdp_chanman_check_fds(chan_man, &inst);
|
||||
freerdp_chanman_data(&inst, 0, "testdata1", 9, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 9);
|
||||
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);
|
||||
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);
|
||||
freerdp_event_free(event);
|
||||
|
||||
freerdp_chanman_close(chan_man, NULL);
|
||||
freerdp_chanman_close(chan_man, &inst);
|
||||
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_transport.h"
|
||||
#include "test_chanman.h"
|
||||
#include "test_cliprdr.h"
|
||||
#include "test_freerdp.h"
|
||||
|
||||
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_transport_suite();
|
||||
add_chanman_suite();
|
||||
add_cliprdr_suite();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -160,6 +162,10 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
add_chanman_suite();
|
||||
}
|
||||
else if (strcmp("cliprdr", argv[*pindex]) == 0)
|
||||
{
|
||||
add_cliprdr_suite();
|
||||
}
|
||||
else if (strcmp("per", argv[*pindex]) == 0)
|
||||
{
|
||||
add_per_suite();
|
||||
|
@ -99,7 +99,26 @@ enum FRDP_EVENT_TYPE
|
||||
{
|
||||
FRDP_EVENT_TYPE_DEBUG = 0,
|
||||
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
|
||||
|
@ -164,6 +164,31 @@ struct _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;
|
||||
|
||||
#endif /* __RDP_TYPES_H */
|
||||
|
@ -20,9 +20,7 @@
|
||||
#ifndef __UTILS_DEBUG_H
|
||||
#define __UTILS_DEBUG_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_DEBUG_ASSERT
|
||||
#include <assert.h>
|
||||
@ -36,6 +34,7 @@
|
||||
#define DEBUG_NULL(fmt, ...) do { } while (0)
|
||||
#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_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%d): ", fmt, ## __VA_ARGS__)
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
#define DEBUG(fmt, ...) DEBUG_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef __LIST_UTILS_H
|
||||
#define __LIST_UTILS_H
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
|
||||
#define DEFINE_LIST_TYPE(_list_type, _item_type) \
|
||||
\
|
||||
struct _item_type##_full \
|
||||
@ -32,7 +34,7 @@ struct _item_type##_full \
|
||||
static struct _item_type* _item_type##_new(void) \
|
||||
{ \
|
||||
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)); \
|
||||
return item; \
|
||||
} \
|
||||
@ -58,7 +60,7 @@ struct _list_type \
|
||||
static struct _list_type* _list_type##_new(void) \
|
||||
{ \
|
||||
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)); \
|
||||
return list; \
|
||||
} \
|
||||
@ -101,9 +103,9 @@ void _list_type##_free(struct _list_type* list) \
|
||||
{ \
|
||||
item = _list_type##_dequeue(list); \
|
||||
_item_type##_free(item); \
|
||||
free(item); \
|
||||
xfree(item); \
|
||||
} \
|
||||
free(list); \
|
||||
xfree(list); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate;
|
||||
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_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 */
|
||||
|
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));
|
||||
memset(event, 0, sizeof(FRDP_REDRAW_EVENT));
|
||||
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)
|
||||
{
|
||||
@ -68,6 +84,20 @@ void freerdp_event_free(FRDP_EVENT* event)
|
||||
xfree(vevent->visible_rects);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -22,19 +22,18 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/mutex.h>
|
||||
#include <freerdp/utils/debug.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>
|
||||
|
||||
#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. */
|
||||
typedef struct rdp_svc_plugin_list rdpSvcPluginList;
|
||||
struct rdp_svc_plugin_list
|
||||
@ -48,11 +47,42 @@ static rdpSvcPluginList* g_svc_plugin_list = NULL;
|
||||
/* For locking the global resources */
|
||||
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
|
||||
{
|
||||
void* init_handle;
|
||||
uint32 open_handle;
|
||||
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)
|
||||
@ -120,6 +150,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
||||
uint32 totalLength, uint32 dataFlags)
|
||||
{
|
||||
STREAM* data_in;
|
||||
struct svc_data_in_item* item;
|
||||
|
||||
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");
|
||||
}
|
||||
/* the stream ownership is passed to the callback who is responsible for freeing it. */
|
||||
|
||||
plugin->priv->data_in = NULL;
|
||||
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,
|
||||
uint32 totalLength, uint32 dataFlags)
|
||||
{
|
||||
@ -168,11 +221,71 @@ static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData,
|
||||
stream_free((STREAM*)pData);
|
||||
break;
|
||||
case CHANNEL_EVENT_USER:
|
||||
plugin->event_callback(plugin, (FRDP_EVENT*)pData);
|
||||
svc_plugin_process_event(plugin, (FRDP_EVENT*)pData);
|
||||
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)
|
||||
{
|
||||
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");
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
stream_get_data(data_out), stream_get_length(data_out), data_out);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
stream_free(data_out);
|
||||
printf("svc_plugin_send: VirtualChannelWrite failed %d\n", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user