general improvements

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5078 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-05-03 16:28:23 +00:00
parent 9d5d251987
commit 1be5b1ff45
8 changed files with 599 additions and 59 deletions

View File

@ -818,6 +818,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t * hash);
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t * hash, const char *key, const void *data);
/*!
\brief Insert data into a hash
\param hash the hash to add data to
\param key the name of the key to add the data to
\param data the data to add
\param mutex optional mutex to lock
\return SWITCH_STATUS_SUCCESS if the data is added
\note the string key must be a constant or a dynamic string
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex);
/*!
\brief Insert data into a hash with dynamicly allocated key name
\param hash the hash to add data to
@ -827,6 +838,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t * hash, co
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup(switch_hash_t * hash, const char *key, const void *data);
/*!
\brief Insert data into a hash with dynamicly allocated key name
\param hash the hash to add data to
\param key the name of the key to add the data to
\param data the data to add
\param mutex optional mutex to lock
\return SWITCH_STATUS_SUCCESS if the data is added
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex);
/*!
\brief Delete data from a hash based on desired key
\param hash the hash to delete from
@ -835,6 +856,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup(switch_hash_t * hash
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t * hash, const char *key);
/*!
\brief Delete data from a hash based on desired key
\param hash the hash to delete from
\param key the key from which to delete the data
\param mutex optional mutex to lock
\return SWITCH_STATUS_SUCCESS if the data is deleted
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex);
/*!
\brief Retrieve data from a given hash
\param hash the hash to retrieve from
@ -842,6 +872,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t * hash, co
\return a pointer to the data held in the key
*/
SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t * hash, const char *key);
/*!
\brief Retrieve data from a given hash
\param hash the hash to retrieve from
\param key the key to retrieve
\param mutex optional mutex to lock
\return a pointer to the data held in the key
*/
SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex);
///\}
///\defgroup timer Timer Functions

View File

@ -228,15 +228,24 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
*/
SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
/*!
\brief Load a module
\param dir the directory where the module resides
\param fname the file name of the module
\param runtime option to start the runtime thread if it exists
\param err pointer to error message
\return the status
*/
SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime);
SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err);
/*!
\brief Unoad a module
\param dir the directory where the module resides
\param fname the file name of the module
\param err pointer to error message
\return the status
*/
SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, char *fname, const char **err);
/* Prototypes of module interface functions */

View File

@ -420,6 +420,7 @@ typedef enum {
SWITCH_STATUS_MORE_DATA - Need More Data
SWITCH_STATUS_NOTFOUND - Not Found
SWITCH_STATUS_UNLOAD - Unload
SWITCH_STATUS_NOUNLOAD - Never Unload
</pre>
*/
typedef enum {
@ -438,7 +439,8 @@ typedef enum {
SWITCH_STATUS_SOCKERR,
SWITCH_STATUS_MORE_DATA,
SWITCH_STATUS_NOTFOUND,
SWITCH_STATUS_UNLOAD
SWITCH_STATUS_UNLOAD,
SWITCH_STATUS_NOUNLOAD
} switch_status_t;
@ -816,6 +818,7 @@ typedef enum {
SWITCH_EVENT_NOTALK - Not Talking Detected
SWITCH_EVENT_SESSION_CRASH - Session Crashed
SWITCH_EVENT_MODULE_LOAD - Module was loaded
SWITCH_EVENT_MODULE_UNLOAD - Module was unloaded
SWITCH_EVENT_DTMF - DTMF was sent
SWITCH_EVENT_MESSAGE - A Basic Message
SWITCH_EVENT_PRESENCE_IN - Presence in
@ -863,6 +866,7 @@ typedef enum {
SWITCH_EVENT_NOTALK,
SWITCH_EVENT_SESSION_CRASH,
SWITCH_EVENT_MODULE_LOAD,
SWITCH_EVENT_MODULE_UNLOAD,
SWITCH_EVENT_DTMF,
SWITCH_EVENT_MESSAGE,
SWITCH_EVENT_PRESENCE_IN,

View File

@ -46,6 +46,7 @@ static switch_api_interface_t show_api_interface;
static switch_api_interface_t pause_api_interface;
static switch_api_interface_t transfer_api_interface;
static switch_api_interface_t load_api_interface;
static switch_api_interface_t unload_api_interface;
static switch_api_interface_t reload_api_interface;
static switch_api_interface_t kill_api_interface;
static switch_api_interface_t originate_api_interface;
@ -150,6 +151,7 @@ static switch_status_t ctl_function(char *data, switch_core_session_t *session,
static switch_status_t load_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
{
const char *err;
if (session) {
return SWITCH_STATUS_FALSE;
@ -160,10 +162,32 @@ static switch_status_t load_function(char *mod, switch_core_session_t *session,
return SWITCH_STATUS_SUCCESS;
}
if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "OK\n");
} else {
stream->write_function(stream, "ERROR\n");
stream->write_function(stream, "ERROR [%s]\n", err);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t unload_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
{
const char *err;
if (session) {
return SWITCH_STATUS_FALSE;
}
if (switch_strlen_zero(mod)) {
stream->write_function(stream, "USAGE: %s\n", unload_api_interface.syntax);
return SWITCH_STATUS_SUCCESS;
}
if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "OK\n");
} else {
stream->write_function(stream, "ERROR [%s]\n", err);
}
return SWITCH_STATUS_SUCCESS;
@ -1221,12 +1245,20 @@ static switch_api_interface_t load_api_interface = {
/*.next */ &transfer_api_interface
};
static switch_api_interface_t unload_api_interface = {
/*.interface_name */ "unload",
/*.desc */ "Unoad Module",
/*.function */ unload_function,
/*.syntax */ "<mod_name>",
/*.next */ &load_api_interface
};
static switch_api_interface_t reload_api_interface = {
/*.interface_name */ "reloadxml",
/*.desc */ "Reload XML",
/*.function */ reload_function,
/*.syntax */ "",
/*.next */ &load_api_interface,
/*.next */ &unload_api_interface,
};
@ -1263,7 +1295,7 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
*module_interface = &mod_commands_module_interface;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_NOUNLOAD;
}
/* For Emacs:

View File

@ -1565,11 +1565,14 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
#endif
#ifdef SWITCH_HAVE_ODBC
return profile->master_odbc ? 1 : 0;
#else
return 1;
if (profile->odbc_dsn) {
return profile->master_odbc ? 1 : 0;
}
#endif
return profile->master_db ? 1: 0;
}
void sofia_glue_sql_close(sofia_profile_t *profile)

View File

@ -57,19 +57,83 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup(switch_hash_t * hash
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex)
{
if (mutex) {
switch_mutex_lock(mutex);
}
apr_hash_set(hash, switch_core_strdup(apr_hash_pool_get(hash), key), APR_HASH_KEY_STRING, data);
if (mutex) {
switch_mutex_unlock(mutex);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t * hash, const char *key, const void *data)
{
apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex)
{
if (mutex) {
switch_mutex_lock(mutex);
}
apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
if (mutex) {
switch_mutex_unlock(mutex);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t * hash, const char *key)
{
apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex)
{
if (mutex) {
switch_mutex_lock(mutex);
}
apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
if (mutex) {
switch_mutex_unlock(mutex);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t * hash, const char *key)
{
return apr_hash_get(hash, key, APR_HASH_KEY_STRING);
}
SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex)
{
void *val;
if (mutex) {
switch_mutex_lock(mutex);
}
val = apr_hash_get(hash, key, APR_HASH_KEY_STRING);
if (mutex) {
switch_mutex_unlock(mutex);
}
return val;
}

View File

@ -121,6 +121,7 @@ static char *EVENT_NAMES[] = {
"NOTALK",
"SESSION_CRASH",
"MODULE_LOAD",
"MODULE_UNLOAD",
"DTMF",
"MESSAGE",
"PRESENCE_IN",

View File

@ -41,12 +41,15 @@
#include <apr_file_io.h>
struct switch_loadable_module {
char *key;
char *filename;
int perm;
const switch_loadable_module_interface_t *module_interface;
void *lib;
switch_module_load_t switch_module_load;
switch_module_runtime_t switch_module_runtime;
switch_module_shutdown_t switch_module_shutdown;
switch_memory_pool_t *pool;
};
struct switch_loadable_module_container {
@ -64,10 +67,12 @@ struct switch_loadable_module_container {
switch_hash_t *chat_hash;
switch_hash_t *say_hash;
switch_hash_t *management_hash;
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
};
static struct switch_loadable_module_container loadable_modules;
static void do_shutdown(switch_loadable_module_t *module);
static void *switch_loadable_module_exec(switch_thread_t * thread, void *obj)
{
@ -102,6 +107,7 @@ static void switch_loadable_module_runtime(void)
void *val;
switch_loadable_module_t *module;
switch_mutex_lock(loadable_modules.mutex);
for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
module = (switch_loadable_module_t *) val;
@ -111,12 +117,16 @@ static void switch_loadable_module_runtime(void)
switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
}
}
switch_mutex_unlock(loadable_modules.mutex);
}
static switch_status_t switch_loadable_module_process(char *key, switch_loadable_module_t *new_module)
{
switch_event_t *event;
new_module->key = switch_core_strdup(new_module->pool, key);
switch_mutex_lock(loadable_modules.mutex);
switch_core_hash_insert(loadable_modules.module_hash, key, new_module);
if (new_module->module_interface->endpoint_interface) {
@ -380,11 +390,252 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
}
}
switch_mutex_unlock(loadable_modules.mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t *old_module)
{
switch_event_t *event;
switch_mutex_lock(loadable_modules.mutex);
switch_core_hash_delete(loadable_modules.module_hash, old_module->key);
if (old_module->module_interface->endpoint_interface) {
const switch_endpoint_interface_t *ptr;
for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Endpoint '%s'\n", ptr->interface_name);
switch_core_hash_delete(loadable_modules.endpoint_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->codec_interface) {
const switch_codec_implementation_t *impl;
const switch_codec_interface_t *ptr;
for (ptr = old_module->module_interface->codec_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
unsigned load_interface = 1;
for (impl = ptr->implementations; impl; impl = impl->next) {
if (!impl->iananame) {
load_interface = 0;
break;
}
}
if (load_interface) {
for (impl = ptr->implementations; impl; impl = impl->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Deleting Codec '%s' (%s) %dhz %dms\n",
impl->iananame, ptr->interface_name, impl->samples_per_second, impl->microseconds_per_frame / 1000);
if (switch_core_hash_find(loadable_modules.codec_hash, impl->iananame)) {
switch_core_hash_delete(loadable_modules.codec_hash, impl->iananame);
}
}
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "codec");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
}
}
}
}
if (old_module->module_interface->dialplan_interface) {
const switch_dialplan_interface_t *ptr;
for (ptr = old_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Dialplan '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "dialplan");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.dialplan_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->timer_interface) {
const switch_timer_interface_t *ptr;
for (ptr = old_module->module_interface->timer_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Timer '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "timer");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.timer_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->application_interface) {
const switch_application_interface_t *ptr;
for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "application");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "description", "%s", switch_str_nil(ptr->short_desc));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "syntax", "%s", switch_str_nil(ptr->syntax));
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.application_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->api_interface) {
const switch_api_interface_t *ptr;
for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "api");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "description", "%s", switch_str_nil(ptr->desc));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "syntax", "%s", switch_str_nil(ptr->syntax));
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.api_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->file_interface) {
const switch_file_interface_t *ptr;
for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
int i;
for (i = 0; ptr->extens[i]; i++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting File Format '%s'\n", ptr->extens[i]);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "file");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->extens[i]);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.file_hash, ptr->extens[i]);
}
}
}
}
if (old_module->module_interface->speech_interface) {
const switch_speech_interface_t *ptr;
for (ptr = old_module->module_interface->speech_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Speech interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "speech");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.speech_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->asr_interface) {
const switch_asr_interface_t *ptr;
for (ptr = old_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Asr interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "asr");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.asr_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->directory_interface) {
const switch_directory_interface_t *ptr;
for (ptr = old_module->module_interface->directory_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Directory interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "directory");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.directory_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->chat_interface) {
const switch_chat_interface_t *ptr;
for (ptr = old_module->module_interface->chat_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Chat interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "chat");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.chat_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->say_interface) {
const switch_say_interface_t *ptr;
for (ptr = old_module->module_interface->say_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Say interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "say");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_delete(loadable_modules.say_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->management_interface) {
const switch_management_interface_t *ptr;
for (ptr = old_module->module_interface->management_interface; ptr; ptr = ptr->next) {
if (ptr->relative_oid) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Deleting Management interface '%s' OID[%s.%s]\n", old_module->key, FREESWITCH_OID_PREFIX, ptr->relative_oid);
switch_core_hash_delete(loadable_modules.management_hash, ptr->relative_oid);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "management");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->relative_oid);
switch_event_fire(&event);
}
}
}
}
switch_mutex_unlock(loadable_modules.mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_loadable_module_load_file(char *filename, switch_loadable_module_t **new_module)
{
switch_loadable_module_t *module = NULL;
@ -398,12 +649,18 @@ static switch_status_t switch_loadable_module_load_file(char *filename, switch_l
const char *err = NULL;
switch_loadable_module_interface_t *module_interface = NULL;
char derr[512] = "";
switch_memory_pool_t *pool;
assert(filename != NULL);
*new_module = NULL;
status = switch_dso_load(&dso, filename, loadable_modules.pool);
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
abort();
}
while (loading) {
if (status != APR_SUCCESS) {
switch_dso_error(dso, derr, sizeof(derr));
@ -419,26 +676,37 @@ static switch_status_t switch_loadable_module_load_file(char *filename, switch_l
break;
}
if (load_func_ptr(&module_interface, filename) != SWITCH_STATUS_SUCCESS) {
status = load_func_ptr(&module_interface, filename);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
err = "Module load routine returned an error";
module_interface = NULL;
break;
}
if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
err = "Could not allocate memory\n";
break;
abort();
}
if (status == SWITCH_STATUS_NOUNLOAD) {
module->perm++;
}
loading = 0;
}
if (err) {
if (pool) {
switch_core_destroy_memory_pool(&pool);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Loading module %s\n**%s**\n", filename, err);
return SWITCH_STATUS_GENERR;
}
module->filename = switch_core_permanent_strdup(filename);
module->pool = pool;
module->filename = switch_core_strdup(module->pool, filename);
module->module_interface = module_interface;
module->switch_module_load = load_func_ptr;
@ -456,7 +724,7 @@ static switch_status_t switch_loadable_module_load_file(char *filename, switch_l
}
SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime)
SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err)
{
switch_size_t len = 0;
char *path;
@ -495,18 +763,82 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, ch
}
}
switch_mutex_lock(loadable_modules.mutex);
if (switch_core_hash_find(loadable_modules.module_hash, file)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Module %s Already Loaded!\n", file);
return SWITCH_STATUS_FALSE;
}
if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
*err = "Module already loadedn\n";
status = SWITCH_STATUS_FALSE;
} else if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
if ((status = switch_loadable_module_process((char *) file, new_module)) == SWITCH_STATUS_SUCCESS && runtime) {
if (new_module->switch_module_runtime) {
switch_core_launch_thread(switch_loadable_module_exec, new_module, loadable_modules.pool);
switch_core_launch_thread(switch_loadable_module_exec, new_module, new_module->pool);
}
}
}
switch_mutex_unlock(loadable_modules.mutex);
return status;
}
SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, char *fname, const char **err)
{
switch_size_t len = 0;
char *path = NULL;
char *file = NULL;
switch_loadable_module_t *module = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
#ifdef WIN32
const char *ext = ".dll";
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
#else
const char *ext = ".so";
#endif
if (!(file = strdup(fname))) {
abort();
}
if (*file == '/') {
path = strdup(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 *) malloc(len);
snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
}
}
switch_mutex_lock(loadable_modules.mutex);
if ((module = switch_core_hash_find(loadable_modules.module_hash, file))) {
if (module->perm) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module is not unloadable.\n");
*err = "Module is not unloadable";
status = SWITCH_STATUS_NOUNLOAD;
} else {
do_shutdown(module);
}
} else {
status = SWITCH_STATUS_FALSE;
}
switch_mutex_unlock(loadable_modules.mutex);
switch_safe_free(file);
switch_safe_free(path);
return status;
@ -522,40 +854,58 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filen
int loading = 1;
const char *err = NULL;
switch_loadable_module_interface_t *module_interface = NULL;
switch_memory_pool_t *pool;
if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n");
return SWITCH_STATUS_GENERR;
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
abort();
}
if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n");
abort();
}
while (loading) {
load_func_ptr = (switch_module_load_t) switch_module_load;
switch_status_t status;
if (load_func_ptr == NULL) {
err = "Cannot Load";
break;
}
if (load_func_ptr(&module_interface, filename) != SWITCH_STATUS_SUCCESS) {
status = load_func_ptr(&module_interface, filename);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
err = "Module load routine returned an error";
module_interface = NULL;
break;
}
if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
err = "Could not allocate memory\n";
break;
abort();
}
if (status == SWITCH_STATUS_NOUNLOAD) {
module->perm++;
}
loading = 0;
}
if (err) {
switch_core_destroy_memory_pool(&pool);
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_permanent_strdup(filename);
module->pool = pool;
module->filename = switch_core_strdup(module->pool, filename);
module->module_interface = module_interface;
module->switch_module_load = load_func_ptr;
@ -566,7 +916,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filen
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_core_launch_thread(switch_loadable_module_exec, module, module->pool);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name);
return switch_loadable_module_process((char *) module->filename, module);
@ -599,6 +949,8 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
switch_xml_t cfg, xml;
unsigned char all = 0;
unsigned int count = 0;
const char *err;
#ifdef WIN32
const char *ext = ".dll";
@ -633,10 +985,10 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
switch_core_hash_init(&loadable_modules.say_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.management_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
switch_mutex_init(&loadable_modules.mutex, SWITCH_MUTEX_NESTED, loadable_modules.pool);
if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_xml_t mods, ld;
if ((mods = switch_xml_child(cfg, "modules"))) {
for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
const char *val = switch_xml_attr_soft(ld, "module");
@ -644,7 +996,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
continue;
}
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE);
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, &err);
count++;
}
}
@ -664,7 +1016,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
continue;
}
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE);
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, &err);
count++;
}
}
@ -687,6 +1039,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
while (apr_dir_read(&finfo, finfo_flags, module_dir_handle) == APR_SUCCESS) {
const char *fname = finfo.fname;
const char *err;
if (finfo.filetype != APR_REG) {
continue;
@ -704,7 +1057,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
continue;
}
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) fname, SWITCH_FALSE);
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) fname, SWITCH_FALSE, &err);
}
apr_dir_close(module_dir_handle);
}
@ -714,35 +1067,58 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
return SWITCH_STATUS_SUCCESS;
}
static void do_shutdown(switch_loadable_module_t *module)
{
assert(module != NULL);
switch_loadable_module_unprocess(module);
if (module->switch_module_shutdown) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
switch_memory_pool_t *pool;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
switch_dso_unload(module->lib);
module->lib = NULL;
if ((pool = module->pool)) {
module = NULL;
switch_core_destroy_memory_pool(&pool);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
}
switch_core_hash_delete_locked(loadable_modules.module_hash, module->key, loadable_modules.mutex);
}
SWITCH_DECLARE(void) switch_loadable_module_shutdown(void)
{
switch_hash_index_t *hi;
void *val;
switch_loadable_module_t *module;
for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
module = (switch_loadable_module_t *) val;
if (module->switch_module_shutdown) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
switch_dso_unload(module->lib);
module->lib = NULL;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
}
do_shutdown(module);
}
}
SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoint_interface(char *name)
{
return switch_core_hash_find(loadable_modules.endpoint_hash, name);
switch_endpoint_interface_t *ptr;
switch_mutex_lock(loadable_modules.mutex);
ptr = switch_core_hash_find(loadable_modules.endpoint_hash, name);
switch_mutex_unlock(loadable_modules.mutex);
return ptr;
}
SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_interface(char *name)
@ -751,6 +1127,7 @@ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_inte
switch_codec_interface_t *codec;
switch_size_t x;
switch_mutex_lock(loadable_modules.mutex);
if (!(codec = switch_core_hash_find(loadable_modules.codec_hash, name))) {
for (x = 0; x < strlen(name); x++) {
altname[x] = (char) toupper((int) name[x]);
@ -762,62 +1139,63 @@ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_inte
codec = switch_core_hash_find(loadable_modules.codec_hash, altname);
}
}
switch_mutex_unlock(loadable_modules.mutex);
return codec;
}
SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(char *name)
{
return switch_core_hash_find(loadable_modules.dialplan_hash, name);
return switch_core_hash_find_locked(loadable_modules.dialplan_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_interface(char *name)
{
return switch_core_hash_find(loadable_modules.timer_hash, name);
return switch_core_hash_find_locked(loadable_modules.timer_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_application_interface_t *) switch_loadable_module_get_application_interface(char *name)
{
return switch_core_hash_find(loadable_modules.application_hash, name);
return switch_core_hash_find_locked(loadable_modules.application_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_api_interface_t *) switch_loadable_module_get_api_interface(char *name)
{
return switch_core_hash_find(loadable_modules.api_hash, name);
return switch_core_hash_find_locked(loadable_modules.api_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(char *name)
{
return switch_core_hash_find(loadable_modules.file_hash, name);
return switch_core_hash_find_locked(loadable_modules.file_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(char *name)
{
return switch_core_hash_find(loadable_modules.speech_hash, name);
return switch_core_hash_find_locked(loadable_modules.speech_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(char *name)
{
return switch_core_hash_find(loadable_modules.asr_hash, name);
return switch_core_hash_find_locked(loadable_modules.asr_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(char *name)
{
return switch_core_hash_find(loadable_modules.directory_hash, name);
return switch_core_hash_find_locked(loadable_modules.directory_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interface(char *name)
{
return switch_core_hash_find(loadable_modules.chat_hash, name);
return switch_core_hash_find_locked(loadable_modules.chat_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(char *name)
{
return switch_core_hash_find(loadable_modules.say_hash, name);
return switch_core_hash_find_locked(loadable_modules.say_hash, name, loadable_modules.mutex);
}
SWITCH_DECLARE(switch_management_interface_t *) switch_loadable_module_get_management_interface(char *relative_oid)
{
return switch_core_hash_find(loadable_modules.management_hash, relative_oid);
return switch_core_hash_find_locked(loadable_modules.management_hash, relative_oid, loadable_modules.mutex);
}
SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array, int arraylen)
@ -828,6 +1206,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool
int i = 0;
const switch_codec_implementation_t *imp;
switch_mutex_lock(loadable_modules.mutex);
for (hi = switch_hash_first(pool, loadable_modules.codec_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
codec_interface = (switch_codec_interface_t *) val;
@ -848,6 +1227,8 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool
}
}
switch_mutex_unlock(loadable_modules.mutex);
return i;
}
@ -858,6 +1239,8 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
switch_codec_interface_t *codec_interface;
const switch_codec_implementation_t *imp;
switch_mutex_lock(loadable_modules.mutex);
for (x = 0; x < preflen; x++) {
char *cur, *last = NULL, *next = NULL, *name, *p, buf[256];
uint32_t interval = 0, rate = 0;
@ -930,6 +1313,9 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
}
}
switch_mutex_unlock(loadable_modules.mutex);
return i;
}