2005-11-19 20:07:43 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Anthony Minessale II < anthmct @ yahoo . com >
*
*
* switch_loadable_module . c - - Loadable Modules
*
*/
2006-03-06 03:23:34 +00:00
# include <switch.h>
2007-03-09 20:44:13 +00:00
/* for apr_pstrcat */
# include <apr_strings.h>
/* for apr_env_get and apr_env_set */
# include <apr_env.h>
/* for apr file and directory handling */
# include <apr_file_io.h>
2005-11-19 20:07:43 +00:00
struct switch_loadable_module {
char * filename ;
2006-04-30 18:24:24 +00:00
const switch_loadable_module_interface_t * module_interface ;
2005-11-19 20:07:43 +00:00
void * lib ;
2006-03-30 23:02:50 +00:00
switch_module_load_t switch_module_load ;
switch_module_runtime_t switch_module_runtime ;
switch_module_shutdown_t switch_module_shutdown ;
2005-11-19 20:07:43 +00:00
} ;
struct switch_loadable_module_container {
2006-04-29 01:00:52 +00:00
switch_hash_t * module_hash ;
switch_hash_t * endpoint_hash ;
switch_hash_t * codec_hash ;
switch_hash_t * dialplan_hash ;
switch_hash_t * timer_hash ;
switch_hash_t * application_hash ;
switch_hash_t * api_hash ;
switch_hash_t * file_hash ;
switch_hash_t * speech_hash ;
2006-11-09 05:39:04 +00:00
switch_hash_t * asr_hash ;
2006-04-29 01:00:52 +00:00
switch_hash_t * directory_hash ;
2006-10-19 07:13:34 +00:00
switch_hash_t * chat_hash ;
2006-12-20 21:25:14 +00:00
switch_hash_t * say_hash ;
2007-03-07 18:34:22 +00:00
switch_hash_t * management_hash ;
2006-04-29 01:00:52 +00:00
switch_memory_pool_t * pool ;
2005-11-19 20:07:43 +00:00
} ;
static struct switch_loadable_module_container loadable_modules ;
2006-04-29 01:00:52 +00:00
static void * switch_loadable_module_exec ( switch_thread_t * thread , void * obj )
2005-11-19 20:07:43 +00:00
{
2006-03-30 23:02:50 +00:00
2006-04-29 23:43:28 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2006-04-29 06:05:03 +00:00
switch_core_thread_session_t * ts = obj ;
switch_loadable_module_t * module = ts - > objs [ 0 ] ;
2005-11-19 20:07:43 +00:00
int restarts ;
2006-03-31 16:10:00 +00:00
assert ( thread ! = NULL ) ;
2005-11-19 20:07:43 +00:00
assert ( module ! = NULL ) ;
for ( restarts = 0 ; status ! = SWITCH_STATUS_TERM ; restarts + + ) {
status = module - > switch_module_runtime ( ) ;
}
2007-03-01 17:23:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Thread ended for %s \n " , module - > module_interface - > module_name ) ;
2005-12-22 18:53:33 +00:00
if ( ts - > pool ) {
2006-04-29 01:00:52 +00:00
switch_memory_pool_t * pool = ts - > pool ;
2006-04-30 18:24:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Destroying Pool for %s \n " , module - > module_interface - > module_name ) ;
2005-12-22 18:53:33 +00:00
switch_core_destroy_memory_pool ( & pool ) ;
}
2006-01-04 01:04:33 +00:00
switch_yield ( 1000000 ) ;
2005-11-19 20:07:43 +00:00
return NULL ;
}
2006-02-22 22:36:52 +00:00
2006-03-30 23:02:50 +00:00
2007-03-17 19:51:08 +00:00
static void switch_loadable_module_runtime ( void )
{
switch_hash_index_t * hi ;
void * val ;
switch_loadable_module_t * module ;
2006-04-25 00:33:00 +00:00
2007-03-17 19:51:08 +00:00
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_runtime ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Starting runtime thread for %s \n " , module - > module_interface - > module_name ) ;
switch_core_launch_thread ( switch_loadable_module_exec , module , loadable_modules . pool ) ;
}
}
}
2006-04-25 00:33:00 +00:00
2006-04-29 23:43:28 +00:00
static switch_status_t switch_loadable_module_process ( char * key , switch_loadable_module_t * new_module )
2006-04-25 00:33:00 +00:00
{
2006-05-01 19:44:21 +00:00
switch_event_t * event ;
2006-04-25 00:33:00 +00:00
switch_core_hash_insert ( loadable_modules . module_hash , key , new_module ) ;
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > endpoint_interface ) {
2006-04-29 23:43:28 +00:00
const switch_endpoint_interface_t * ptr ;
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > endpoint_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load endpoint interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Endpoint '%s' \n " , ptr - > interface_name ) ;
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . endpoint_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2007-02-23 18:24:31 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > codec_interface ) {
2006-04-29 06:05:03 +00:00
const switch_codec_implementation_t * impl ;
2006-04-29 23:43:28 +00:00
const switch_codec_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > codec_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load codec interface from %s due to no interface name. \n " , key ) ;
} else {
2007-02-23 19:15:43 +00:00
unsigned load_interface = 1 ;
2007-02-23 18:24:31 +00:00
for ( impl = ptr - > implementations ; impl ; impl = impl - > next ) {
2007-02-23 19:15:43 +00:00
if ( ! impl - > iananame ) {
load_interface = 0 ;
break ;
2007-02-23 18:24:31 +00:00
}
2006-06-23 20:14:29 +00:00
}
2007-02-23 19:15:43 +00:00
if ( ! load_interface ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load codec interface %s from %s due to no iana name in an implementation. \n " , ptr - > interface_name , key ) ;
} else {
for ( impl = ptr - > implementations ; impl ; impl = impl - > next ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE ,
" Adding 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_insert ( loadable_modules . codec_hash , impl - > iananame , ( const void * ) ptr ) ;
}
}
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 18:24:31 +00:00
}
2006-04-25 00:33:00 +00:00
}
2007-02-23 18:24:31 +00:00
}
2006-04-25 00:33:00 +00:00
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > dialplan_interface ) {
2006-04-29 23:43:28 +00:00
const switch_dialplan_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > dialplan_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load dialplan interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Dialplan '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . dialplan_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > timer_interface ) {
2006-04-29 23:43:28 +00:00
const switch_timer_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > timer_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load timer interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Timer '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . timer_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > application_interface ) {
2006-04-29 23:43:28 +00:00
const switch_application_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > application_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load application interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Application '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
2007-02-23 19:15:43 +00:00
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 ) ) ;
2007-02-23 18:24:31 +00:00
switch_event_fire ( & event ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . application_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > api_interface ) {
2006-04-29 23:43:28 +00:00
const switch_api_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > api_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load api interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding API Function '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
2007-02-23 19:15:43 +00:00
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 ) ) ;
2007-02-23 18:24:31 +00:00
switch_event_fire ( & event ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . api_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > file_interface ) {
2006-04-29 23:43:28 +00:00
const switch_file_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > file_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load file interface from %s due to no interface name. \n " , key ) ;
} else {
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 ] ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . file_hash , ptr - > extens [ i ] , ( const void * ) ptr ) ;
2007-02-23 18:24:31 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > speech_interface ) {
2006-04-29 23:43:28 +00:00
const switch_speech_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > speech_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load speech interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Speech interface '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . speech_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-11-09 05:39:04 +00:00
if ( new_module - > module_interface - > asr_interface ) {
const switch_asr_interface_t * ptr ;
for ( ptr = new_module - > module_interface - > asr_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load asr interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Asr interface '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . asr_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-11-09 05:39:04 +00:00
}
}
}
2006-04-30 18:24:24 +00:00
if ( new_module - > module_interface - > directory_interface ) {
2006-04-29 23:43:28 +00:00
const switch_directory_interface_t * ptr ;
2006-04-25 00:33:00 +00:00
2006-04-30 18:24:24 +00:00
for ( ptr = new_module - > module_interface - > directory_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load directory interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Directory interface '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . directory_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-05-01 19:44:21 +00:00
}
2006-04-25 00:33:00 +00:00
}
}
2006-10-19 07:13:34 +00:00
if ( new_module - > module_interface - > chat_interface ) {
const switch_chat_interface_t * ptr ;
for ( ptr = new_module - > module_interface - > chat_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load chat interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Chat interface '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . chat_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-10-19 07:13:34 +00:00
}
}
}
2006-12-20 21:25:14 +00:00
if ( new_module - > module_interface - > say_interface ) {
const switch_say_interface_t * ptr ;
for ( ptr = new_module - > module_interface - > say_interface ; ptr ; ptr = ptr - > next ) {
2007-02-23 18:24:31 +00:00
if ( ! ptr - > interface_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load say interface from %s due to no interface name. \n " , key ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Adding Say interface '%s' \n " , ptr - > interface_name ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-02-23 19:15:43 +00:00
switch_core_hash_insert ( loadable_modules . say_hash , ptr - > interface_name , ( const void * ) ptr ) ;
2006-12-20 21:25:14 +00:00
}
}
}
2007-03-07 18:34:22 +00:00
if ( new_module - > module_interface - > management_interface ) {
const switch_management_interface_t * ptr ;
for ( ptr = new_module - > module_interface - > management_interface ; ptr ; ptr = ptr - > next ) {
if ( ! ptr - > relative_oid ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to load management interface from %s due to no interface name. \n " , key ) ;
} else {
2007-03-17 19:51:08 +00:00
if ( switch_core_hash_find ( loadable_modules . management_hash , ptr - > relative_oid ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR ,
" Failed to load management interface %s. OID %s already exists \n " , key , ptr - > relative_oid ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE ,
" Adding Management interface '%s' OID[%s.%s] \n " , key , FREESWITCH_OID_PREFIX , ptr - > relative_oid ) ;
switch_core_hash_insert ( loadable_modules . management_hash , ptr - > relative_oid , ( const void * ) ptr ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MODULE_LOAD ) = = 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 ) ;
}
2007-03-07 18:34:22 +00:00
}
2007-03-17 19:51:08 +00:00
2007-03-07 18:34:22 +00:00
}
}
}
2006-04-25 00:33:00 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-03-30 23:02:50 +00:00
2006-04-29 23:43:28 +00:00
static switch_status_t switch_loadable_module_load_file ( char * filename , switch_loadable_module_t * * new_module )
2005-11-19 20:07:43 +00:00
{
2006-04-29 06:05:03 +00:00
switch_loadable_module_t * module = NULL ;
2007-03-09 20:44:13 +00:00
switch_dso_handle_t * dso = NULL ;
2006-02-13 18:34:39 +00:00
apr_status_t status = SWITCH_STATUS_SUCCESS ;
2007-03-09 20:44:13 +00:00
switch_dso_handle_sym_t load_function_handle = NULL ;
switch_dso_handle_sym_t shutdown_function_handle = NULL ;
switch_dso_handle_sym_t runtime_function_handle = NULL ;
2006-04-25 00:33:00 +00:00
switch_module_load_t load_func_ptr = NULL ;
2005-11-19 20:07:43 +00:00
int loading = 1 ;
const char * err = NULL ;
2006-04-30 18:24:24 +00:00
switch_loadable_module_interface_t * module_interface = NULL ;
2006-02-13 18:34:39 +00:00
char derr [ 512 ] = " " ;
2005-11-19 20:07:43 +00:00
assert ( filename ! = NULL ) ;
* new_module = NULL ;
2007-03-09 20:44:13 +00:00
status = switch_dso_load ( & dso , filename , loadable_modules . pool ) ;
2005-11-19 20:07:43 +00:00
while ( loading ) {
if ( status ! = APR_SUCCESS ) {
2007-03-09 20:44:13 +00:00
switch_dso_error ( dso , derr , sizeof ( derr ) ) ;
2005-11-19 20:07:43 +00:00
err = derr ;
break ;
}
2007-03-09 20:44:13 +00:00
status = switch_dso_sym ( & load_function_handle , dso , " switch_module_load " ) ;
2007-02-13 22:15:24 +00:00
load_func_ptr = ( switch_module_load_t ) ( intptr_t ) load_function_handle ;
2005-11-19 20:07:43 +00:00
if ( load_func_ptr = = NULL ) {
2006-12-18 20:08:45 +00:00
err = " Cannot locate symbol 'switch_module_load' please make sure this is a vaild module. " ;
2005-11-19 20:07:43 +00:00
break ;
}
2006-04-30 18:24:24 +00:00
if ( load_func_ptr ( & module_interface , filename ) ! = SWITCH_STATUS_SUCCESS ) {
2005-11-19 20:07:43 +00:00
err = " Module load routine returned an error " ;
2006-04-30 18:24:24 +00:00
module_interface = NULL ;
2005-11-19 20:07:43 +00:00
break ;
}
2006-07-27 15:45:19 +00:00
if ( ( module = switch_core_permanent_alloc ( sizeof ( switch_loadable_module_t ) ) ) = = 0 ) {
2005-11-19 20:07:43 +00:00
err = " Could not allocate memory \n " ;
break ;
}
loading = 0 ;
}
if ( err ) {
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Error Loading module %s \n **%s** \n " , filename , err ) ;
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_GENERR ;
}
2006-07-27 15:45:19 +00:00
module - > filename = switch_core_permanent_strdup ( filename ) ;
2006-04-30 18:24:24 +00:00
module - > module_interface = module_interface ;
2005-11-19 20:07:43 +00:00
module - > switch_module_load = load_func_ptr ;
2007-03-09 20:44:13 +00:00
switch_dso_sym ( & shutdown_function_handle , dso , " switch_module_shutdown " ) ;
2007-02-13 22:15:24 +00:00
module - > switch_module_shutdown = ( switch_module_shutdown_t ) ( intptr_t ) shutdown_function_handle ;
2007-03-09 20:44:13 +00:00
switch_dso_sym ( & runtime_function_handle , dso , " switch_module_runtime " ) ;
2007-02-13 22:15:24 +00:00
module - > switch_module_runtime = ( switch_module_runtime_t ) ( intptr_t ) runtime_function_handle ;
2005-11-19 20:07:43 +00:00
module - > lib = dso ;
* new_module = module ;
2006-04-30 18:24:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Successfully Loaded [%s] \n " , module_interface - > module_name ) ;
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-17 19:51:08 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_loadable_module_load_module ( char * dir , char * fname , switch_bool_t runtime )
2006-02-14 16:26:24 +00:00
{
2006-03-30 23:02:50 +00:00
switch_size_t len = 0 ;
2006-02-14 16:26:24 +00:00
char * path ;
char * file ;
2006-04-29 06:05:03 +00:00
switch_loadable_module_t * new_module = NULL ;
2006-04-29 23:43:28 +00:00
switch_status_t status ;
2006-02-14 16:26:24 +00:00
2006-02-14 17:31:20 +00:00
# ifdef WIN32
const char * ext = " .dll " ;
2006-03-05 23:44:04 +00:00
# elif defined (MACOSX) || defined (DARWIN)
const char * ext = " .dylib " ;
2006-02-14 17:31:20 +00:00
# else
const char * ext = " .so " ;
# endif
2006-02-20 00:23:25 +00:00
if ( ( file = switch_core_strdup ( loadable_modules . pool , fname ) ) = = 0 ) {
2006-04-20 00:58:06 +00:00
return SWITCH_STATUS_FALSE ;
2006-02-14 16:26:24 +00:00
}
if ( * file = = ' / ' ) {
path = switch_core_strdup ( loadable_modules . pool , file ) ;
} else {
2006-02-14 17:31:20 +00:00
if ( strchr ( file , ' . ' ) ) {
2006-03-30 23:02:50 +00:00
len = strlen ( dir ) ;
len + = strlen ( file ) ;
len + = 4 ;
2006-02-14 17:31:20 +00:00
path = ( char * ) switch_core_alloc ( loadable_modules . pool , len ) ;
2006-03-03 08:26:00 +00:00
snprintf ( path , len , " %s%s%s " , dir , SWITCH_PATH_SEPARATOR , file ) ;
2006-02-14 17:31:20 +00:00
} else {
2006-03-30 23:02:50 +00:00
len = strlen ( dir ) ;
len + = strlen ( file ) ;
len + = 8 ;
2006-02-14 17:31:20 +00:00
path = ( char * ) switch_core_alloc ( loadable_modules . pool , len ) ;
2006-03-03 08:26:00 +00:00
snprintf ( path , len , " %s%s%s%s " , dir , SWITCH_PATH_SEPARATOR , file , ext ) ;
2006-02-14 17:31:20 +00:00
}
2006-02-14 16:26:24 +00:00
}
2006-12-01 16:08:56 +00:00
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 ;
}
2006-04-25 00:33:00 +00:00
if ( ( status = switch_loadable_module_load_file ( path , & new_module ) = = SWITCH_STATUS_SUCCESS ) ) {
2007-03-17 19:51:08 +00:00
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 ) ;
}
}
2006-02-14 16:26:24 +00:00
}
2007-03-17 19:51:08 +00:00
return status ;
2006-02-14 16:26:24 +00:00
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_loadable_module_build_dynamic ( char * filename ,
2006-04-25 00:33:00 +00:00
switch_module_load_t switch_module_load ,
switch_module_runtime_t switch_module_runtime ,
switch_module_shutdown_t switch_module_shutdown )
{
2006-04-29 06:05:03 +00:00
switch_loadable_module_t * module = NULL ;
2006-04-25 04:09:34 +00:00
switch_module_load_t load_func_ptr = NULL ;
int loading = 1 ;
const char * err = NULL ;
2006-04-30 18:24:24 +00:00
switch_loadable_module_interface_t * module_interface = NULL ;
2006-04-25 00:33:00 +00:00
2006-07-27 15:45:19 +00:00
if ( ( module = switch_core_permanent_alloc ( sizeof ( switch_loadable_module_t ) ) ) = = 0 ) {
2006-04-25 00:33:00 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Couldn't allocate memory \n " ) ;
return SWITCH_STATUS_GENERR ;
}
while ( loading ) {
load_func_ptr = ( switch_module_load_t ) switch_module_load ;
if ( load_func_ptr = = NULL ) {
err = " Cannot Load " ;
break ;
}
2006-04-30 18:24:24 +00:00
if ( load_func_ptr ( & module_interface , filename ) ! = SWITCH_STATUS_SUCCESS ) {
2006-04-25 00:33:00 +00:00
err = " Module load routine returned an error " ;
2006-04-30 18:24:24 +00:00
module_interface = NULL ;
2006-04-25 00:33:00 +00:00
break ;
}
2006-07-27 15:45:19 +00:00
if ( ( module = switch_core_permanent_alloc ( sizeof ( switch_loadable_module_t ) ) ) = = 0 ) {
2006-04-25 00:33:00 +00:00
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 ;
}
2006-07-27 15:45:19 +00:00
module - > filename = switch_core_permanent_strdup ( filename ) ;
2006-04-30 18:24:24 +00:00
module - > module_interface = module_interface ;
2006-04-25 00:33:00 +00:00
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 ) ;
}
2006-04-30 18:24:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Successfully Loaded [%s] \n " , module_interface - > module_name ) ;
2006-04-25 00:33:00 +00:00
return switch_loadable_module_process ( ( char * ) module - > filename , module ) ;
}
2006-03-06 03:23:34 +00:00
# ifdef WIN32
static void switch_loadable_module_path_init ( )
{
char * path = NULL , * working = NULL ;
apr_dir_t * perl_dir_handle = NULL ;
2006-03-06 20:35:23 +00:00
apr_env_get ( & path , " path " , loadable_modules . pool ) ;
apr_filepath_get ( & working , APR_FILEPATH_NATIVE , loadable_modules . pool ) ;
if ( apr_dir_open ( & perl_dir_handle , " . \\ perl " , loadable_modules . pool ) = = APR_SUCCESS ) {
apr_dir_close ( perl_dir_handle ) ;
apr_env_set ( " path " ,
apr_pstrcat ( loadable_modules . pool , path , " ; " , working , " \\ perl " , NULL ) ,
loadable_modules . pool ) ;
}
2006-03-06 03:23:34 +00:00
}
# endif
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_loadable_module_init ( )
2005-11-19 20:07:43 +00:00
{
2006-02-13 18:34:39 +00:00
apr_finfo_t finfo = { 0 } ;
apr_dir_t * module_dir_handle = NULL ;
2006-01-20 15:05:05 +00:00
apr_int32_t finfo_flags = APR_FINFO_DIRENT | APR_FINFO_TYPE | APR_FINFO_NAME ;
2006-02-14 16:26:24 +00:00
char * cf = " modules.conf " ;
2006-05-10 03:23:05 +00:00
char * pcf = " post_load_modules.conf " ;
switch_xml_t cfg , xml ;
2006-02-14 16:26:24 +00:00
unsigned char all = 0 ;
unsigned int count = 0 ;
2005-11-19 20:07:43 +00:00
# ifdef WIN32
const char * ext = " .dll " ;
const char * EXT = " .DLL " ;
2006-03-05 23:44:04 +00:00
# elif defined (MACOSX) || defined (DARWIN)
const char * ext = " .dylib " ;
const char * EXT = " .DYLIB " ;
2005-11-19 20:07:43 +00:00
# else
const char * ext = " .so " ;
const char * EXT = " .SO " ;
# endif
memset ( & loadable_modules , 0 , sizeof ( loadable_modules ) ) ;
switch_core_new_memory_pool ( & loadable_modules . pool ) ;
2006-03-06 03:23:34 +00:00
# ifdef WIN32
2006-03-06 20:35:23 +00:00
switch_loadable_module_path_init ( ) ;
2006-03-06 03:23:34 +00:00
# endif
2005-11-19 20:07:43 +00:00
switch_core_hash_init ( & loadable_modules . module_hash , loadable_modules . pool ) ;
switch_core_hash_init ( & loadable_modules . endpoint_hash , loadable_modules . pool ) ;
switch_core_hash_init ( & loadable_modules . codec_hash , loadable_modules . pool ) ;
switch_core_hash_init ( & loadable_modules . timer_hash , loadable_modules . pool ) ;
switch_core_hash_init ( & loadable_modules . application_hash , loadable_modules . pool ) ;
2005-12-09 19:33:21 +00:00
switch_core_hash_init ( & loadable_modules . api_hash , loadable_modules . pool ) ;
2005-12-26 21:01:22 +00:00
switch_core_hash_init ( & loadable_modules . file_hash , loadable_modules . pool ) ;
2006-01-27 16:43:57 +00:00
switch_core_hash_init ( & loadable_modules . speech_hash , loadable_modules . pool ) ;
2006-11-09 05:39:04 +00:00
switch_core_hash_init ( & loadable_modules . asr_hash , loadable_modules . pool ) ;
2006-02-09 16:28:49 +00:00
switch_core_hash_init ( & loadable_modules . directory_hash , loadable_modules . pool ) ;
2006-10-19 07:13:34 +00:00
switch_core_hash_init ( & loadable_modules . chat_hash , loadable_modules . pool ) ;
2006-12-20 21:25:14 +00:00
switch_core_hash_init ( & loadable_modules . say_hash , loadable_modules . pool ) ;
2007-03-07 18:34:22 +00:00
switch_core_hash_init ( & loadable_modules . management_hash , loadable_modules . pool ) ;
2005-11-19 20:07:43 +00:00
switch_core_hash_init ( & loadable_modules . dialplan_hash , loadable_modules . pool ) ;
2006-05-10 15:47:54 +00:00
if ( ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
2006-05-10 03:23:05 +00:00
switch_xml_t mods , ld ;
2005-11-19 20:07:43 +00:00
2006-05-10 03:23:05 +00:00
if ( ( mods = switch_xml_child ( cfg , " modules " ) ) ) {
for ( ld = switch_xml_child ( mods , " load " ) ; ld ; ld = ld - > next ) {
2006-05-17 00:58:21 +00:00
const char * val = switch_xml_attr_soft ( ld , " module " ) ;
2006-05-10 03:23:05 +00:00
if ( strchr ( val , ' . ' ) & & ! strstr ( val , ext ) & & ! strstr ( val , EXT ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Invalid extension for %s \n " , val ) ;
continue ;
2005-11-19 20:07:43 +00:00
}
2007-03-17 19:51:08 +00:00
switch_loadable_module_load_module ( ( char * ) SWITCH_GLOBAL_dirs . mod_dir , ( char * ) val , SWITCH_FALSE ) ;
2006-05-10 03:23:05 +00:00
count + + ;
2005-11-19 20:07:43 +00:00
}
2006-02-14 16:26:24 +00:00
}
2006-05-10 03:23:05 +00:00
switch_xml_free ( xml ) ;
2006-02-14 16:26:24 +00:00
} else {
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " open of %s failed \n " , cf ) ;
2006-02-14 16:26:24 +00:00
}
2005-11-19 20:07:43 +00:00
2006-05-10 15:47:54 +00:00
if ( ( xml = switch_xml_open_cfg ( pcf , & cfg , NULL ) ) ) {
2006-05-10 03:23:05 +00:00
switch_xml_t mods , ld ;
if ( ( mods = switch_xml_child ( cfg , " modules " ) ) ) {
for ( ld = switch_xml_child ( mods , " load " ) ; ld ; ld = ld - > next ) {
2006-05-17 00:58:21 +00:00
const char * val = switch_xml_attr_soft ( ld , " module " ) ;
2006-05-10 03:23:05 +00:00
if ( strchr ( val , ' . ' ) & & ! strstr ( val , ext ) & & ! strstr ( val , EXT ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Invalid extension for %s \n " , val ) ;
continue ;
}
2007-03-17 19:51:08 +00:00
switch_loadable_module_load_module ( ( char * ) SWITCH_GLOBAL_dirs . mod_dir , ( char * ) val , SWITCH_FALSE ) ;
2006-05-10 03:23:05 +00:00
count + + ;
}
}
switch_xml_free ( xml ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " open of %s failed \n " , pcf ) ;
2006-02-14 16:26:24 +00:00
}
2005-11-19 20:07:43 +00:00
2006-05-10 03:23:05 +00:00
if ( ! count ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " No modules loaded assuming 'load all' \n " ) ;
all = 1 ;
}
2006-02-14 16:26:24 +00:00
if ( all ) {
2006-02-28 21:21:48 +00:00
if ( apr_dir_open ( & module_dir_handle , SWITCH_GLOBAL_dirs . mod_dir , loadable_modules . pool ) ! = APR_SUCCESS ) {
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Can't open directory: %s \n " , SWITCH_GLOBAL_dirs . mod_dir ) ;
2006-02-14 16:26:24 +00:00
return SWITCH_STATUS_GENERR ;
}
2005-11-19 20:07:43 +00:00
2006-02-14 16:26:24 +00:00
while ( apr_dir_read ( & finfo , finfo_flags , module_dir_handle ) = = APR_SUCCESS ) {
const char * fname = finfo . fname ;
2005-11-19 20:07:43 +00:00
2006-02-14 16:26:24 +00:00
if ( finfo . filetype ! = APR_REG ) {
continue ;
2005-11-19 20:07:43 +00:00
}
2006-02-14 16:26:24 +00:00
if ( ! fname ) {
fname = finfo . name ;
2005-12-09 19:33:21 +00:00
}
2006-03-30 23:02:50 +00:00
if ( ! fname ) {
2006-02-14 16:26:24 +00:00
continue ;
2005-12-26 21:01:22 +00:00
}
2006-02-14 16:26:24 +00:00
if ( ! strstr ( fname , ext ) & & ! strstr ( fname , EXT ) ) {
continue ;
2006-01-27 16:43:57 +00:00
}
2006-02-09 16:28:49 +00:00
2007-03-17 19:51:08 +00:00
switch_loadable_module_load_module ( ( char * ) SWITCH_GLOBAL_dirs . mod_dir , ( char * ) fname , SWITCH_FALSE ) ;
2005-11-19 20:07:43 +00:00
}
2006-02-14 16:26:24 +00:00
apr_dir_close ( module_dir_handle ) ;
2005-11-19 20:07:43 +00:00
}
2007-03-17 19:51:08 +00:00
switch_loadable_module_runtime ( ) ;
2006-05-10 03:23:05 +00:00
2005-11-19 20:07:43 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-01-05 21:03:22 +00:00
SWITCH_DECLARE ( void ) switch_loadable_module_shutdown ( void )
2005-11-19 20:07:43 +00:00
{
2006-01-20 15:05:05 +00:00
switch_hash_index_t * hi ;
2005-11-19 20:07:43 +00:00
void * val ;
2006-04-29 06:05:03 +00:00
switch_loadable_module_t * module ;
2005-11-19 20:07:43 +00:00
2005-12-14 22:46:09 +00:00
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 ) ;
2006-04-29 06:05:03 +00:00
module = ( switch_loadable_module_t * ) val ;
2006-11-09 05:39:04 +00:00
2005-11-19 20:07:43 +00:00
if ( module - > switch_module_shutdown ) {
2006-11-09 05:39:04 +00:00
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 ) ;
2007-03-09 20:44:13 +00:00
switch_dso_unload ( module - > lib ) ;
2006-11-09 05:39:04 +00:00
module - > lib = NULL ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " %s shutdown. \n " , module - > module_interface - > module_name ) ;
}
2005-11-19 20:07:43 +00:00
} else {
2006-11-09 05:39:04 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " %s has no shutdown routine \n " , module - > module_interface - > module_name ) ;
2005-11-19 20:07:43 +00:00
}
}
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_endpoint_interface_t * ) switch_loadable_module_get_endpoint_interface ( char * name )
2005-11-19 20:07:43 +00:00
{
return switch_core_hash_find ( loadable_modules . endpoint_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_codec_interface_t * ) switch_loadable_module_get_codec_interface ( char * name )
2005-11-19 20:07:43 +00:00
{
2006-05-03 17:15:17 +00:00
char altname [ 256 ] = " " ;
switch_codec_interface_t * codec ;
2006-05-04 16:01:38 +00:00
switch_size_t x ;
2006-05-03 16:55:30 +00:00
2006-05-03 17:15:17 +00:00
if ( ! ( codec = switch_core_hash_find ( loadable_modules . codec_hash , name ) ) ) {
for ( x = 0 ; x < strlen ( name ) ; x + + ) {
2006-10-01 21:21:41 +00:00
altname [ x ] = ( char ) toupper ( ( int ) name [ x ] ) ;
2006-05-03 17:15:17 +00:00
}
if ( ! ( codec = switch_core_hash_find ( loadable_modules . codec_hash , altname ) ) ) {
for ( x = 0 ; x < strlen ( name ) ; x + + ) {
2006-10-01 21:21:41 +00:00
altname [ x ] = ( char ) tolower ( ( int ) name [ x ] ) ;
2006-05-03 17:15:17 +00:00
}
codec = switch_core_hash_find ( loadable_modules . codec_hash , altname ) ;
}
2006-05-03 16:55:30 +00:00
}
2006-05-03 17:15:17 +00:00
return codec ;
2005-11-19 20:07:43 +00:00
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_dialplan_interface_t * ) switch_loadable_module_get_dialplan_interface ( char * name )
2005-11-19 20:07:43 +00:00
{
return switch_core_hash_find ( loadable_modules . dialplan_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_timer_interface_t * ) switch_loadable_module_get_timer_interface ( char * name )
2005-11-19 20:07:43 +00:00
{
return switch_core_hash_find ( loadable_modules . timer_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_application_interface_t * ) switch_loadable_module_get_application_interface ( char * name )
2005-11-19 20:07:43 +00:00
{
return switch_core_hash_find ( loadable_modules . application_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_api_interface_t * ) switch_loadable_module_get_api_interface ( char * name )
2005-12-09 19:33:21 +00:00
{
return switch_core_hash_find ( loadable_modules . api_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_file_interface_t * ) switch_loadable_module_get_file_interface ( char * name )
2005-12-26 21:01:22 +00:00
{
return switch_core_hash_find ( loadable_modules . file_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_speech_interface_t * ) switch_loadable_module_get_speech_interface ( char * name )
2006-01-27 16:43:57 +00:00
{
return switch_core_hash_find ( loadable_modules . speech_hash , name ) ;
}
2006-11-09 05:39:04 +00:00
SWITCH_DECLARE ( switch_asr_interface_t * ) switch_loadable_module_get_asr_interface ( char * name )
{
return switch_core_hash_find ( loadable_modules . asr_hash , name ) ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_directory_interface_t * ) switch_loadable_module_get_directory_interface ( char * name )
2006-02-09 16:28:49 +00:00
{
return switch_core_hash_find ( loadable_modules . directory_hash , name ) ;
}
2006-10-19 07:13:34 +00:00
SWITCH_DECLARE ( switch_chat_interface_t * ) switch_loadable_module_get_chat_interface ( char * name )
{
return switch_core_hash_find ( loadable_modules . chat_hash , name ) ;
}
2006-12-20 21:25:14 +00:00
SWITCH_DECLARE ( switch_say_interface_t * ) switch_loadable_module_get_say_interface ( char * name )
{
return switch_core_hash_find ( loadable_modules . say_hash , name ) ;
}
2007-03-07 18:34:22 +00:00
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 ) ;
}
2006-07-10 22:08:02 +00:00
SWITCH_DECLARE ( int ) switch_loadable_module_get_codecs ( switch_memory_pool_t * pool , const switch_codec_implementation_t * * array ,
2006-01-20 15:05:05 +00:00
int arraylen )
2005-11-19 20:07:43 +00:00
{
2006-01-20 15:05:05 +00:00
switch_hash_index_t * hi ;
2005-11-19 20:07:43 +00:00
void * val ;
2006-07-10 22:08:02 +00:00
switch_codec_interface_t * codec_interface ;
2005-11-19 20:07:43 +00:00
int i = 0 ;
2007-01-29 18:31:35 +00:00
const switch_codec_implementation_t * imp ;
2005-11-19 20:07:43 +00:00
2005-12-14 22:46:09 +00:00
for ( hi = switch_hash_first ( pool , loadable_modules . codec_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
switch_hash_this ( hi , NULL , NULL , & val ) ;
2006-07-10 22:08:02 +00:00
codec_interface = ( switch_codec_interface_t * ) val ;
2007-01-29 18:31:35 +00:00
/* Look for a 20ms implementation because it's the safest choice */
for ( imp = codec_interface - > implementations ; imp ; imp = imp - > next ) {
if ( imp - > microseconds_per_frame / 1000 = = 20 ) {
array [ i + + ] = imp ;
goto found ;
}
}
/* oh well we will use what we have */
2006-07-10 22:08:02 +00:00
array [ i + + ] = codec_interface - > implementations ;
2007-01-29 18:31:35 +00:00
found :
2005-11-19 20:07:43 +00:00
if ( i > arraylen ) {
break ;
}
}
return i ;
}
2006-02-22 22:36:52 +00:00
2006-07-10 22:08:02 +00:00
SWITCH_DECLARE ( int ) switch_loadable_module_get_codecs_sorted ( const switch_codec_implementation_t * * array ,
2006-01-20 15:05:05 +00:00
int arraylen , char * * prefs , int preflen )
2005-12-06 17:18:56 +00:00
{
int x , i = 0 ;
2006-04-29 23:43:28 +00:00
switch_codec_interface_t * codec_interface ;
2006-07-10 22:08:02 +00:00
const switch_codec_implementation_t * imp ;
for ( x = 0 ; x < preflen ; x + + ) {
2006-07-14 19:42:09 +00:00
char * cur , * last = NULL , * next = NULL , * name , * p , buf [ 256 ] ;
uint32_t interval = 0 , rate = 0 ;
switch_copy_string ( buf , prefs [ x ] , sizeof ( buf ) ) ;
last = name = next = cur = buf ;
for ( ; ; ) {
if ( ! next ) {
break ;
}
if ( ( p = strchr ( next , ' @ ' ) ) ) {
* p + + = ' \0 ' ;
}
next = p ;
if ( cur ! = name ) {
if ( strchr ( cur , ' i ' ) ) {
interval = atoi ( cur ) ;
} else if ( strchr ( cur , ' k ' ) ) {
rate = atoi ( cur ) ;
}
}
cur = next ;
}
2006-07-10 22:08:02 +00:00
if ( ( codec_interface = switch_loadable_module_get_codec_interface ( name ) ) ! = 0 ) {
2007-01-29 15:43:41 +00:00
/* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
if ( ! interval ) {
for ( imp = codec_interface - > implementations ; imp ; imp = imp - > next ) {
uint8_t match = 1 ;
if ( ( uint32_t ) ( imp - > microseconds_per_frame / 1000 ) ! = 20 ) {
match = 0 ;
}
if ( match & & rate & & ( uint32_t ) imp - > samples_per_second ! = rate ) {
match = 0 ;
}
if ( match ) {
array [ i + + ] = imp ;
goto found ;
}
}
}
/* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available*/
2006-07-10 22:08:02 +00:00
for ( imp = codec_interface - > implementations ; imp ; imp = imp - > next ) {
2006-07-14 19:42:09 +00:00
uint8_t match = 1 ;
if ( interval & & ( uint32_t ) ( imp - > microseconds_per_frame / 1000 ) ! = interval ) {
match = 0 ;
}
if ( match & & rate & & ( uint32_t ) imp - > samples_per_second ! = rate ) {
match = 0 ;
}
if ( match ) {
2006-07-10 22:08:02 +00:00
array [ i + + ] = imp ;
2007-01-29 15:43:41 +00:00
goto found ;
2006-07-10 22:08:02 +00:00
}
2006-02-21 15:05:18 +00:00
}
2007-01-29 15:43:41 +00:00
found :
2006-07-10 22:08:02 +00:00
if ( i > arraylen ) {
break ;
}
}
}
2005-12-06 17:18:56 +00:00
return i ;
}
2005-12-23 02:55:25 +00:00
2006-07-26 20:12:49 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_api_execute ( char * cmd , char * arg , switch_core_session_t * session , switch_stream_handle_t * stream )
2005-12-23 02:55:25 +00:00
{
2006-04-29 23:43:28 +00:00
switch_api_interface_t * api ;
switch_status_t status ;
2005-12-23 02:55:25 +00:00
2006-05-10 15:47:54 +00:00
assert ( stream ! = NULL ) ;
assert ( stream - > data ! = NULL ) ;
assert ( stream - > write_function ! = NULL ) ;
2006-05-10 19:07:38 +00:00
if ( ! stream - > event ) {
switch_event_create ( & stream - > event , SWITCH_EVENT_API ) ;
}
if ( stream - > event ) {
if ( cmd ) {
2007-02-13 04:43:49 +00:00
switch_event_add_header ( stream - > event , SWITCH_STACK_BOTTOM , " API-Command " , " %s " , cmd ) ;
2006-05-10 19:07:38 +00:00
}
if ( arg ) {
2007-02-13 04:43:49 +00:00
switch_event_add_header ( stream - > event , SWITCH_STACK_BOTTOM , " API-Command-Argument " , " %s " , arg ) ;
2006-05-10 19:07:38 +00:00
}
}
2006-02-20 00:23:25 +00:00
if ( ( api = switch_loadable_module_get_api_interface ( cmd ) ) ! = 0 ) {
2006-07-26 20:12:49 +00:00
status = api - > function ( arg , session , stream ) ;
2005-12-23 02:55:25 +00:00
} else {
2005-12-23 03:12:39 +00:00
status = SWITCH_STATUS_FALSE ;
2006-05-10 15:47:54 +00:00
stream - > write_function ( stream , " INVALID COMMAND [%s] " , cmd ) ;
2007-03-04 01:52:52 +00:00
/* snprintf(retbuf, len, "INVALID COMMAND [%s]", cmd); */
2005-12-23 02:55:25 +00:00
}
2006-05-10 19:07:38 +00:00
if ( stream - > event ) {
switch_event_fire ( & stream - > event ) ;
2005-12-23 03:12:39 +00:00
}
return status ;
2005-12-23 02:55:25 +00:00
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2007-02-09 02:36:03 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/