From a3d0b78ea0bafe1ca18fb092866cb6260404086e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 25 Apr 2006 00:33:00 +0000 Subject: [PATCH] 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 --- src/include/switch_loadable_module.h | 21 ++ src/include/switch_types.h | 8 + src/switch_loadable_module.c | 303 +++++++++++++++------------ 3 files changed, 202 insertions(+), 130 deletions(-) diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index fbf5a64ec7..b63fe1e2fe 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -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); +/*! + \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 \param name the name of the timer diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 7513418892..76eacc68ee 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -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_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 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 */ diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index f09be47ec7..e1c91e0559 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -32,24 +32,11 @@ #include -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 { char *filename; const switch_loadable_module_interface *interface; void *lib; 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_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) { @@ -105,8 +196,7 @@ static switch_status switch_loadable_module_load_file(char *filename, switch_loa 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; + switch_module_load_t load_func_ptr = NULL; int loading = 1; const char *err = 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"); - load_func_ptr = (switch_load_fp_t) function_handle; + load_func_ptr = (switch_module_load_t) function_handle; if (load_func_ptr == NULL) { err = "Cannot Load"; @@ -155,22 +245,6 @@ static switch_status switch_loadable_module_load_file(char *filename, switch_loa 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; } @@ -198,6 +272,7 @@ SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char char *path; char *file; switch_loadable_module *new_module = NULL; + switch_status status; #ifdef WIN32 const char *ext = ".dll"; @@ -229,106 +304,74 @@ SWITCH_DECLARE(switch_status) switch_loadable_module_load_module(char *dir, char 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) { - 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); - } - } + + 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; } - - return SWITCH_STATUS_SUCCESS; } +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 static void switch_loadable_module_path_init() {