add some write locks to the core and a function to unregister event bindings

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8880 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2008-07-01 23:41:09 +00:00
parent 34215ce00f
commit 43b712b7b1
10 changed files with 269 additions and 63 deletions

View File

@ -599,6 +599,9 @@ SWITCH_DECLARE(void) switch_core_set_variable(_In_z_ const char *varname, _In_op
*/ */
SWITCH_DECLARE(void) switch_core_session_hupall(_In_ switch_call_cause_t cause); SWITCH_DECLARE(void) switch_core_session_hupall(_In_ switch_call_cause_t cause);
SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(_In_ const char *var_name, _In_ const char *var_val, _In_ switch_call_cause_t cause);
SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_interface_t *endpoint_interface, switch_call_cause_t cause);
/*! /*!
\brief Send a message to another session using it's uuid \brief Send a message to another session using it's uuid
\param uuid_str the unique id of the session you want to send a message to \param uuid_str the unique id of the session you want to send a message to

View File

@ -70,14 +70,6 @@ SWITCH_BEGIN_EXTERN_C
struct switch_event_header *next; struct switch_event_header *next;
}; };
/*! \brief A registered custom event subclass */
struct switch_event_subclass {
/*! the owner of the subclass */
char *owner;
/*! the subclass name */
char *name;
};
/*! \brief Representation of an event */ /*! \brief Representation of an event */
struct switch_event { struct switch_event {
/*! the event id (descriptor) */ /*! the event id (descriptor) */
@ -87,7 +79,7 @@ struct switch_event {
/*! the owner of the event */ /*! the owner of the event */
char *owner; char *owner;
/*! the subclass of the event */ /*! the subclass of the event */
switch_event_subclass_t *subclass; char *subclass_name;
/*! the event headers */ /*! the event headers */
switch_event_header_t *headers; switch_event_header_t *headers;
/*! the event headers tail pointer */ /*! the event headers tail pointer */
@ -103,20 +95,7 @@ struct switch_event {
struct switch_event *next; struct switch_event *next;
}; };
/*! \brief A node to store binded events */ struct switch_event_node;
struct switch_event_node {
/*! the id of the node */
char *id;
/*! the event id enumeration to bind to */
switch_event_types_t event_id;
/*! the event subclass to bind to for custom events */
switch_event_subclass_t *subclass;
/*! a callback function to execute when the event is triggered */
switch_event_callback_t callback;
/*! private data */
void *user_data;
struct switch_event_node *next;
};
#define SWITCH_EVENT_SUBCLASS_ANY NULL #define SWITCH_EVENT_SUBCLASS_ANY NULL
@ -228,6 +207,25 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con
SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback, SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback,
void *user_data); void *user_data);
/*!
\brief Bind an event callback to a specific event
\param id an identifier token of the binder
\param event the event enumeration to bind to
\param subclass_name the event subclass to bind to in the case if SWITCH_EVENT_CUSTOM
\param callback the callback functon to bind
\param user_data optional user specific data to pass whenever the callback is invoked
\param node bind handle to later remove the binding.
\return SWITCH_STATUS_SUCCESS if the event was binded
*/
SWITCH_DECLARE(switch_status_t) switch_event_bind_removable(const char *id, switch_event_types_t event, const char *subclass_name,
switch_event_callback_t callback, void *user_data, switch_event_node_t **node);
/*!
\brief Unbind a bound event consumer
\param node node to unbind
\return SWITCH_STATUS_SUCCESS if the consumer was unbinded
*/
SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node);
/*! /*!
\brief Render the name of an event id enumeration \brief Render the name of an event id enumeration
\param event the event id to render the name of \param event the event id to render the name of
@ -253,6 +251,8 @@ SWITCH_DECLARE(switch_status_t) switch_name_event(const char *name, switch_event
*/ */
SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name); SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name);
SWITCH_DECLARE(switch_status_t) switch_event_free_subclass_detailed(const char *owner, const char *subclass_name);
/*! /*!
\brief Render a string representation of an event sutable for printing or network transport \brief Render a string representation of an event sutable for printing or network transport
\param event the event to render \param event the event to render
@ -311,6 +311,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(_In_z_ char
\note the body supplied by this function will supersede an existing body the event may have \note the body supplied by this function will supersede an existing body the event may have
*/ */
#define switch_event_reserve_subclass(subclass_name) switch_event_reserve_subclass_detailed(__FILE__, subclass_name) #define switch_event_reserve_subclass(subclass_name) switch_event_reserve_subclass_detailed(__FILE__, subclass_name)
#define switch_event_free_subclass(subclass_name) switch_event_free_subclass_detailed(__FILE__, subclass_name)
/*! /*!
\brief Create a new event assuming it will not be custom event and therefore hiding the unused parameters \brief Create a new event assuming it will not be custom event and therefore hiding the unused parameters

View File

@ -195,6 +195,8 @@ struct switch_endpoint_interface {
/*! private information */ /*! private information */
void *private_info; void *private_info;
switch_thread_rwlock_t *rwlock;
/* to facilitate linking */ /* to facilitate linking */
struct switch_endpoint_interface *next; struct switch_endpoint_interface *next;
}; };
@ -245,6 +247,7 @@ struct switch_timer_interface {
switch_status_t (*timer_check) (switch_timer_t *, switch_bool_t); switch_status_t (*timer_check) (switch_timer_t *, switch_bool_t);
/*! function to deallocate the timer */ /*! function to deallocate the timer */
switch_status_t (*timer_destroy) (switch_timer_t *); switch_status_t (*timer_destroy) (switch_timer_t *);
switch_thread_rwlock_t *rwlock;
struct switch_timer_interface *next; struct switch_timer_interface *next;
}; };
@ -254,6 +257,7 @@ struct switch_dialplan_interface {
const char *interface_name; const char *interface_name;
/*! the function to read an extension and set a channels dialpan */ /*! the function to read an extension and set a channels dialpan */
switch_dialplan_hunt_function_t hunt_function; switch_dialplan_hunt_function_t hunt_function;
switch_thread_rwlock_t *rwlock;
struct switch_dialplan_interface *next; struct switch_dialplan_interface *next;
}; };
@ -277,6 +281,7 @@ struct switch_file_interface {
switch_status_t (*file_get_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char **string); switch_status_t (*file_get_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char **string);
/*! list of supported file extensions */ /*! list of supported file extensions */
char **extens; char **extens;
switch_thread_rwlock_t *rwlock;
struct switch_file_interface *next; struct switch_file_interface *next;
}; };
@ -353,6 +358,7 @@ struct switch_asr_interface {
switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags); switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*! function to read results from the ASR */ /*! function to read results from the ASR */
switch_status_t (*asr_get_results) (switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags); switch_status_t (*asr_get_results) (switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
switch_thread_rwlock_t *rwlock;
struct switch_asr_interface *next; struct switch_asr_interface *next;
}; };
@ -393,7 +399,7 @@ struct switch_speech_interface {
void (*speech_text_param_tts) (switch_speech_handle_t *sh, char *param, const char *val); void (*speech_text_param_tts) (switch_speech_handle_t *sh, char *param, const char *val);
void (*speech_numeric_param_tts) (switch_speech_handle_t *sh, char *param, int val); void (*speech_numeric_param_tts) (switch_speech_handle_t *sh, char *param, int val);
void (*speech_float_param_tts) (switch_speech_handle_t *sh, char *param, double val); void (*speech_float_param_tts) (switch_speech_handle_t *sh, char *param, double val);
switch_thread_rwlock_t *rwlock;
struct switch_speech_interface *next; struct switch_speech_interface *next;
}; };
@ -426,6 +432,7 @@ struct switch_say_interface {
const char *interface_name; const char *interface_name;
/*! function to pass down to the module */ /*! function to pass down to the module */
switch_say_callback_t say_function; switch_say_callback_t say_function;
switch_thread_rwlock_t *rwlock;
struct switch_say_interface *next; struct switch_say_interface *next;
}; };
@ -435,6 +442,7 @@ struct switch_chat_interface {
const char *interface_name; const char *interface_name;
/*! function to open the directory interface */ /*! function to open the directory interface */
switch_status_t (*chat_send) (char *proto, char *from, char *to, char *subject, char *body, char *hint); switch_status_t (*chat_send) (char *proto, char *from, char *to, char *subject, char *body, char *hint);
switch_thread_rwlock_t *rwlock;
struct switch_chat_interface *next; struct switch_chat_interface *next;
}; };
@ -444,6 +452,7 @@ struct switch_management_interface {
const char *relative_oid; const char *relative_oid;
/*! function to open the directory interface */ /*! function to open the directory interface */
switch_status_t (*management_function) (char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen); switch_status_t (*management_function) (char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen);
switch_thread_rwlock_t *rwlock;
struct switch_management_interface *next; struct switch_management_interface *next;
}; };
@ -461,7 +470,7 @@ struct switch_directory_interface {
switch_status_t (*directory_next) (switch_directory_handle_t *dh); switch_status_t (*directory_next) (switch_directory_handle_t *dh);
/*! function to advance to the next name/value pair in the current record */ /*! function to advance to the next name/value pair in the current record */
switch_status_t (*directory_next_pair) (switch_directory_handle_t *dh, char **var, char **val); switch_status_t (*directory_next_pair) (switch_directory_handle_t *dh, char **var, char **val);
switch_thread_rwlock_t *rwlock;
struct switch_directory_interface *next; struct switch_directory_interface *next;
}; };
@ -586,6 +595,7 @@ struct switch_codec_interface {
/*! a list of codec implementations related to the codec */ /*! a list of codec implementations related to the codec */
switch_codec_implementation_t *implementations; switch_codec_implementation_t *implementations;
uint32_t codec_id; uint32_t codec_id;
switch_thread_rwlock_t *rwlock;
struct switch_codec_interface *next; struct switch_codec_interface *next;
}; };
@ -603,6 +613,7 @@ struct switch_application_interface {
const char *syntax; const char *syntax;
/*! flags to control behaviour */ /*! flags to control behaviour */
uint32_t flags; uint32_t flags;
switch_thread_rwlock_t *rwlock;
struct switch_application_interface *next; struct switch_application_interface *next;
}; };
@ -616,6 +627,7 @@ struct switch_api_interface {
switch_api_function_t function; switch_api_function_t function;
/*! an example of the api syntax */ /*! an example of the api syntax */
const char *syntax; const char *syntax;
switch_thread_rwlock_t *rwlock;
struct switch_api_interface *next; struct switch_api_interface *next;
}; };

View File

@ -100,6 +100,7 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_PATH_SEPARATOR "/" #define SWITCH_PATH_SEPARATOR "/"
#endif #endif
#define SWITCH_URL_SEPARATOR "://" #define SWITCH_URL_SEPARATOR "://"
#define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application"
#define SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE "proto_specific_hangup_cause" #define SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE "proto_specific_hangup_cause"
#define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer" #define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer"
#define SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE "execute_on_ring" #define SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE "execute_on_ring"

View File

@ -242,6 +242,7 @@ static struct {
switch_mutex_t *mutex; switch_mutex_t *mutex;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
int running; int running;
switch_event_node_t *node;
} globals; } globals;
@ -1182,7 +1183,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
} }
/* Subscribe to presence request events */ /* Subscribe to presence request events */
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY,
pres_event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
@ -1215,7 +1217,10 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
fifo_node_t *node; fifo_node_t *node;
switch_memory_pool_t *pool = globals.pool; switch_memory_pool_t *pool = globals.pool;
switch_mutex_t *mutex = globals.mutex; switch_mutex_t *mutex = globals.mutex;
switch_event_unbind(&globals.node);
switch_event_free_subclass(FIFO_EVENT);
switch_mutex_lock(mutex); switch_mutex_lock(mutex);
globals.running = 0; globals.running = 0;
@ -1229,6 +1234,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
free(pop); free(pop);
} }
} }
switch_core_hash_destroy(&node->caller_hash); switch_core_hash_destroy(&node->caller_hash);
switch_core_hash_destroy(&node->consumer_hash); switch_core_hash_destroy(&node->consumer_hash);
} }

View File

@ -147,7 +147,7 @@ static void event_handler(switch_event_t *event)
return; return;
} }
if (event->subclass && !strcmp(event->subclass->name, MULTICAST_EVENT)) { if (event->subclass_name && !strcmp(event->subclass_name, MULTICAST_EVENT)) {
/* ignore our own events to avoid ping pong */ /* ignore our own events to avoid ping pong */
return; return;
} }
@ -155,7 +155,7 @@ static void event_handler(switch_event_t *event)
if (globals.event_list[(uint8_t) SWITCH_EVENT_ALL]) { if (globals.event_list[(uint8_t) SWITCH_EVENT_ALL]) {
send = 1; send = 1;
} else if ((globals.event_list[(uint8_t) event->event_id])) { } else if ((globals.event_list[(uint8_t) event->event_id])) {
if (event->event_id != SWITCH_EVENT_CUSTOM || (event->subclass && switch_core_hash_find(globals.event_hash, event->subclass->name))) { if (event->event_id != SWITCH_EVENT_CUSTOM || (event->subclass_name && switch_core_hash_find(globals.event_hash, event->subclass_name))) {
send = 1; send = 1;
} }
} }

View File

@ -162,7 +162,7 @@ static void event_handler(switch_event_t *event)
if (l->event_list[SWITCH_EVENT_ALL]) { if (l->event_list[SWITCH_EVENT_ALL]) {
send = 1; send = 1;
} else if ((l->event_list[event->event_id])) { } else if ((l->event_list[event->event_id])) {
if (event->event_id != SWITCH_EVENT_CUSTOM || !event->subclass || (switch_core_hash_find(l->event_hash, event->subclass->name))) { if (event->event_id != SWITCH_EVENT_CUSTOM || !event->subclass_name || (switch_core_hash_find(l->event_hash, event->subclass_name))) {
send = 1; send = 1;
} }
} }

View File

@ -72,6 +72,50 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(const char *u
return session; return session;
} }
SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_name, const char *var_val, switch_call_cause_t cause)
{
switch_hash_index_t *hi;
void *val;
switch_core_session_t *session;
switch_mutex_lock(runtime.throttle_mutex);
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
if (val) {
const char *this_val;
session = (switch_core_session_t *) val;
switch_core_session_read_lock(session);
if ((this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) {
switch_channel_hangup(switch_core_session_get_channel(session), cause);
}
switch_core_session_rwunlock(session);
}
}
switch_mutex_unlock(runtime.throttle_mutex);
}
SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_interface_t *endpoint_interface, switch_call_cause_t cause)
{
switch_hash_index_t *hi;
void *val;
switch_core_session_t *session;
switch_mutex_lock(runtime.throttle_mutex);
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
if (val) {
session = (switch_core_session_t *) val;
switch_core_session_read_lock(session);
if (session->endpoint_interface == endpoint_interface) {
switch_channel_hangup(switch_core_session_get_channel(session), cause);
}
switch_core_session_rwunlock(session);
}
}
switch_mutex_unlock(runtime.throttle_mutex);
}
SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause) SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
{ {
switch_hash_index_t *hi; switch_hash_index_t *hi;
@ -686,6 +730,8 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
{ {
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
switch_event_t *event; switch_event_t *event;
const switch_endpoint_interface_t *endpoint_interface = (*session)->endpoint_interface;
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_NOTICE, "Close Channel %s [%s]\n", switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_NOTICE, "Close Channel %s [%s]\n",
switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel))); switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel)));
@ -720,6 +766,8 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
*session = NULL; *session = NULL;
switch_core_destroy_memory_pool(&pool); switch_core_destroy_memory_pool(&pool);
switch_thread_rwlock_unlock(endpoint_interface->rwlock);
} }
static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj) static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)
@ -827,6 +875,8 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch
return NULL; return NULL;
} }
switch_thread_rwlock_rdlock(endpoint_interface->rwlock);
if (pool && *pool) { if (pool && *pool) {
usepool = *pool; usepool = *pool;
*pool = NULL; *pool = NULL;
@ -1047,8 +1097,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *
switch_assert(application_interface->application_function); switch_assert(application_interface->application_function);
application_interface->application_function(session, arg); switch_channel_set_variable(session->channel, SWITCH_CURRENT_APPLICATION_VARIABLE, application_interface->interface_name);
switch_thread_rwlock_rdlock(application_interface->rwlock);
application_interface->application_function(session, arg);
switch_thread_rwlock_unlock(application_interface->rwlock);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(session->channel, event); switch_channel_event_set_data(session->channel, event);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", application_interface->interface_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", application_interface->interface_name);

View File

@ -38,11 +38,35 @@
#define DISPATCH_QUEUE_LEN 5000 #define DISPATCH_QUEUE_LEN 5000
//#define DEBUG_DISPATCH_QUEUES //#define DEBUG_DISPATCH_QUEUES
/*! \brief A node to store binded events */
struct switch_event_node {
/*! the id of the node */
char *id;
/*! the event id enumeration to bind to */
switch_event_types_t event_id;
/*! the event subclass to bind to for custom events */
switch_event_subclass_t *subclass;
/*! a callback function to execute when the event is triggered */
switch_event_callback_t callback;
/*! private data */
void *user_data;
struct switch_event_node *next;
};
/*! \brief A registered custom event subclass */
struct switch_event_subclass {
/*! the owner of the subclass */
char *owner;
/*! the subclass name */
char *name;
};
static int SOFT_MAX_DISPATCH = 0; static int SOFT_MAX_DISPATCH = 0;
static char hostname[128] = ""; static char hostname[128] = "";
static char guess_ip_v4[80] = ""; static char guess_ip_v4[80] = "";
static char guess_ip_v6[80] = ""; static char guess_ip_v6[80] = "";
static switch_event_node_t *EVENT_NODES[SWITCH_EVENT_ALL + 1] = { NULL }; static switch_event_node_t *EVENT_NODES[SWITCH_EVENT_ALL + 1] = { NULL };
static switch_thread_rwlock_t *RWLOCK = NULL;
static switch_mutex_t *BLOCK = NULL; static switch_mutex_t *BLOCK = NULL;
static switch_mutex_t *POOL_LOCK = NULL; static switch_mutex_t *POOL_LOCK = NULL;
static switch_memory_pool_t *RUNTIME_POOL = NULL; static switch_memory_pool_t *RUNTIME_POOL = NULL;
@ -148,7 +172,7 @@ static int switch_events_match(switch_event_t *event, switch_event_node_t *node)
if (match || event->event_id == node->event_id) { if (match || event->event_id == node->event_id) {
if (event->subclass && node->subclass) { if (event->subclass_name && node->subclass) {
if (!strncasecmp(node->subclass->name, "file:", 5)) { if (!strncasecmp(node->subclass->name, "file:", 5)) {
char *file_header; char *file_header;
if ((file_header = switch_event_get_header(event, "file")) != 0) { if ((file_header = switch_event_get_header(event, "file")) != 0) {
@ -159,10 +183,10 @@ static int switch_events_match(switch_event_t *event, switch_event_node_t *node)
if ((func_header = switch_event_get_header(event, "function")) != 0) { if ((func_header = switch_event_get_header(event, "function")) != 0) {
match = strstr(node->subclass->name + 5, func_header) ? 1 : 0; match = strstr(node->subclass->name + 5, func_header) ? 1 : 0;
} }
} else { } else if (event->subclass_name && node->subclass->name) {
match = strstr(event->subclass->name, node->subclass->name) ? 1 : 0; match = strstr(event->subclass_name, node->subclass->name) ? 1 : 0;
} }
} else if ((event->subclass && !node->subclass) || (!event->subclass && !node->subclass)) { } else if ((event->subclass_name && !node->subclass) || (!event->subclass_name && !node->subclass)) {
match = 1; match = 1;
} else { } else {
match = 0; match = 0;
@ -276,6 +300,7 @@ SWITCH_DECLARE(void) switch_event_deliver(switch_event_t **event)
switch_event_types_t e; switch_event_types_t e;
switch_event_node_t *node; switch_event_node_t *node;
switch_thread_rwlock_rdlock(RWLOCK);
for (e = (*event)->event_id;; e = SWITCH_EVENT_ALL) { for (e = (*event)->event_id;; e = SWITCH_EVENT_ALL) {
for (node = EVENT_NODES[e]; node; node = node->next) { for (node = EVENT_NODES[e]; node; node = node->next) {
if (switch_events_match(*event, node)) { if (switch_events_match(*event, node)) {
@ -288,6 +313,7 @@ SWITCH_DECLARE(void) switch_event_deliver(switch_event_t **event)
break; break;
} }
} }
switch_thread_rwlock_unlock(RWLOCK);
switch_event_destroy(event); switch_event_destroy(event);
} }
@ -321,6 +347,30 @@ SWITCH_DECLARE(switch_status_t) switch_name_event(const char *name, switch_event
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
SWITCH_DECLARE(switch_status_t) switch_event_free_subclass_detailed(const char *owner, const char *subclass_name)
{
switch_event_subclass_t *subclass;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_assert(RUNTIME_POOL != NULL);
switch_assert(CUSTOM_HASH != NULL);
if ((subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
if (!strcmp(owner, subclass->owner)) {
switch_thread_rwlock_wrlock(RWLOCK);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Subclass reservation deleted for %s:%s\n", owner, subclass_name);
switch_core_hash_delete(CUSTOM_HASH, subclass_name);
FREE(subclass->owner);
FREE(subclass->name);
FREE(subclass);
status = SWITCH_STATUS_SUCCESS;
switch_thread_rwlock_unlock(RWLOCK);
}
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name) SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name)
{ {
switch_event_subclass_t *subclass; switch_event_subclass_t *subclass;
@ -332,13 +382,11 @@ SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(const cha
return SWITCH_STATUS_INUSE; return SWITCH_STATUS_INUSE;
} }
if ((subclass = switch_core_alloc(RUNTIME_POOL, sizeof(*subclass))) == 0) { switch_zmalloc(subclass, sizeof(*subclass));
return SWITCH_STATUS_MEMERR;
}
subclass->owner = switch_core_strdup(RUNTIME_POOL, owner);
subclass->name = switch_core_strdup(RUNTIME_POOL, subclass_name);
subclass->owner = DUP(owner);
subclass->name = DUP(subclass_name);
switch_core_hash_insert(CUSTOM_HASH, subclass->name, subclass); switch_core_hash_insert(CUSTOM_HASH, subclass->name, subclass);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -448,6 +496,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activate Eventing Engine.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activate Eventing Engine.\n");
switch_thread_rwlock_create(&RWLOCK, RUNTIME_POOL);
switch_mutex_init(&BLOCK, SWITCH_MUTEX_NESTED, RUNTIME_POOL); switch_mutex_init(&BLOCK, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
switch_mutex_init(&POOL_LOCK, SWITCH_MUTEX_NESTED, RUNTIME_POOL); switch_mutex_init(&POOL_LOCK, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
switch_mutex_init(&EVENT_QUEUE_MUTEX, SWITCH_MUTEX_NESTED, RUNTIME_POOL); switch_mutex_init(&EVENT_QUEUE_MUTEX, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
@ -492,10 +541,15 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_subclass(switch_event_t **ev
(*event)->event_id = event_id; (*event)->event_id = event_id;
if (subclass_name) { if (subclass_name) {
if (!((*event)->subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) { switch_event_subclass_t *subclass;
if (!(subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
switch_event_reserve_subclass((char *) subclass_name); switch_event_reserve_subclass((char *) subclass_name);
(*event)->subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name); subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name);
} }
(*event)->subclass_name = DUP(subclass_name);
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", subclass_name); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", subclass_name);
} }
@ -662,6 +716,7 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
} }
} }
FREE(ep->body); FREE(ep->body);
FREE(ep->subclass_name);
memset(ep, 0, sizeof(*ep)); memset(ep, 0, sizeof(*ep));
if (switch_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != SWITCH_STATUS_SUCCESS) { if (switch_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != SWITCH_STATUS_SUCCESS) {
FREE(ep); FREE(ep);
@ -674,11 +729,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_
{ {
switch_event_header_t *header, *hp, *hp2, *last = NULL; switch_event_header_t *header, *hp, *hp2, *last = NULL;
if (switch_event_create_subclass(event, todup->event_id, todup->subclass ? todup->subclass->name : NULL) != SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(event, todup->event_id, todup->subclass_name) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
(*event)->subclass = todup->subclass; if (todup->subclass_name) {
(*event)->subclass_name = DUP(todup->subclass_name);
}
(*event)->event_user_data = todup->event_user_data; (*event)->event_user_data = todup->event_user_data;
(*event)->bind_user_data = todup->bind_user_data; (*event)->bind_user_data = todup->bind_user_data;
@ -942,9 +999,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Calling-Function", func); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Calling-Function", func);
switch_event_add_header(*event, SWITCH_STACK_BOTTOM, "Event-Calling-Line-Number", "%d", line); switch_event_add_header(*event, SWITCH_STACK_BOTTOM, "Event-Calling-Line-Number", "%d", line);
if ((*event)->subclass) { if ((*event)->subclass_name) {
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", (*event)->subclass->name); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", (*event)->subclass_name);
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass-Owner", (*event)->subclass->owner);
} }
if (user_data) { if (user_data) {
@ -958,8 +1014,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback, SWITCH_DECLARE(switch_status_t) switch_event_bind_removable(const char *id, switch_event_types_t event, const char *subclass_name,
void *user_data) switch_event_callback_t callback, void *user_data, switch_event_node_t **node)
{ {
switch_event_node_t *event_node; switch_event_node_t *event_node;
switch_event_subclass_t *subclass = NULL; switch_event_subclass_t *subclass = NULL;
@ -967,21 +1023,27 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_t
switch_assert(BLOCK != NULL); switch_assert(BLOCK != NULL);
switch_assert(RUNTIME_POOL != NULL); switch_assert(RUNTIME_POOL != NULL);
if (subclass_name) { if (node) {
if ((subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name)) == 0) { *node = NULL;
if ((subclass = switch_core_alloc(RUNTIME_POOL, sizeof(*subclass))) == 0) {
return SWITCH_STATUS_MEMERR;
} else {
subclass->owner = switch_core_strdup(RUNTIME_POOL, id);
subclass->name = switch_core_strdup(RUNTIME_POOL, subclass_name);
}
}
} }
if (event <= SWITCH_EVENT_ALL && (event_node = switch_core_alloc(RUNTIME_POOL, sizeof(switch_event_node_t))) != 0) { if (subclass_name) {
if (!(subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
switch_event_reserve_subclass_detailed(id, subclass_name);
subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name);
}
if (!subclass) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not reserve subclass. '%s'\n", subclass_name);
return SWITCH_STATUS_FALSE;
}
}
if (event <= SWITCH_EVENT_ALL) {
switch_zmalloc(event_node, sizeof(*event_node));
switch_mutex_lock(BLOCK); switch_mutex_lock(BLOCK);
switch_thread_rwlock_wrlock(RWLOCK);
/* <LOCKED> ----------------------------------------------- */ /* <LOCKED> ----------------------------------------------- */
event_node->id = switch_core_strdup(RUNTIME_POOL, id); event_node->id = DUP(id);
event_node->event_id = event; event_node->event_id = event;
event_node->subclass = subclass; event_node->subclass = subclass;
event_node->callback = callback; event_node->callback = callback;
@ -992,14 +1054,62 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_t
} }
EVENT_NODES[event] = event_node; EVENT_NODES[event] = event_node;
switch_thread_rwlock_unlock(RWLOCK);
switch_mutex_unlock(BLOCK); switch_mutex_unlock(BLOCK);
/* </LOCKED> ----------------------------------------------- */ /* </LOCKED> ----------------------------------------------- */
if (node) {
*node = event_node;
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
return SWITCH_STATUS_MEMERR; return SWITCH_STATUS_MEMERR;
} }
SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name,
switch_event_callback_t callback, void *user_data)
{
return switch_event_bind_removable(id, event, subclass_name, callback, user_data, NULL);
}
SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node)
{
switch_event_node_t *n, *np, *lnp = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
n = *node;
switch_thread_rwlock_wrlock(RWLOCK);
switch_mutex_lock(BLOCK);
/* <LOCKED> ----------------------------------------------- */
for (np = EVENT_NODES[n->event_id]; np; np = np->next) {
if (np == n) {
if (lnp) {
lnp->next = n->next;
} else {
EVENT_NODES[n->event_id] = n->next;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Event Binding deleted for %s:%s\n", n->id, switch_event_name(n->event_id));
n->subclass = NULL;
FREE(n->id);
FREE(n);
*node = NULL;
status = SWITCH_STATUS_SUCCESS;
break;
}
lnp = np;
}
switch_mutex_unlock(BLOCK);
switch_thread_rwlock_unlock(RWLOCK);
/* </LOCKED> ----------------------------------------------- */
return status;
}
SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(char *file, char *func, int line, SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(char *file, char *func, int line,
const char *proto, const char *login, const char *proto, const char *login,
const char *from, const char *from_domain, const char *from, const char *from_domain,

View File

@ -412,8 +412,16 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
if (old_module->module_interface->endpoint_interface) { if (old_module->module_interface->endpoint_interface) {
const switch_endpoint_interface_t *ptr; const switch_endpoint_interface_t *ptr;
for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) { for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) { if (ptr->interface_name) {
switch_core_session_hupall_endpoint(ptr, SWITCH_CAUSE_SYSTEM_SHUTDOWN);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name);
switch_thread_rwlock_wrlock(ptr->rwlock);
switch_thread_rwlock_unlock(ptr->rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Endpoint '%s'\n", 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); switch_core_hash_delete(loadable_modules.endpoint_hash, ptr->interface_name);
} }
@ -486,10 +494,14 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
if (old_module->module_interface->application_interface) { if (old_module->module_interface->application_interface) {
const switch_application_interface_t *ptr; const switch_application_interface_t *ptr;
for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) { for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) { if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name);
switch_core_session_hupall_matching_var(SWITCH_CURRENT_APPLICATION_VARIABLE, ptr->interface_name, SWITCH_CAUSE_SYSTEM_SHUTDOWN);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name);
switch_thread_rwlock_wrlock(ptr->rwlock);
switch_thread_rwlock_unlock(ptr->rwlock);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "application"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "application");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
@ -508,6 +520,11 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) { for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) { if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name);
switch_thread_rwlock_wrlock(ptr->rwlock);
switch_thread_rwlock_unlock(ptr->rwlock);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "api"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "api");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
@ -1357,9 +1374,11 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
if (cmd && (api = switch_loadable_module_get_api_interface(cmd)) != 0) { if (cmd && (api = switch_loadable_module_get_api_interface(cmd)) != 0) {
switch_thread_rwlock_rdlock(api->rwlock);
if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) { if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
} }
switch_thread_rwlock_unlock(api->rwlock);
} else { } else {
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "INVALID COMMAND!\n"); stream->write_function(stream, "INVALID COMMAND!\n");
@ -1398,7 +1417,7 @@ SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_crea
} else { \ } else { \
mod->_TYPE_##_interface = i; \ mod->_TYPE_##_interface = i; \
} \ } \
\ switch_thread_rwlock_create(&i->rwlock, mod->pool); \
return i; } return i; }