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,7 +84,111 @@ 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_process(char *key, switch_loadable_module *new_module)
{
switch_core_hash_insert(loadable_modules.module_hash, key, new_module);
if (new_module->interface->endpoint_interface) {
const switch_endpoint_interface *ptr;
for (ptr = new_module->interface->endpoint_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Endpoint '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.endpoint_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->codec_interface) {
const switch_codec_implementation *impl;
const switch_codec_interface *ptr;
for (ptr = new_module->interface->codec_interface; ptr; ptr = ptr->next) {
for (impl = ptr->implementations; impl; impl = impl->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Adding Codec '%s' (%s) %dkhz %dms\n",
ptr->iananame,
ptr->interface_name,
impl->samples_per_second, impl->microseconds_per_frame / 1000);
}
switch_core_hash_insert(loadable_modules.codec_hash, (char *) ptr->iananame, (void *) ptr);
}
}
if (new_module->interface->dialplan_interface) {
const switch_dialplan_interface *ptr;
for (ptr = new_module->interface->dialplan_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Dialplan '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.dialplan_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->timer_interface) {
const switch_timer_interface *ptr;
for (ptr = new_module->interface->timer_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Timer '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.timer_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->application_interface) {
const switch_application_interface *ptr;
for (ptr = new_module->interface->application_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Application '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.application_hash,
(char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->api_interface) {
const switch_api_interface *ptr;
for (ptr = new_module->interface->api_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding API Function '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.api_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->file_interface) {
const switch_file_interface *ptr;
for (ptr = new_module->interface->file_interface; ptr; ptr = ptr->next) {
int i;
for (i = 0; ptr->extens[i]; i++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding File Format '%s'\n", ptr->extens[i]);
switch_core_hash_insert(loadable_modules.file_hash, (char *) ptr->extens[i], (void *) ptr);
}
}
}
if (new_module->interface->speech_interface) {
const switch_speech_interface *ptr;
for (ptr = new_module->interface->speech_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Speech interface '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.speech_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->directory_interface) {
const switch_directory_interface *ptr;
for (ptr = new_module->interface->directory_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Directory interface '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.directory_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status switch_loadable_module_load_file(char *filename, switch_loadable_module **new_module) static switch_status switch_loadable_module_load_file(char *filename, switch_loadable_module **new_module)
{ {
@ -105,8 +196,7 @@ static switch_status switch_loadable_module_load_file(char *filename, switch_loa
apr_dso_handle_t *dso = NULL; apr_dso_handle_t *dso = NULL;
apr_status_t status = SWITCH_STATUS_SUCCESS; apr_status_t status = SWITCH_STATUS_SUCCESS;
apr_dso_handle_sym_t function_handle = NULL; apr_dso_handle_sym_t function_handle = NULL;
//switch_status (*load_func_ptr) (switch_loadable_module_interface **, char *) = NULL; switch_module_load_t load_func_ptr = NULL;
switch_load_fp_t load_func_ptr = NULL;
int loading = 1; int loading = 1;
const char *err = NULL; const char *err = NULL;
switch_loadable_module_interface *interface = NULL; switch_loadable_module_interface *interface = NULL;
@ -125,7 +215,7 @@ static switch_status switch_loadable_module_load_file(char *filename, switch_loa
} }
status = apr_dso_sym(&function_handle, dso, "switch_module_load"); status = apr_dso_sym(&function_handle, dso, "switch_module_load");
load_func_ptr = (switch_load_fp_t) function_handle; load_func_ptr = (switch_module_load_t) function_handle;
if (load_func_ptr == NULL) { if (load_func_ptr == NULL) {
err = "Cannot Load"; err = "Cannot Load";
@ -155,22 +245,6 @@ static switch_status switch_loadable_module_load_file(char *filename, switch_loa
module->interface = interface; module->interface = interface;
module->switch_module_load = load_func_ptr; 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) { if ((status = apr_dso_sym(&function_handle, dso, "switch_module_shutdown")) == APR_SUCCESS) {
module->switch_module_shutdown = (switch_module_shutdown_t) function_handle; module->switch_module_shutdown = (switch_module_shutdown_t) function_handle;
} }
@ -198,6 +272,7 @@ SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char
char *path; char *path;
char *file; char *file;
switch_loadable_module *new_module = NULL; switch_loadable_module *new_module = NULL;
switch_status status;
#ifdef WIN32 #ifdef WIN32
const char *ext = ".dll"; const char *ext = ".dll";
@ -230,103 +305,71 @@ SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char
} }
} }
if (switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS) { if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
switch_core_hash_insert(loadable_modules.module_hash, (char *) file, new_module); return switch_loadable_module_process((char *) file, new_module);
} else {
return status;
}
}
if (new_module->interface->endpoint_interface) { SWITCH_DECLARE(switch_status) switch_loadable_module_build_dynamic(char *filename,
const switch_endpoint_interface *ptr; switch_module_load_t switch_module_load,
for (ptr = new_module->interface->endpoint_interface; ptr; ptr = ptr->next) { switch_module_runtime_t switch_module_runtime,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Endpoint '%s'\n", ptr->interface_name); switch_module_shutdown_t switch_module_shutdown)
switch_core_hash_insert(loadable_modules.endpoint_hash, (char *) ptr->interface_name, (void *) ptr); {
} 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 (new_module->interface->codec_interface) { if (load_func_ptr(&interface, filename) != SWITCH_STATUS_SUCCESS) {
const switch_codec_implementation *impl; err = "Module load routine returned an error";
const switch_codec_interface *ptr; interface = NULL;
break;
for (ptr = new_module->interface->codec_interface; ptr; ptr = ptr->next) {
for (impl = ptr->implementations; impl; impl = impl->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Adding Codec '%s' (%s) %dkhz %dms\n",
ptr->iananame,
ptr->interface_name,
impl->samples_per_second, impl->microseconds_per_frame / 1000);
}
switch_core_hash_insert(loadable_modules.codec_hash, (char *) ptr->iananame, (void *) ptr);
}
} }
if (new_module->interface->dialplan_interface) { if ((module = switch_core_permenant_alloc(sizeof(switch_loadable_module))) == 0) {
const switch_dialplan_interface *ptr; err = "Could not allocate memory\n";
break;
for (ptr = new_module->interface->dialplan_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Dialplan '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.dialplan_hash, (char *) ptr->interface_name, (void *) ptr);
}
} }
if (new_module->interface->timer_interface) { loading = 0;
const switch_timer_interface *ptr;
for (ptr = new_module->interface->timer_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Timer '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.timer_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->application_interface) {
const switch_application_interface *ptr;
for (ptr = new_module->interface->application_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Application '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.application_hash,
(char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->api_interface) {
const switch_api_interface *ptr;
for (ptr = new_module->interface->api_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding API Function '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.api_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->file_interface) {
const switch_file_interface *ptr;
for (ptr = new_module->interface->file_interface; ptr; ptr = ptr->next) {
int i;
for (i = 0; ptr->extens[i]; i++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding File Format '%s'\n", ptr->extens[i]);
switch_core_hash_insert(loadable_modules.file_hash, (char *) ptr->extens[i], (void *) ptr);
}
}
}
if (new_module->interface->speech_interface) {
const switch_speech_interface *ptr;
for (ptr = new_module->interface->speech_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Speech interface '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.speech_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->interface->directory_interface) {
const switch_directory_interface *ptr;
for (ptr = new_module->interface->directory_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Directory interface '%s'\n", ptr->interface_name);
switch_core_hash_insert(loadable_modules.directory_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
} }
return SWITCH_STATUS_SUCCESS; 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