From 8fc2236411795bbff2c7e06a44f6d465bdfed9d6 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 11:27:56 +0800 Subject: [PATCH 01/16] libfreerdp-utils/svc_plugin: move debug macros to API header. --- include/freerdp/utils/debug.h | 2 -- include/freerdp/utils/svc_plugin.h | 7 +++++++ libfreerdp-utils/svc_plugin.c | 6 ------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/freerdp/utils/debug.h b/include/freerdp/utils/debug.h index 99bc8e796..3810cbab3 100644 --- a/include/freerdp/utils/debug.h +++ b/include/freerdp/utils/debug.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 diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index 4081bf0d9..cccb82ba2 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -26,6 +26,7 @@ #include #include #include +#include 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 */ diff --git a/libfreerdp-utils/svc_plugin.c b/libfreerdp-utils/svc_plugin.c index 210b7f1b5..f03ef46ce 100644 --- a/libfreerdp-utils/svc_plugin.c +++ b/libfreerdp-utils/svc_plugin.c @@ -29,12 +29,6 @@ #include #include -#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 From f28ce72fed69d355976f85d998eb444759a9b8b4 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 11:38:52 +0800 Subject: [PATCH 02/16] config.h.in: add missing header definition. --- config.h.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config.h.in b/config.h.in index 1d70425fa..7baeabd19 100644 --- a/config.h.in +++ b/config.h.in @@ -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 From d0ac3d3ee9a4131f29b97b258d6ec90716bd3e3b Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 11:40:49 +0800 Subject: [PATCH 03/16] rdpdbg: use DEBUG_SVC macro. --- channels/rdpdbg/rdpdbg_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/channels/rdpdbg/rdpdbg_main.c b/channels/rdpdbg/rdpdbg_main.c index e4eda5a43..36f2722ea 100644 --- a/channels/rdpdbg/rdpdbg_main.c +++ b/channels/rdpdbg/rdpdbg_main.c @@ -34,14 +34,14 @@ struct rdpdbg_plugin static void rdpdbg_process_connect(rdpSvcPlugin* plugin) { - printf("rdpdbg_process_connect\n"); + DEBUG_SVC("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_SVC("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_SVC("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_SVC("terminating"); xfree(plugin); } From b13dd011104f3b83019a918e91ec1bbf977cadb7 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 12:57:40 +0800 Subject: [PATCH 04/16] libfreerdp-utils/debug: add DEBUG_WARN. --- include/freerdp/utils/debug.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/freerdp/utils/debug.h b/include/freerdp/utils/debug.h index 3810cbab3..c59efafe7 100644 --- a/include/freerdp/utils/debug.h +++ b/include/freerdp/utils/debug.h @@ -34,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__) From 8bc7fb0875a91c61a87aa6384eb61ff5d46099a3 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 16:56:01 +0800 Subject: [PATCH 05/16] libfreerdp-utils/svc_plugin: add threading support. --- cunit/test_chanman.c | 5 +- include/freerdp/utils/list.h | 10 ++- include/freerdp/utils/thread.h | 41 ++++++++++ libfreerdp-utils/svc_plugin.c | 132 ++++++++++++++++++++++++++++++++- 4 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 include/freerdp/utils/thread.h diff --git a/cunit/test_chanman.c b/cunit/test_chanman.c index 3781f47dc..844a48843 100644 --- a/cunit/test_chanman.c +++ b/cunit/test_chanman.c @@ -71,6 +71,9 @@ 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_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); freerdp_chanman_check_fds(chan_man, &inst); @@ -81,6 +84,6 @@ void test_chanman(void) 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); } diff --git a/include/freerdp/utils/list.h b/include/freerdp/utils/list.h index 37f3b69aa..94bb420f3 100644 --- a/include/freerdp/utils/list.h +++ b/include/freerdp/utils/list.h @@ -20,6 +20,8 @@ #ifndef __LIST_UTILS_H #define __LIST_UTILS_H +#include + #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 diff --git a/include/freerdp/utils/thread.h b/include/freerdp/utils/thread.h new file mode 100644 index 000000000..82f6192c2 --- /dev/null +++ b/include/freerdp/utils/thread.h @@ -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 +#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 */ diff --git a/libfreerdp-utils/svc_plugin.c b/libfreerdp-utils/svc_plugin.c index f03ef46ce..d8ea67104 100644 --- a/libfreerdp-utils/svc_plugin.c +++ b/libfreerdp-utils/svc_plugin.c @@ -22,11 +22,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include #include /* The list of all plugin instances. */ @@ -42,11 +46,33 @@ 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; +}; + +DEFINE_LIST_TYPE(svc_data_in_list, svc_data_in_item); + +void svc_data_in_item_free(struct svc_data_in_item* item) +{ + stream_free(item->data_in); + item->data_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) @@ -114,6 +140,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) { @@ -132,10 +159,18 @@ 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]); } } @@ -167,6 +202,63 @@ static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, } } +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 */ + plugin->receive_callback(plugin, item->data_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; @@ -178,15 +270,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); @@ -261,7 +384,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; } From 35cfae8412a078290629c2329f717be7b633e8b3 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 17:06:14 +0800 Subject: [PATCH 06/16] cliprdr: initial work. --- channels/CMakeLists.txt | 1 + channels/cliprdr/CMakeLists.txt | 29 +++++ channels/cliprdr/cliprdr_constants.h | 58 ++++++++++ channels/cliprdr/cliprdr_main.c | 153 +++++++++++++++++++++++++++ channels/cliprdr/cliprdr_main.h | 35 ++++++ cunit/CMakeLists.txt | 2 + cunit/test_cliprdr.c | 95 +++++++++++++++++ cunit/test_cliprdr.h | 26 +++++ cunit/test_freerdp.c | 6 ++ 9 files changed, 405 insertions(+) create mode 100644 channels/cliprdr/CMakeLists.txt create mode 100644 channels/cliprdr/cliprdr_constants.h create mode 100644 channels/cliprdr/cliprdr_main.c create mode 100644 channels/cliprdr/cliprdr_main.h create mode 100644 cunit/test_cliprdr.c create mode 100644 cunit/test_cliprdr.h diff --git a/channels/CMakeLists.txt b/channels/CMakeLists.txt index 47496e308..cac9ecb25 100644 --- a/channels/CMakeLists.txt +++ b/channels/CMakeLists.txt @@ -17,5 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. +add_subdirectory(cliprdr) add_subdirectory(rdpdbg) diff --git a/channels/cliprdr/CMakeLists.txt b/channels/cliprdr/CMakeLists.txt new file mode 100644 index 000000000..c15ce6dda --- /dev/null +++ b/channels/cliprdr/CMakeLists.txt @@ -0,0 +1,29 @@ +# FreeRDP: A Remote Desktop Protocol Client +# FreeRDP cmake build script +# +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 Marc-Andre Moreau +# +# 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_main.c +) + +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}) diff --git a/channels/cliprdr/cliprdr_constants.h b/channels/cliprdr/cliprdr_constants.h new file mode 100644 index 000000000..d18864d00 --- /dev/null +++ b/channels/cliprdr/cliprdr_constants.h @@ -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 */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c new file mode 100644 index 000000000..11a4e5c81 --- /dev/null +++ b/channels/cliprdr/cliprdr_main.c @@ -0,0 +1,153 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include + +#include "cliprdr_constants.h" +#include "cliprdr_main.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) +{ + cliprdr_send_clip_caps(cliprdr); +} + +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; + + default: + DEBUG_WARN("unknown msgType %d", msgType); + break; + } + + stream_free(data_in); +} + +static void cliprdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* 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; +} diff --git a/channels/cliprdr/cliprdr_main.h b/channels/cliprdr/cliprdr_main.h new file mode 100644 index 000000000..1859dc122 --- /dev/null +++ b/channels/cliprdr/cliprdr_main.h @@ -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 + +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 */ diff --git a/cunit/CMakeLists.txt b/cunit/CMakeLists.txt index 4ff394cfc..4b0f84f94 100644 --- a/cunit/CMakeLists.txt +++ b/cunit/CMakeLists.txt @@ -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) diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c new file mode 100644 index 000000000..5c71d5bbb --- /dev/null +++ b/cunit/test_cliprdr.c @@ -0,0 +1,95 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include + +#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 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); +} + +void test_cliprdr(void) +{ + rdpChanMan* chan_man; + rdpSettings settings = { 0 }; + rdpInst inst = { 0 }; + FRDP_EVENT* event; + + 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); + + 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); + + sleep(1); + freerdp_chanman_check_fds(chan_man, &inst); + + freerdp_chanman_close(chan_man, &inst); + freerdp_chanman_free(chan_man); +} diff --git a/cunit/test_cliprdr.h b/cunit/test_cliprdr.h new file mode 100644 index 000000000..f1a5509ca --- /dev/null +++ b/cunit/test_cliprdr.h @@ -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); diff --git a/cunit/test_freerdp.c b/cunit/test_freerdp.c index 6da5a8d7a..959f0e636 100644 --- a/cunit/test_freerdp.c +++ b/cunit/test_freerdp.c @@ -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(); From 1ca5c76903060d9936f3bc4c311e2669e2d027d1 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 20:52:08 +0800 Subject: [PATCH 07/16] libfreerdp/svc_plugin: push events in a queue for threading. --- cunit/test_chanman.c | 7 ++++--- libfreerdp-utils/svc_plugin.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/cunit/test_chanman.c b/cunit/test_chanman.c index 844a48843..7ad61c034 100644 --- a/cunit/test_chanman.c +++ b/cunit/test_chanman.c @@ -75,12 +75,13 @@ void test_chanman(void) 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); - freerdp_chanman_check_fds(chan_man, &inst); - 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); diff --git a/libfreerdp-utils/svc_plugin.c b/libfreerdp-utils/svc_plugin.c index d8ea67104..ba5d6fae3 100644 --- a/libfreerdp-utils/svc_plugin.c +++ b/libfreerdp-utils/svc_plugin.c @@ -31,6 +31,7 @@ #include #include #include +#include #include /* The list of all plugin instances. */ @@ -50,14 +51,23 @@ static freerdp_mutex g_mutex = NULL; 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) { - stream_free(item->data_in); - item->data_in = NULL; + 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 @@ -174,6 +184,20 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3 } } +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) { @@ -197,7 +221,7 @@ 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; } } @@ -219,7 +243,10 @@ static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) if (item != NULL) { /* the ownership of the data is passed to the callback */ - plugin->receive_callback(plugin, item->data_in); + 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 From f5adaa10c1022acb6ee73d37eda6231fc92df535 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 22:03:09 +0800 Subject: [PATCH 08/16] Add cliprdr constants and event types. --- include/freerdp/constants.h | 21 ++++++++++++++++++++- include/freerdp/types.h | 25 +++++++++++++++++++++++++ libfreerdp-utils/event.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/freerdp/constants.h b/include/freerdp/constants.h index e9c8ad6a9..c970dc0a7 100644 --- a/include/freerdp/constants.h +++ b/include/freerdp/constants.h @@ -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 diff --git a/include/freerdp/types.h b/include/freerdp/types.h index 6f5a89b9f..a37d1ca97 100644 --- a/include/freerdp/types.h +++ b/include/freerdp/types.h @@ -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; + uint16* 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; + uint16 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 */ diff --git a/libfreerdp-utils/event.c b/libfreerdp-utils/event.c index 66f858c23..6e3500178 100644 --- a/libfreerdp-utils/event.c +++ b/libfreerdp-utils/event.c @@ -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); } From 128901d60abf1a748985aec58f01ff30a607657c Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 22:09:56 +0800 Subject: [PATCH 09/16] cliprdr: add cliprdr->ui sync event. --- channels/cliprdr/cliprdr_main.c | 5 +++++ cunit/test_cliprdr.c | 9 +++++++-- include/freerdp/types.h | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index 11a4e5c81..a46e0849b 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -87,7 +87,12 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) 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) diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 5c71d5bbb..4504cfbdf 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -87,8 +87,13 @@ void test_cliprdr(void) 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); - sleep(1); - freerdp_chanman_check_fds(chan_man, &inst); + 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); freerdp_chanman_close(chan_man, &inst); freerdp_chanman_free(chan_man); diff --git a/include/freerdp/types.h b/include/freerdp/types.h index a37d1ca97..7c949a457 100644 --- a/include/freerdp/types.h +++ b/include/freerdp/types.h @@ -169,7 +169,7 @@ typedef FRDP_EVENT FRDP_CB_SYNC_EVENT; struct _FRDP_CB_FORMAT_LIST_EVENT { FRDP_EVENT event; - uint16* formats; + uint32* formats; uint16 num_formats; }; typedef struct _FRDP_CB_FORMAT_LIST_EVENT FRDP_CB_FORMAT_LIST_EVENT; @@ -177,7 +177,7 @@ typedef struct _FRDP_CB_FORMAT_LIST_EVENT FRDP_CB_FORMAT_LIST_EVENT; struct _FRDP_CB_DATA_REQUEST_EVENT { FRDP_EVENT event; - uint16 format; + uint32 format; }; typedef struct _FRDP_CB_DATA_REQUEST_EVENT FRDP_CB_DATA_REQUEST_EVENT; From 4fc7794ae998fe53fc04f51aea0e897240447cb7 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 23:06:39 +0800 Subject: [PATCH 10/16] cliprdr: add format list ui event. --- channels/cliprdr/CMakeLists.txt | 4 ++ channels/cliprdr/cliprdr_format.c | 76 +++++++++++++++++++++++++++++++ channels/cliprdr/cliprdr_format.h | 26 +++++++++++ channels/cliprdr/cliprdr_main.c | 12 +++++ cunit/test_cliprdr.c | 25 ++++++++++ 5 files changed, 143 insertions(+) create mode 100644 channels/cliprdr/cliprdr_format.c create mode 100644 channels/cliprdr/cliprdr_format.h diff --git a/channels/cliprdr/CMakeLists.txt b/channels/cliprdr/CMakeLists.txt index c15ce6dda..d74f823f2 100644 --- a/channels/cliprdr/CMakeLists.txt +++ b/channels/cliprdr/CMakeLists.txt @@ -18,7 +18,11 @@ # 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}) diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c new file mode 100644 index 000000000..82213b81a --- /dev/null +++ b/channels/cliprdr/cliprdr_format.c @@ -0,0 +1,76 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include + +#include "cliprdr_constants.h" +#include "cliprdr_main.h" +#include "cliprdr_format.h" + +#define CFSTR_HTML "HTML Format" +#define CFSTR_PNG "PNG" +#define CFSTR_JPEG "JFIF" +#define CFSTR_GIF "GIF" + +static void cliprdr_copy_format_name(char* dest, const char* src) +{ + while (*src) + { + *dest = *src++; + dest += 2; + } +} + +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: + cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_HTML); + break; + case CB_FORMAT_PNG: + cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_PNG); + break; + case CB_FORMAT_JPEG: + cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_JPEG); + break; + case CB_FORMAT_GIF: + cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_GIF); + break; + } + stream_seek(data_out, 32); + } + + cliprdr_packet_send(cliprdr, data_out); +} diff --git a/channels/cliprdr/cliprdr_format.h b/channels/cliprdr/cliprdr_format.h new file mode 100644 index 000000000..894e12d73 --- /dev/null +++ b/channels/cliprdr/cliprdr_format.h @@ -0,0 +1,26 @@ +/** + * 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); + +#endif /* __CLIPRDR_FORMAT_H */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index a46e0849b..f0e2819b1 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -28,6 +28,7 @@ #include "cliprdr_constants.h" #include "cliprdr_main.h" +#include "cliprdr_format.h" STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen) { @@ -128,6 +129,17 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* 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; + + default: + DEBUG_WARN("unknown event type %d", event->event_type); + break; + } + freerdp_event_free(event); } static void cliprdr_process_terminate(rdpSvcPlugin* plugin) diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 4504cfbdf..5836dbd77 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "test_cliprdr.h" @@ -62,6 +63,15 @@ static const uint8 test_monitor_ready_data[] = 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) @@ -70,6 +80,7 @@ void test_cliprdr(void) rdpSettings settings = { 0 }; rdpInst inst = { 0 }; FRDP_EVENT* event; + FRDP_CB_FORMAT_LIST_EVENT* format_list_event; settings.hostname = "testhost"; inst.settings = &settings; @@ -95,6 +106,20 @@ void test_cliprdr(void) CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_SYNC); freerdp_event_free(event); + 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); + while (!event_processed) + { + freerdp_chanman_check_fds(chan_man, &inst); + } + freerdp_chanman_close(chan_man, &inst); freerdp_chanman_free(chan_man); } From 19c309e5d421bdf8691145e616dc59a65a495b4a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 23:13:30 +0800 Subject: [PATCH 11/16] cliprdr: use unicode constants for format names. --- channels/cliprdr/cliprdr_format.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c index 82213b81a..1a7cc80b9 100644 --- a/channels/cliprdr/cliprdr_format.c +++ b/channels/cliprdr/cliprdr_format.c @@ -30,19 +30,10 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" -#define CFSTR_HTML "HTML Format" -#define CFSTR_PNG "PNG" -#define CFSTR_JPEG "JFIF" -#define CFSTR_GIF "GIF" - -static void cliprdr_copy_format_name(char* dest, const char* src) -{ - while (*src) - { - *dest = *src++; - dest += 2; - } -} +#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) { @@ -57,16 +48,16 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LI switch (cb_event->formats[i]) { case CB_FORMAT_HTML: - cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_HTML); + memcpy(stream_get_tail(data_out), CFSTR_HTML, sizeof(CFSTR_HTML)); break; case CB_FORMAT_PNG: - cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_PNG); + memcpy(stream_get_tail(data_out), CFSTR_PNG, sizeof(CFSTR_PNG)); break; case CB_FORMAT_JPEG: - cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_JPEG); + memcpy(stream_get_tail(data_out), CFSTR_JPEG, sizeof(CFSTR_JPEG)); break; case CB_FORMAT_GIF: - cliprdr_copy_format_name(stream_get_tail(data_out), CFSTR_GIF); + memcpy(stream_get_tail(data_out), CFSTR_GIF, sizeof(CFSTR_GIF)); break; } stream_seek(data_out, 32); From a57fe59660876026bd351bedb3735b8cc3bdd0ba Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 12 Jul 2011 23:53:54 +0800 Subject: [PATCH 12/16] cliprdr: process format list PDU. --- channels/cliprdr/cliprdr_format.c | 67 +++++++++++++++++++++++++++++++ channels/cliprdr/cliprdr_format.h | 1 + channels/cliprdr/cliprdr_main.c | 4 ++ cunit/test_cliprdr.c | 35 +++++++++++++++- 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c index 1a7cc80b9..166ed112f 100644 --- a/channels/cliprdr/cliprdr_format.c +++ b/channels/cliprdr/cliprdr_format.c @@ -65,3 +65,70 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LI 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); +} diff --git a/channels/cliprdr/cliprdr_format.h b/channels/cliprdr/cliprdr_format.h index 894e12d73..4abddc0e4 100644 --- a/channels/cliprdr/cliprdr_format.h +++ b/channels/cliprdr/cliprdr_format.h @@ -22,5 +22,6 @@ #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); #endif /* __CLIPRDR_FORMAT_H */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index f0e2819b1..13d342fd5 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -119,6 +119,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) cliprdr_process_monitor_ready(cliprdr); break; + case CB_FORMAT_LIST: + cliprdr_process_format_list(cliprdr, data_in, dataLen); + break; + default: DEBUG_WARN("unknown msgType %d", msgType); break; diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 5836dbd77..cacf49978 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -60,10 +60,19 @@ 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 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); + /*freerdp_hexdump(data, data_size);*/ } static int event_processed; @@ -81,6 +90,7 @@ void test_cliprdr(void) rdpInst inst = { 0 }; FRDP_EVENT* event; FRDP_CB_FORMAT_LIST_EVENT* format_list_event; + int i; settings.hostname = "testhost"; inst.settings = &settings; @@ -92,12 +102,14 @@ void test_cliprdr(void) 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); @@ -106,6 +118,7 @@ void test_cliprdr(void) 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; @@ -113,6 +126,7 @@ void test_cliprdr(void) format_list_event->formats[0] = CB_FORMAT_TEXT; format_list_event->formats[1] = CB_FORMAT_HTML; + /* cliprdr sends format list PDU to server */ event_processed = 0; freerdp_chanman_send_event(chan_man, "cliprdr", event); while (!event_processed) @@ -120,6 +134,25 @@ void test_cliprdr(void) freerdp_chanman_check_fds(chan_man, &inst); } + /* 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); + freerdp_chanman_close(chan_man, &inst); freerdp_chanman_free(chan_man); } From b4a0b651f81fa2c7dab6842fa3a087d159ae228e Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 13 Jul 2011 00:01:50 +0800 Subject: [PATCH 13/16] cliprdr: process format list response PDU. --- channels/cliprdr/cliprdr_main.c | 3 +++ cunit/test_cliprdr.c | 13 +++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index 13d342fd5..94fbe7f33 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -123,6 +123,9 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) cliprdr_process_format_list(cliprdr, data_in, dataLen); break; + case CB_FORMAT_LIST_RESPONSE: + break; + default: DEBUG_WARN("unknown msgType %d", msgType); break; diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index cacf49978..f7cc1252e 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -69,6 +69,11 @@ static const uint8 test_format_list_data[] = "\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 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); @@ -125,15 +130,19 @@ void test_cliprdr(void) 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; - - /* cliprdr sends format list PDU to server */ 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); From a93194da063d23ebc6177515d8088eaa8a7312fb Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 13 Jul 2011 00:30:25 +0800 Subject: [PATCH 14/16] cliprdr: add server data request -> UI data response. --- channels/cliprdr/cliprdr_format.c | 18 ++++++++++++ channels/cliprdr/cliprdr_format.h | 3 ++ channels/cliprdr/cliprdr_main.c | 8 ++++++ cunit/test_cliprdr.c | 47 +++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c index 166ed112f..3b3835bd9 100644 --- a/channels/cliprdr/cliprdr_format.c +++ b/channels/cliprdr/cliprdr_format.c @@ -132,3 +132,21 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 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_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); +} diff --git a/channels/cliprdr/cliprdr_format.h b/channels/cliprdr/cliprdr_format.h index 4abddc0e4..6b311dcd8 100644 --- a/channels/cliprdr/cliprdr_format.h +++ b/channels/cliprdr/cliprdr_format.h @@ -24,4 +24,7 @@ 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_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event); + #endif /* __CLIPRDR_FORMAT_H */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index 94fbe7f33..9d233ed7e 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -126,6 +126,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) case CB_FORMAT_LIST_RESPONSE: break; + case CB_FORMAT_DATA_REQUEST: + cliprdr_process_format_data_request(cliprdr, data_in); + break; + default: DEBUG_WARN("unknown msgType %d", msgType); break; @@ -142,6 +146,10 @@ static void cliprdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event) cliprdr_process_format_list_event((cliprdrPlugin*)plugin, (FRDP_CB_FORMAT_LIST_EVENT*)event); break; + case FRDP_EVENT_TYPE_CB_DATA_RESPONSE: + cliprdr_process_data_response_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_RESPONSE_EVENT*)event); + break; + default: DEBUG_WARN("unknown event type %d", event->event_type); break; diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index f7cc1252e..7596e44e1 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "test_cliprdr.h" @@ -74,6 +75,17 @@ 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); @@ -95,6 +107,8 @@ void test_cliprdr(void) 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"; @@ -162,6 +176,39 @@ void test_cliprdr(void) } 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); + } + freerdp_chanman_close(chan_man, &inst); freerdp_chanman_free(chan_man); } From e10aba7caefa5edad536aeeb9aa3aeb03b0ddde5 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 13 Jul 2011 00:50:00 +0800 Subject: [PATCH 15/16] cliprdr: add UI data request -> server data response. --- channels/cliprdr/cliprdr_format.c | 22 +++++++++++++++++++- channels/cliprdr/cliprdr_format.h | 5 ++++- channels/cliprdr/cliprdr_main.c | 10 ++++++++- cunit/test_cliprdr.c | 34 ++++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c index 3b3835bd9..6cce75823 100644 --- a/channels/cliprdr/cliprdr_format.c +++ b/channels/cliprdr/cliprdr_format.c @@ -142,7 +142,7 @@ void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* data_in svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (FRDP_EVENT*)cb_event); } -void cliprdr_process_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event) +void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event) { STREAM* data_out; @@ -150,3 +150,23 @@ void cliprdr_process_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RE 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); +} diff --git a/channels/cliprdr/cliprdr_format.h b/channels/cliprdr/cliprdr_format.h index 6b311dcd8..59ccbc142 100644 --- a/channels/cliprdr/cliprdr_format.h +++ b/channels/cliprdr/cliprdr_format.h @@ -25,6 +25,9 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LI 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_data_response_event(cliprdrPlugin* cliprdr, FRDP_CB_DATA_RESPONSE_EVENT* cb_event); +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 */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index 9d233ed7e..090b5302e 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -130,6 +130,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) 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; @@ -146,8 +150,12 @@ static void cliprdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event) 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_data_response_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_RESPONSE_EVENT*)event); + cliprdr_process_format_data_response_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_RESPONSE_EVENT*)event); break; default: diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 7596e44e1..52791d88b 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -89,7 +89,7 @@ static const uint8 test_data_response_data[] = 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);*/ + freerdp_hexdump(data, data_size); } static int event_processed; @@ -209,6 +209,38 @@ void test_cliprdr(void) 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); } From 25a8b6f0e2f1fd103d25404feeb593fdace4843a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 13 Jul 2011 14:04:42 +0800 Subject: [PATCH 16/16] rdpdbg: change to use new DEBUG_WARN macro so that message will always printed --- channels/rdpdbg/rdpdbg_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/channels/rdpdbg/rdpdbg_main.c b/channels/rdpdbg/rdpdbg_main.c index 36f2722ea..e1067417b 100644 --- a/channels/rdpdbg/rdpdbg_main.c +++ b/channels/rdpdbg/rdpdbg_main.c @@ -34,14 +34,14 @@ struct rdpdbg_plugin static void rdpdbg_process_connect(rdpSvcPlugin* plugin) { - DEBUG_SVC("connecting"); + DEBUG_WARN("connecting"); } static void rdpdbg_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { STREAM* data_out; - DEBUG_SVC("size %d", 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) { - DEBUG_SVC("event_type %d", 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) { - DEBUG_SVC("terminating"); + DEBUG_WARN("terminating"); xfree(plugin); }