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:
parent
cfdc15bc67
commit
a3d0b78ea0
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue