From 93f88d1c48872d9e727146c3db0e36def6dd11f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 8 Oct 2012 19:54:11 -0400 Subject: [PATCH] channels: added support for loading plugins from a static entry table --- channels/client/CMakeLists.txt | 2 +- channels/client/{loader.c => channels.c} | 73 +++++++++++++++--------- channels/rdpsnd/CMakeLists.txt | 5 ++ channels/rdpsnd/client/CMakeLists.txt | 17 ++++-- channels/rdpsnd/client/rdpsnd_main.c | 30 +++++++++- client/X11/CMakeLists.txt | 4 ++ client/X11/xfreerdp.c | 27 +++++++-- include/CMakeLists.txt | 5 +- include/freerdp/channels/channels.h | 2 + include/freerdp/client/channels.h | 30 ++++++++++ libfreerdp/channels/CMakeLists.txt | 4 ++ libfreerdp/channels/libchannels.c | 43 ++++++++------ 12 files changed, 184 insertions(+), 58 deletions(-) rename channels/client/{loader.c => channels.c} (53%) create mode 100644 include/freerdp/client/channels.h diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index 67e3e4ab9..30f746848 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "FREERDP_CHANNELS_CLIENT") set(${MODULE_PREFIX}_SRCS tables.c tables.h - loader.c) + channels.c) foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES}) diff --git a/channels/client/loader.c b/channels/client/channels.c similarity index 53% rename from channels/client/loader.c rename to channels/client/channels.c index 884864b92..dca5ba2d3 100644 --- a/channels/client/loader.c +++ b/channels/client/channels.c @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channel Loader + * Client Channels * * Copyright 2012 Marc-Andre Moreau * @@ -23,43 +23,62 @@ #include #include +#include + extern const VIRTUAL_CHANNEL_ENTRY VIRTUAL_CHANNEL_TABLE[]; extern const DEVICE_SERVICE_ENTRY DEVICE_SERVICE_TABLE[]; +void* freerdp_channels_find_static_virtual_channel_entry(const char* name) +{ + int index = 0; + VIRTUAL_CHANNEL_ENTRY* pEntry; + + pEntry = (VIRTUAL_CHANNEL_ENTRY*) &VIRTUAL_CHANNEL_TABLE[index++]; + + while (pEntry->entry != NULL) + { + if (strcmp(pEntry->name, name) == 0) + { + return (void*) pEntry->entry; + } + + pEntry = (VIRTUAL_CHANNEL_ENTRY*) &VIRTUAL_CHANNEL_TABLE[index++]; + } + + return NULL; +} + +void* freerdp_channels_find_static_device_service_entry(const char* name) +{ + int index = 0; + DEVICE_SERVICE_ENTRY* pEntry; + + pEntry = (DEVICE_SERVICE_ENTRY*) &DEVICE_SERVICE_TABLE[index++]; + + while (pEntry->entry != NULL) + { + if (strcmp(pEntry->name, name) == 0) + { + return (void*) pEntry->entry; + } + + pEntry = (DEVICE_SERVICE_ENTRY*) &DEVICE_SERVICE_TABLE[index++]; + } + + return NULL; +} + void* freerdp_channels_find_static_entry(const char* name, const char* entry) { if (strcmp(entry, "VirtualChannelEntry") == 0) { - VIRTUAL_CHANNEL_ENTRY* pEntry; - - pEntry = (VIRTUAL_CHANNEL_ENTRY*) &VIRTUAL_CHANNEL_TABLE[0]; - - while (pEntry != NULL) - { - if (strcmp(pEntry->name, name) == 0) - { - return (void*) pEntry->entry; - } - - return NULL; - } + return freerdp_channels_find_static_virtual_channel_entry(name); } else if (strcmp(entry, "DeviceServiceEntry") == 0) { - DEVICE_SERVICE_ENTRY* pEntry; - - pEntry = (DEVICE_SERVICE_ENTRY*) &DEVICE_SERVICE_TABLE[0]; - - while (pEntry != NULL) - { - if (strcmp(pEntry->name, name) == 0) - { - return (void*) pEntry->entry; - } - - return NULL; - } + return freerdp_channels_find_static_device_service_entry(name); } return NULL; } + diff --git a/channels/rdpsnd/CMakeLists.txt b/channels/rdpsnd/CMakeLists.txt index 14ce938d1..cc57e41f1 100644 --- a/channels/rdpsnd/CMakeLists.txt +++ b/channels/rdpsnd/CMakeLists.txt @@ -20,6 +20,11 @@ set(MODULE_PREFIX "CHANNEL_RDPSND") if(WITH_CLIENT_CHANNELS) add_subdirectory(client) + if(${MODULE_PREFIX}_CLIENT_STATIC) + set(CHANNEL_STATIC_CLIENT_MODULES ${CHANNEL_STATIC_CLIENT_MODULES} ${MODULE_PREFIX} PARENT_SCOPE) + set(${MODULE_PREFIX}_CLIENT_NAME ${${MODULE_PREFIX}_CLIENT_NAME} PARENT_SCOPE) + set(${MODULE_PREFIX}_CLIENT_ENTRY ${${MODULE_PREFIX}_CLIENT_ENTRY} PARENT_SCOPE) + endif() endif() if(WITH_SERVER_CHANNELS) diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index 2fa44f662..3842ee23a 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -1,9 +1,7 @@ # 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 +# Copyright 2012 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. @@ -24,7 +22,16 @@ set(${MODULE_PREFIX}_SRCS rdpsnd_main.c rdpsnd_main.h) -add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +if(NOT WITH_STATIC_PLUGINS) + add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +else() + set(${MODULE_PREFIX}_STATIC ON PARENT_SCOPE) + set(${MODULE_PREFIX}_NAME ${MODULE_NAME} PARENT_SCOPE) + set(${MODULE_PREFIX}_ENTRY "VirtualChannelEntry" PARENT_SCOPE) + + add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS}) +endif() + set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") if(WITH_MONOLITHIC_BUILD) @@ -35,6 +42,8 @@ endif() install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH}) +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${MODULE_NAME}/Client") + if(WITH_ALSA) add_subdirectory(alsa) endif() diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index cdee38187..2df231bc2 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -30,6 +30,8 @@ #include #include +#include + #include #include #include @@ -563,6 +565,30 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin) xfree(plugin); } -DEFINE_SVC_PLUGIN(rdpsnd, "rdpsnd", - CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP) +#ifdef WITH_STATIC_PLUGINS +#define VirtualChannelEntry rdpsnd_VirtualChannelEntry +#endif + +const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) +{ + rdpsndPlugin* _p; + + _p = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin)); + ZeroMemory(_p, sizeof(rdpsndPlugin)); + + _p->plugin.channel_def.options = + CHANNEL_OPTION_INITIALIZED | + CHANNEL_OPTION_ENCRYPT_RDP; + + strcpy(_p->plugin.channel_def.name, "rdpsnd"); + + _p->plugin.connect_callback = rdpsnd_process_connect; + _p->plugin.receive_callback = rdpsnd_process_receive; + _p->plugin.event_callback = rdpsnd_process_event; + _p->plugin.terminate_callback = rdpsnd_process_terminate; + + svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints); + + return 1; +} diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 63c584f7a..08bd69f6d 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -94,6 +94,10 @@ endif() include_directories(${CMAKE_SOURCE_DIR}/resources) +if(WITH_STATIC_PLUGINS) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-channels-client) +endif() + if(WITH_MONOLITHIC_BUILD) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp) else() diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index a4adfd93f..f63fb4cdc 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -58,6 +58,10 @@ #include #include +#ifdef WITH_STATIC_PLUGINS +#include +#endif + #include #include "xf_gdi.h" @@ -944,14 +948,27 @@ int xf_process_client_args(rdpSettings* settings, const char* opt, const char* v */ int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { + void* entry; rdpChannels* channels = (rdpChannels*) user_data; - printf("loading plugin %s\n", name); + entry = NULL; + +#ifdef WITH_STATIC_PLUGINS + entry = freerdp_channels_find_static_virtual_channel_entry(name); + + if (entry) + { + if (freerdp_channels_client_load(channels, settings, entry, plugin_data) == 0) + { + printf("loading channel %s (static)\n", name); + return 1; + } + } +#endif + + printf("loading channel %s (plugin)\n", name); freerdp_channels_load_plugin(channels, settings, name, plugin_data); - // FIXME we should check the return code for freerdp_channels_load_plugin() - // and report any error to the caller. freerdp_parse_args() actually expect to get - // an error code when there is a loading error. - // Is it as easy as "return freerdp_channels_load_plugin()" ? + return 1; } diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index ae8acdede..390b28bda 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -21,14 +21,15 @@ file(GLOB FREERDP_HEADERS "freerdp/*.h") install(FILES ${FREERDP_HEADERS} DESTINATION include/freerdp) install(DIRECTORY freerdp/cache DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") -install(DIRECTORY freerdp/channels DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/codec DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/crypto DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/gdi DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/locale DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/plugins DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/rail DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") -install(DIRECTORY freerdp/server DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/utils DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/client DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/server DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/channels DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") diff --git a/include/freerdp/channels/channels.h b/include/freerdp/channels/channels.h index 8bc3a3974..3d6a245de 100644 --- a/include/freerdp/channels/channels.h +++ b/include/freerdp/channels/channels.h @@ -33,6 +33,8 @@ FREERDP_API int freerdp_channels_global_init(void); FREERDP_API int freerdp_channels_global_uninit(void); FREERDP_API rdpChannels* freerdp_channels_new(void); FREERDP_API void freerdp_channels_free(rdpChannels* channels); +FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, + void* entry, void* data); FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data); FREERDP_API int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance); diff --git a/include/freerdp/client/channels.h b/include/freerdp/client/channels.h new file mode 100644 index 000000000..1d699f229 --- /dev/null +++ b/include/freerdp/client/channels.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Client Channels + * + * Copyright 2012 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. + */ + +#ifndef FREERDP_CHANNELS_CLIENT +#define FREERDP_CHANNELS_CLIENT + +#include + +void* freerdp_channels_find_static_virtual_channel_entry(const char* name); +void* freerdp_channels_find_static_device_service_entry(const char* name); +void* freerdp_channels_find_static_entry(const char* name, const char* entry); + +#endif /* FREERDP_CHANNELS_CLIENT */ + diff --git a/libfreerdp/channels/CMakeLists.txt b/libfreerdp/channels/CMakeLists.txt index a3777363f..29c5af9b9 100644 --- a/libfreerdp/channels/CMakeLists.txt +++ b/libfreerdp/channels/CMakeLists.txt @@ -32,6 +32,10 @@ endif() set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") +if(WITH_STATIC_PLUGINS) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-channels-client) +endif() + if(WITH_MONOLITHIC_BUILD) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr) set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/libfreerdp/channels/libchannels.c b/libfreerdp/channels/libchannels.c index 400709e67..6fccfb80c 100644 --- a/libfreerdp/channels/libchannels.c +++ b/libfreerdp/channels/libchannels.c @@ -671,18 +671,12 @@ void freerdp_channels_free(rdpChannels* channels) xfree(channels); } -/** - * this is called when processing the command line parameters - * called only from main thread - */ -int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) +int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, void* entry, void* data) { - int ok; + int status; struct lib_data* lib; CHANNEL_ENTRY_POINTS_EX ep; - DEBUG_CHANNELS("%s", name); - if (channels->num_libs_data + 1 >= CHANNEL_MAX_COUNT) { DEBUG_CHANNELS("too many channels"); @@ -690,13 +684,7 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c } lib = channels->libs_data + channels->num_libs_data; - lib->entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME); - - if (lib->entry == NULL) - { - DEBUG_CHANNELS("failed to find export function"); - return 1; - } + lib->entry = (PVIRTUALCHANNELENTRY) entry; ep.cbSize = sizeof(ep); ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; @@ -714,7 +702,7 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c WaitForSingleObject(g_mutex_init, INFINITE); g_init_channels = channels; - ok = lib->entry((PCHANNEL_ENTRY_POINTS) &ep); + status = lib->entry((PCHANNEL_ENTRY_POINTS) &ep); g_init_channels = NULL; ReleaseMutex(g_mutex_init); @@ -723,7 +711,7 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c channels->settings = 0; channels->can_call_init = 0; - if (!ok) + if (!status) { DEBUG_CHANNELS("export function call failed"); return 1; @@ -732,6 +720,27 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c return 0; } +/** + * this is called when processing the command line parameters + * called only from main thread + */ +int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) +{ + void* entry; + + DEBUG_CHANNELS("%s", name); + + entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME); + + if (entry == NULL) + { + DEBUG_CHANNELS("failed to find export function"); + return 1; + } + + return freerdp_channels_client_load(channels, settings, entry, data); +} + /** * go through and inform all the libraries that we are initialized * called only from main thread