channels: added support for loading plugins from a static entry table

This commit is contained in:
Marc-André Moreau 2012-10-08 19:54:11 -04:00
parent 84f88883e9
commit 93f88d1c48
12 changed files with 184 additions and 58 deletions

View File

@ -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})

View File

@ -1,6 +1,6 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Client Channel Loader
* Client Channels
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
@ -23,43 +23,62 @@
#include <stdlib.h>
#include <string.h>
#include <freerdp/client/channels.h>
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;
}

View File

@ -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)

View File

@ -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 <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2012 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.
@ -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()

View File

@ -30,6 +30,8 @@
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <freerdp/constants.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
@ -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;
}

View File

@ -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()

View File

@ -58,6 +58,10 @@
#include <freerdp/plugins/cliprdr.h>
#include <freerdp/rail.h>
#ifdef WITH_STATIC_PLUGINS
#include <freerdp/client/channels.h>
#endif
#include <winpr/synch.h>
#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;
}

View File

@ -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")

View File

@ -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);

View File

@ -0,0 +1,30 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Client Channels
*
* Copyright 2012 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.
*/
#ifndef FREERDP_CHANNELS_CLIENT
#define FREERDP_CHANNELS_CLIENT
#include <freerdp/api.h>
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 */

View File

@ -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)

View File

@ -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