tweak loadable module code to allow registration for langauges that can in turn fully implement modules of thier own (e.g. mono)

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1244 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-04-25 00:33:00 +00:00
parent cfdc15bc67
commit a3d0b78ea0
3 changed files with 202 additions and 130 deletions

View File

@ -109,6 +109,27 @@ SWITCH_DECLARE(switch_codec_interface *) switch_loadable_module_get_codec_interf
*/ */
SWITCH_DECLARE(switch_dialplan_interface *) switch_loadable_module_get_dialplan_interface(char *name); SWITCH_DECLARE(switch_dialplan_interface *) switch_loadable_module_get_dialplan_interface(char *name);
/*!
\brief build a dynamic module object and register it (for use in double embeded modules)
\param filename the name of the modules source file
\param switch_module_load the function to call when the module is loaded
\param switch_module_runtime a function requested to be started in it's own thread once loaded
\param switch_module_shutdown the function to call when the system is shutdown
\return the resulting status
\note only use this function if you are making a module that in turn gateways module loading to another technology
*/
SWITCH_DECLARE(switch_status) switch_loadable_module_build_dynamic(char *filename,
switch_module_load_t switch_module_load,
switch_module_runtime_t switch_module_runtime,
switch_module_shutdown_t switch_module_shutdown);
/*!
\brief Retrieve the dialplan interface by it's registered name
\param name the name of the dialplan
\return the desired dialplan interface
*/
SWITCH_DECLARE(switch_status) switch_loadable_module_load_dynamic(switch_loadable_module *new_module);
/*! /*!
\brief Retrieve the timer interface by it's registered name \brief Retrieve the timer interface by it's registered name
\param name the name of the timer \param name the name of the timer

View File

@ -649,6 +649,14 @@ typedef switch_status (*switch_send_dtmf_hook)(switch_core_session *, char *);
typedef switch_status (*switch_api_function)(char *in, char *out, switch_size_t outlen); typedef switch_status (*switch_api_function)(char *in, char *out, switch_size_t outlen);
typedef switch_status (*switch_dtmf_callback_function)(switch_core_session *session, char *dtmf, void *buf, unsigned int buflen); typedef switch_status (*switch_dtmf_callback_function)(switch_core_session *session, char *dtmf, void *buf, unsigned int buflen);
typedef int (*switch_core_db_callback_func)(void *pArg, int argc, char **argv, char **columnNames); typedef int (*switch_core_db_callback_func)(void *pArg, int argc, char **argv, char **columnNames);
typedef switch_status (*switch_module_load_t) (switch_loadable_module_interface **, char *);
typedef switch_status (*switch_module_reload_t) (void);
typedef switch_status (*switch_module_pause_t) (void);
typedef switch_status (*switch_module_resume_t) (void);
typedef switch_status (*switch_module_status_t) (void);
typedef switch_status (*switch_module_runtime_t) (void);
typedef switch_status (*switch_module_shutdown_t) (void);
/* things we don't deserve to know about */ /* things we don't deserve to know about */

View File

@ -32,24 +32,11 @@
#include <switch.h> #include <switch.h>
typedef switch_status (*switch_module_load_t) (switch_loadable_module_interface **, char *);
typedef switch_status (*switch_module_reload_t) (void);
typedef switch_status (*switch_module_pause_t) (void);
typedef switch_status (*switch_module_resume_t) (void);
typedef switch_status (*switch_module_status_t) (void);
typedef switch_status (*switch_module_runtime_t) (void);
typedef switch_status (*switch_module_shutdown_t) (void);
struct switch_loadable_module { struct switch_loadable_module {
char *filename; char *filename;
const switch_loadable_module_interface *interface; const switch_loadable_module_interface *interface;
void *lib; void *lib;
switch_module_load_t switch_module_load; switch_module_load_t switch_module_load;
switch_module_reload_t switch_module_reload;
switch_module_pause_t switch_module_pause;
switch_module_resume_t switch_module_resume;
switch_module_status_t switch_module_status;
switch_module_runtime_t switch_module_runtime; switch_module_runtime_t switch_module_runtime;
switch_module_shutdown_t switch_module_shutdown; switch_module_shutdown_t switch_module_shutdown;
}; };
@ -97,141 +84,14 @@ static void *switch_loadable_module_exec(switch_thread *thread, void *obj)
} }
typedef switch_status (*switch_load_fp_t)(switch_loadable_module_interface **, char *);
static switch_status switch_loadable_module_load_file(char *filename, switch_loadable_module **new_module)
static switch_status switch_loadable_module_process(char *key, switch_loadable_module *new_module)
{ {
switch_loadable_module *module = NULL;
apr_dso_handle_t *dso = NULL;
apr_status_t status = SWITCH_STATUS_SUCCESS;
apr_dso_handle_sym_t function_handle = NULL;
//switch_status (*load_func_ptr) (switch_loadable_module_interface **, char *) = NULL;
switch_load_fp_t load_func_ptr = NULL;
int loading = 1;
const char *err = NULL;
switch_loadable_module_interface *interface = NULL;
char derr[512] = "";
assert(filename != NULL);
*new_module = NULL;
status = apr_dso_load(&dso, filename, loadable_modules.pool);
while (loading) {
if (status != APR_SUCCESS) {
apr_dso_error(dso, derr, sizeof(derr));
err = derr;
break;
}
status = apr_dso_sym(&function_handle, dso, "switch_module_load");
load_func_ptr = (switch_load_fp_t) function_handle;
if (load_func_ptr == NULL) {
err = "Cannot Load";
break;
}
if (load_func_ptr(&interface, filename) != SWITCH_STATUS_SUCCESS) {
err = "Module load routine returned an error";
interface = NULL;
break;
}
if ((module = switch_core_permenant_alloc(sizeof(switch_loadable_module))) == 0) {
err = "Could not allocate memory\n";
break;
}
loading = 0;
}
if (err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err);
return SWITCH_STATUS_GENERR;
}
module->filename = switch_core_permenant_strdup(filename);
module->interface = interface;
module->switch_module_load = load_func_ptr;
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_reload")) == APR_SUCCESS) {
module->switch_module_reload = (switch_module_reload_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_pause")) == APR_SUCCESS) {
module->switch_module_pause = (switch_module_pause_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_resume")) == APR_SUCCESS) {
module->switch_module_resume = (switch_module_resume_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_status")) == APR_SUCCESS) {
module->switch_module_status = (switch_module_status_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_shutdown")) == APR_SUCCESS) {
module->switch_module_shutdown = (switch_module_shutdown_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_runtime")) == APR_SUCCESS) {
module->switch_module_runtime = (switch_module_runtime_t) function_handle;
}
module->lib = dso;
if (module->switch_module_runtime) {
switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
}
*new_module = module;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", interface->module_name);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char *fname)
{
switch_size_t len = 0;
char *path;
char *file;
switch_loadable_module *new_module = NULL;
#ifdef WIN32
const char *ext = ".dll";
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
#else
const char *ext = ".so";
#endif
if ((file = switch_core_strdup(loadable_modules.pool, fname)) == 0) { switch_core_hash_insert(loadable_modules.module_hash, key, new_module);
return SWITCH_STATUS_FALSE;
}
if (*file == '/') {
path = switch_core_strdup(loadable_modules.pool, file);
} else {
if (strchr(file, '.')) {
len = strlen(dir);
len += strlen(file);
len += 4;
path = (char *) switch_core_alloc(loadable_modules.pool, len);
snprintf(path, len, "%s%s%s", dir, SWITCH_PATH_SEPARATOR, file);
} else {
len = strlen(dir);
len += strlen(file);
len += 8;
path = (char *) switch_core_alloc(loadable_modules.pool, len);
snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
}
}
if (switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS) {
switch_core_hash_insert(loadable_modules.module_hash, (char *) file, new_module);
if (new_module->interface->endpoint_interface) { if (new_module->interface->endpoint_interface) {
const switch_endpoint_interface *ptr; const switch_endpoint_interface *ptr;
@ -324,9 +184,192 @@ SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char
switch_core_hash_insert(loadable_modules.directory_hash, (char *) ptr->interface_name, (void *) ptr); switch_core_hash_insert(loadable_modules.directory_hash, (char *) ptr->interface_name, (void *) ptr);
} }
} }
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
}
static switch_status switch_loadable_module_load_file(char *filename, switch_loadable_module **new_module)
{
switch_loadable_module *module = NULL;
apr_dso_handle_t *dso = NULL;
apr_status_t status = SWITCH_STATUS_SUCCESS;
apr_dso_handle_sym_t function_handle = NULL;
switch_module_load_t load_func_ptr = NULL;
int loading = 1;
const char *err = NULL;
switch_loadable_module_interface *interface = NULL;
char derr[512] = "";
assert(filename != NULL);
*new_module = NULL;
status = apr_dso_load(&dso, filename, loadable_modules.pool);
while (loading) {
if (status != APR_SUCCESS) {
apr_dso_error(dso, derr, sizeof(derr));
err = derr;
break;
}
status = apr_dso_sym(&function_handle, dso, "switch_module_load");
load_func_ptr = (switch_module_load_t) function_handle;
if (load_func_ptr == NULL) {
err = "Cannot Load";
break;
}
if (load_func_ptr(&interface, filename) != SWITCH_STATUS_SUCCESS) {
err = "Module load routine returned an error";
interface = NULL;
break;
}
if ((module = switch_core_permenant_alloc(sizeof(switch_loadable_module))) == 0) {
err = "Could not allocate memory\n";
break;
}
loading = 0;
}
if (err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err);
return SWITCH_STATUS_GENERR;
}
module->filename = switch_core_permenant_strdup(filename);
module->interface = interface;
module->switch_module_load = load_func_ptr;
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_shutdown")) == APR_SUCCESS) {
module->switch_module_shutdown = (switch_module_shutdown_t) function_handle;
}
if ((status = apr_dso_sym(&function_handle, dso, "switch_module_runtime")) == APR_SUCCESS) {
module->switch_module_runtime = (switch_module_runtime_t) function_handle;
}
module->lib = dso;
if (module->switch_module_runtime) {
switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
}
*new_module = module;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", interface->module_name);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char *fname)
{
switch_size_t len = 0;
char *path;
char *file;
switch_loadable_module *new_module = NULL;
switch_status status;
#ifdef WIN32
const char *ext = ".dll";
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
#else
const char *ext = ".so";
#endif
if ((file = switch_core_strdup(loadable_modules.pool, fname)) == 0) {
return SWITCH_STATUS_FALSE;
}
if (*file == '/') {
path = switch_core_strdup(loadable_modules.pool, file);
} else {
if (strchr(file, '.')) {
len = strlen(dir);
len += strlen(file);
len += 4;
path = (char *) switch_core_alloc(loadable_modules.pool, len);
snprintf(path, len, "%s%s%s", dir, SWITCH_PATH_SEPARATOR, file);
} else {
len = strlen(dir);
len += strlen(file);
len += 8;
path = (char *) switch_core_alloc(loadable_modules.pool, len);
snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
}
}
if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
return switch_loadable_module_process((char *) file, new_module);
} else {
return status;
}
}
SWITCH_DECLARE(switch_status) switch_loadable_module_build_dynamic(char *filename,
switch_module_load_t switch_module_load,
switch_module_runtime_t switch_module_runtime,
switch_module_shutdown_t switch_module_shutdown)
{
switch_loadable_module *module = NULL;
if ((module = switch_core_permenant_alloc(sizeof(switch_loadable_module))) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n");
return SWITCH_STATUS_GENERR;
}
switch_module_load_t load_func_ptr = NULL;
int loading = 1;
const char *err = NULL;
switch_loadable_module_interface *interface = NULL;
while (loading) {
load_func_ptr = (switch_module_load_t) switch_module_load;
if (load_func_ptr == NULL) {
err = "Cannot Load";
break;
}
if (load_func_ptr(&interface, filename) != SWITCH_STATUS_SUCCESS) {
err = "Module load routine returned an error";
interface = NULL;
break;
}
if ((module = switch_core_permenant_alloc(sizeof(switch_loadable_module))) == 0) {
err = "Could not allocate memory\n";
break;
}
loading = 0;
}
if (err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err);
return SWITCH_STATUS_GENERR;
}
module->filename = switch_core_permenant_strdup(filename);
module->interface = interface;
module->switch_module_load = load_func_ptr;
if (switch_module_shutdown) {
module->switch_module_shutdown = switch_module_shutdown;
}
if (switch_module_runtime) {
module->switch_module_runtime = switch_module_runtime;
}
if (module->switch_module_runtime) {
switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", interface->module_name);
return switch_loadable_module_process((char *) module->filename, module);
} }
#ifdef WIN32 #ifdef WIN32