*/
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
\param uuid_str the unique id of the session you want to send a message to
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 */
struct switch_event {
/*! the event id (descriptor) */
/*! the owner of the event */
char *owner;
/*! the subclass of the event */
- switch_event_subclass_t *subclass;
+ char *subclass_name;
/*! the event headers */
switch_event_header_t *headers;
/*! the event headers tail pointer */
struct switch_event *next;
};
-/*! \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;
-};
+struct switch_event_node;
#define SWITCH_EVENT_SUBCLASS_ANY NULL
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);
+/*!
+ \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
\param event the event id to render the name of
*/
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
\param event the event to render
\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_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
/*! private information */
void *private_info;
+ switch_thread_rwlock_t *rwlock;
+
/* to facilitate linking */
struct switch_endpoint_interface *next;
};
switch_status_t (*timer_check) (switch_timer_t *, switch_bool_t);
/*! function to deallocate the timer */
switch_status_t (*timer_destroy) (switch_timer_t *);
+ switch_thread_rwlock_t *rwlock;
struct switch_timer_interface *next;
};
const char *interface_name;
/*! the function to read an extension and set a channels dialpan */
switch_dialplan_hunt_function_t hunt_function;
+ switch_thread_rwlock_t *rwlock;
struct switch_dialplan_interface *next;
};
switch_status_t (*file_get_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char **string);
/*! list of supported file extensions */
char **extens;
+ switch_thread_rwlock_t *rwlock;
struct switch_file_interface *next;
};
switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*! 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_thread_rwlock_t *rwlock;
struct switch_asr_interface *next;
};
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_float_param_tts) (switch_speech_handle_t *sh, char *param, double val);
-
+ switch_thread_rwlock_t *rwlock;
struct switch_speech_interface *next;
};
const char *interface_name;
/*! function to pass down to the module */
switch_say_callback_t say_function;
+ switch_thread_rwlock_t *rwlock;
struct switch_say_interface *next;
};
const char *interface_name;
/*! function to open the directory interface */
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;
};
const char *relative_oid;
/*! 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_thread_rwlock_t *rwlock;
struct switch_management_interface *next;
};
switch_status_t (*directory_next) (switch_directory_handle_t *dh);
/*! 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_thread_rwlock_t *rwlock;
struct switch_directory_interface *next;
};
/*! a list of codec implementations related to the codec */
switch_codec_implementation_t *implementations;
uint32_t codec_id;
+ switch_thread_rwlock_t *rwlock;
struct switch_codec_interface *next;
};
const char *syntax;
/*! flags to control behaviour */
uint32_t flags;
+ switch_thread_rwlock_t *rwlock;
struct switch_application_interface *next;
};
switch_api_function_t function;
/*! an example of the api syntax */
const char *syntax;
+ switch_thread_rwlock_t *rwlock;
struct switch_api_interface *next;
};
#define SWITCH_PATH_SEPARATOR "/"
#endif
#define SWITCH_URL_SEPARATOR "://"
+#define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application"
#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_RING_VARIABLE "execute_on_ring"
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
int running;
+ switch_event_node_t *node;
} globals;
}
/* 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");
return SWITCH_STATUS_GENERR;
}
fifo_node_t *node;
switch_memory_pool_t *pool = globals.pool;
switch_mutex_t *mutex = globals.mutex;
-
+
+ switch_event_unbind(&globals.node);
+ switch_event_free_subclass(FIFO_EVENT);
+
switch_mutex_lock(mutex);
globals.running = 0;
free(pop);
}
}
+
switch_core_hash_destroy(&node->caller_hash);
switch_core_hash_destroy(&node->consumer_hash);
}
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 */
return;
}
if (globals.event_list[(uint8_t) SWITCH_EVENT_ALL]) {
send = 1;
} 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;
}
}
if (l->event_list[SWITCH_EVENT_ALL]) {
send = 1;
} 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;
}
}
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_hash_index_t *hi;
{
switch_memory_pool_t *pool;
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_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel)));
*session = NULL;
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)
return NULL;
}
+ switch_thread_rwlock_rdlock(endpoint_interface->rwlock);
+
if (pool && *pool) {
usepool = *pool;
*pool = NULL;
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) {
switch_channel_event_set_data(session->channel, event);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", application_interface->interface_name);
#define DISPATCH_QUEUE_LEN 5000
//#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 char hostname[128] = "";
static char guess_ip_v4[80] = "";
static char guess_ip_v6[80] = "";
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 *POOL_LOCK = NULL;
static switch_memory_pool_t *RUNTIME_POOL = NULL;
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)) {
char *file_header;
if ((file_header = switch_event_get_header(event, "file")) != 0) {
if ((func_header = switch_event_get_header(event, "function")) != 0) {
match = strstr(node->subclass->name + 5, func_header) ? 1 : 0;
}
- } else {
- match = strstr(event->subclass->name, node->subclass->name) ? 1 : 0;
+ } else if (event->subclass_name && node->subclass->name) {
+ 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;
} else {
match = 0;
switch_event_types_t e;
switch_event_node_t *node;
+ switch_thread_rwlock_rdlock(RWLOCK);
for (e = (*event)->event_id;; e = SWITCH_EVENT_ALL) {
for (node = EVENT_NODES[e]; node; node = node->next) {
if (switch_events_match(*event, node)) {
break;
}
}
+ switch_thread_rwlock_unlock(RWLOCK);
switch_event_destroy(event);
}
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_event_subclass_t *subclass;
return SWITCH_STATUS_INUSE;
}
- if ((subclass = switch_core_alloc(RUNTIME_POOL, sizeof(*subclass))) == 0) {
- return SWITCH_STATUS_MEMERR;
- }
-
- subclass->owner = switch_core_strdup(RUNTIME_POOL, owner);
- subclass->name = switch_core_strdup(RUNTIME_POOL, subclass_name);
+ switch_zmalloc(subclass, sizeof(*subclass));
+ subclass->owner = DUP(owner);
+ subclass->name = DUP(subclass_name);
+
switch_core_hash_insert(CUSTOM_HASH, subclass->name, subclass);
return SWITCH_STATUS_SUCCESS;
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(&POOL_LOCK, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
switch_mutex_init(&EVENT_QUEUE_MUTEX, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
(*event)->event_id = event_id;
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);
- (*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);
}
}
}
FREE(ep->body);
+ FREE(ep->subclass_name);
memset(ep, 0, sizeof(*ep));
if (switch_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != SWITCH_STATUS_SUCCESS) {
FREE(ep);
{
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;
}
- (*event)->subclass = todup->subclass;
+ if (todup->subclass_name) {
+ (*event)->subclass_name = DUP(todup->subclass_name);
+ }
(*event)->event_user_data = todup->event_user_data;
(*event)->bind_user_data = todup->bind_user_data;
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);
- if ((*event)->subclass) {
- 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 ((*event)->subclass_name) {
+ switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", (*event)->subclass_name);
}
if (user_data) {
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,
- void *user_data)
+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)
{
switch_event_node_t *event_node;
switch_event_subclass_t *subclass = NULL;
switch_assert(BLOCK != NULL);
switch_assert(RUNTIME_POOL != NULL);
+ if (node) {
+ *node = NULL;
+ }
+
if (subclass_name) {
- if ((subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name)) == 0) {
- 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 (!(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 && (event_node = switch_core_alloc(RUNTIME_POOL, sizeof(switch_event_node_t))) != 0) {
+
+ if (event <= SWITCH_EVENT_ALL) {
+ switch_zmalloc(event_node, sizeof(*event_node));
switch_mutex_lock(BLOCK);
+ switch_thread_rwlock_wrlock(RWLOCK);
/* <LOCKED> ----------------------------------------------- */
- event_node->id = switch_core_strdup(RUNTIME_POOL, id);
+ event_node->id = DUP(id);
event_node->event_id = event;
event_node->subclass = subclass;
event_node->callback = callback;
}
EVENT_NODES[event] = event_node;
+ switch_thread_rwlock_unlock(RWLOCK);
switch_mutex_unlock(BLOCK);
/* </LOCKED> ----------------------------------------------- */
+
+ if (node) {
+ *node = event_node;
+ }
+
return SWITCH_STATUS_SUCCESS;
}
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,
const char *proto, const char *login,
const char *from, const char *from_domain,
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_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_core_hash_delete(loadable_modules.endpoint_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);
+ 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) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "application");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
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);
+
+ 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) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "%s", "api");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
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) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
}
+ switch_thread_rwlock_unlock(api->rwlock);
} else {
status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "INVALID COMMAND!\n");
} else { \
mod->_TYPE_##_interface = i; \
} \
- \
+ switch_thread_rwlock_create(&i->rwlock, mod->pool); \
return i; }