From 5fc5658e5ef23e4fea9045bb9416568ed7440568 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 22 Jul 2008 22:23:50 +0000 Subject: [PATCH] add auto ip-change detection and some other goodies git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9138 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_event.h | 1 + src/include/switch_types.h | 4 + src/mod/endpoints/mod_sofia/mod_sofia.c | 159 ++++++++++++++++-- src/mod/endpoints/mod_sofia/mod_sofia.h | 3 +- src/mod/endpoints/mod_sofia/sofia.c | 9 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 30 +++- .../mod_event_socket/mod_event_socket.c | 40 ++++- src/switch_console.c | 8 +- src/switch_core.c | 46 +++++ src/switch_event.c | 42 +++++ 10 files changed, 322 insertions(+), 20 deletions(-) diff --git a/src/include/switch_event.h b/src/include/switch_event.h index c6df3f5c0d..a8e0164068 100644 --- a/src/include/switch_event.h +++ b/src/include/switch_event.h @@ -225,6 +225,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind_removable(const char *id, swit \return SWITCH_STATUS_SUCCESS if the consumer was unbinded */ SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node); +SWITCH_DECLARE(switch_status_t) switch_event_unbind_callback(switch_event_callback_t callback); /*! \brief Render the name of an event id enumeration diff --git a/src/include/switch_types.h b/src/include/switch_types.h index bfcce98064..2f94359430 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1055,6 +1055,8 @@ typedef uint32_t switch_io_flag_t; SWITCH_EVENT_EXE_SCHEDULE - Something scheduled has been executed SWITCH_EVENT_RE_SCHEDULE - Something scheduled has been rescheduled SWITCH_EVENT_RELOADXML - XML registry has been reloaded + SWITCH_EVENT_NOTIFY - Notification + SWITCH_EVENT_SEND_MESSAGE - Message SWITCH_EVENT_ALL - All events at once @@ -1109,6 +1111,8 @@ typedef enum { SWITCH_EVENT_EXE_SCHEDULE, SWITCH_EVENT_RE_SCHEDULE, SWITCH_EVENT_RELOADXML, + SWITCH_EVENT_NOTIFY, + SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_ALL } switch_event_types_t; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 8143d40af7..e4358a1427 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1388,6 +1388,11 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t return SWITCH_STATUS_SUCCESS; } + if (argv[1] && !strcasecmp(argv[0], "restart") && !strcasecmp(argv[1], "all")) { + sofia_glue_restart_all_profiles(); + return SWITCH_STATUS_SUCCESS; + } + if (switch_strlen_zero(profile_name) || !(profile = sofia_glue_find_profile(profile_name))) { stream->write_function(stream, "Invalid Profile [%s]", switch_str_nil(profile_name)); return SWITCH_STATUS_SUCCESS; @@ -2050,6 +2055,118 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session return cause; } +static void general_event_handler(switch_event_t *event) +{ + switch (event->event_id) { + case SWITCH_EVENT_NOTIFY: + { + const char *profile_name = switch_event_get_header(event, "profile"); + const char *ct = switch_event_get_header(event, "content-type"); + const char *es = switch_event_get_header(event, "event-string"); + const char *user = switch_event_get_header(event, "user"); + const char *host = switch_event_get_header(event, "host"); + const char *body = switch_event_get_body(event); + sofia_profile_t *profile; + nua_handle_t *nh; + + if (profile_name && ct && es && body && user && host && (profile = sofia_glue_find_profile(profile_name))) { + char *id = NULL; + char *contact; + char buf[512] = ""; + + if (!sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find user %s@%s\n", user, host); + return; + } + + id = switch_mprintf("sip:%s@%s", user, host); + + switch_assert(id); + contact = sofia_glue_get_url_from_contact(buf, 0); + + nh = nua_handle(profile->nua, + NULL, + NUTAG_URL(contact), + SIPTAG_FROM_STR(id), + SIPTAG_TO_STR(id), + SIPTAG_CONTACT_STR(profile->url), + TAG_END()); + + nua_notify(nh, + NUTAG_NEWSUB(1), + SIPTAG_EVENT_STR(es), + SIPTAG_CONTENT_TYPE_STR(ct), + SIPTAG_PAYLOAD_STR(body), + TAG_END()); + + + free(id); + sofia_glue_release_profile(profile); + } + + } + break; + case SWITCH_EVENT_SEND_MESSAGE: + { + const char *profile_name = switch_event_get_header(event, "profile"); + const char *ct = switch_event_get_header(event, "content-type"); + const char *user = switch_event_get_header(event, "user"); + const char *host = switch_event_get_header(event, "host"); + const char *body = switch_event_get_body(event); + sofia_profile_t *profile; + nua_handle_t *nh; + + if (profile_name && ct && body && user && host && (profile = sofia_glue_find_profile(profile_name))) { + char *id = NULL; + char *contact; + char buf[512] = ""; + + if (!sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find user %s@%s\n", user, host); + return; + } + + id = switch_mprintf("sip:%s@%s", user, host); + + switch_assert(id); + contact = sofia_glue_get_url_from_contact(buf, 0); + + nh = nua_handle(profile->nua, + NULL, + NUTAG_URL(contact), + SIPTAG_FROM_STR(id), + SIPTAG_TO_STR(id), + SIPTAG_CONTACT_STR(profile->url), + TAG_END()); + + nua_message(nh, + NUTAG_NEWSUB(1), + SIPTAG_CONTENT_TYPE_STR(ct), + SIPTAG_PAYLOAD_STR(body), + TAG_END()); + + + free(id); + sofia_glue_release_profile(profile); + } + + } + break; + case SWITCH_EVENT_TRAP: + { + const char *cond = switch_event_get_header(event, "condition"); + + if (cond && !strcmp(cond, "network-address-change")) { + sofia_glue_restart_all_profiles(); + } + + } + break; + default: + break; + } +} + SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) { switch_chat_interface_t *chat_interface; @@ -2087,37 +2204,53 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n"); switch_yield(1500000); - if (switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL, &mod_sofia_globals.custom_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL, + &mod_sofia_globals.custom_node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_TERM; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, &mod_sofia_globals.in_node) - != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, + &mod_sofia_globals.in_node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, &mod_sofia_globals.out_node) - != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, + &mod_sofia_globals.out_node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, &mod_sofia_globals.probe_node) - != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, + &mod_sofia_globals.probe_node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, &mod_sofia_globals.roster_node) - != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, + &mod_sofia_globals.roster_node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_mwi_event_handler, NULL, &mod_sofia_globals.mwi_node) - != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_mwi_event_handler, NULL, + &mod_sofia_globals.mwi_node) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind(modname, SWITCH_EVENT_NOTIFY, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, general_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } @@ -2138,6 +2271,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_console_set_complete("add sofia status"); switch_console_set_complete("add sofia loglevel"); switch_console_set_complete("add sofia profile"); + switch_console_set_complete("add sofia profile restart all"); SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]@"); SWITCH_ADD_CHAT(chat_interface, SOFIA_CHAT_PROTO, sofia_presence_chat_send); @@ -2162,7 +2296,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown) switch_event_unbind(&mod_sofia_globals.roster_node); switch_event_unbind(&mod_sofia_globals.custom_node); switch_event_unbind(&mod_sofia_globals.mwi_node); - + switch_event_unbind_callback(general_event_handler); + while (mod_sofia_globals.threads) { switch_yield(1000); if (++sanity >= 10000) { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index f745bfdf02..fc2e19e940 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -610,7 +610,7 @@ switch_status_t sofia_glue_add_profile(char *key, sofia_profile_t *profile); void sofia_glue_release_profile__(const char *file, const char *func, int line, sofia_profile_t *profile); #define sofia_glue_release_profile(x) sofia_glue_release_profile__(__FILE__, __SWITCH_FUNC__, __LINE__, x) -sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, char *key); +sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key); #define sofia_glue_find_profile(x) sofia_glue_find_profile__(__FILE__, __SWITCH_FUNC__, __LINE__, x) switch_status_t sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway); @@ -672,3 +672,4 @@ const char *sofia_glue_strip_proto(const char *uri); switch_status_t reconfig_sofia(sofia_profile_t *profile); void sofia_glue_del_gateway(sofia_gateway_t *gp); void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent); +void sofia_glue_restart_all_profiles(void); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9fd82ecde8..a79bc59aa3 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -528,7 +528,14 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void profile->nua = nua_create(profile->s_root, /* Event loop */ sofia_event_callback, /* Callback for processing events */ profile, /* Additional data to pass to callback */ - NUTAG_URL(profile->bindurl), TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_SIPS_URL(profile->tls_bindurl)), TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_CERTIFICATE_DIR(profile->tls_cert_dir)), TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), TPTAG_TLS_VERSION(profile->tls_version)), NTATAG_UDP_MTU(65536), NTATAG_SERVER_RPORT(profile->rport_level), TAG_IF(tportlog, TPTAG_LOG(1)), TAG_END()); /* Last tag should always finish the sequence */ + NUTAG_URL(profile->bindurl), + TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_SIPS_URL(profile->tls_bindurl)), + TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_CERTIFICATE_DIR(profile->tls_cert_dir)), + TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), TPTAG_TLS_VERSION(profile->tls_version)), + NTATAG_UDP_MTU(65536), + NTATAG_SERVER_RPORT(profile->rport_level), + TAG_IF(tportlog, TPTAG_LOG(1)), + TAG_END()); /* Last tag should always finish the sequence */ if (!profile->nua) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s\n", profile->name); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 73c2bf712d..216e54a6a7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2549,7 +2549,7 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup) return url; } -sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, char *key) +sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key) { sofia_profile_t *profile; @@ -2620,6 +2620,34 @@ void sofia_glue_del_gateway(sofia_gateway_t *gp) } } +void sofia_glue_restart_all_profiles(void) +{ + switch_hash_index_t *hi; + const void *var; + void *val; + sofia_profile_t *pptr; + switch_xml_t xml_root; + const char *err; + + if ((xml_root = switch_xml_open_root(1, &err))) { + switch_xml_free(xml_root); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Reload XML [%s]\n", err); + } + + switch_mutex_lock(mod_sofia_globals.hash_mutex); + if (mod_sofia_globals.profile_hash) { + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + if ((pptr = (sofia_profile_t *) val)) { + sofia_set_pflag_locked(pptr, PFLAG_RESPAWN); + sofia_clear_pflag_locked(pptr, PFLAG_RUNNING); + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + +} + void sofia_glue_del_profile(sofia_profile_t *profile) { sofia_gateway_t *gp; diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 3bcb39ef4c..140bfb7f7d 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -408,6 +408,8 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, uint8_t crcount = 0; uint32_t max_len = sizeof(mbuf); switch_channel_t *channel = NULL; + int clen = 0; + *event = NULL; start = switch_timestamp(NULL); ptr = mbuf; @@ -480,16 +482,50 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } if (var && val) { switch_event_add_header(*event, SWITCH_STACK_BOTTOM, var, "%s", val); + if (!strcasecmp(var, "content-length")) { + clen = atoi(val); + + if (clen > 0) { + char *body = malloc(clen + 1); + char *ptr = body; + + switch_assert(body); + + while(clen > 0) { + mlen = clen; + + status = switch_socket_recv(listener->sock, ptr, &mlen); + + if (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + + if (channel && !switch_channel_ready(channel)) { + status = SWITCH_STATUS_FALSE; + break; + } + + clen -= (int) mlen; + ptr += mlen; + } + + switch_event_add_body(*event, "%s", body); + free(body); + } + + + + } } } } - + cur = next; } break; } } - + if (timeout) { elapsed = (uint32_t) (switch_timestamp(NULL) - start); if (elapsed >= timeout) { diff --git a/src/switch_console.c b/src/switch_console.c index e70dfb0f54..211afeb34e 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -467,12 +467,14 @@ static int comp_callback(void *pArg, int argc, char **argv, char **columnNames) return -1; } - fprintf(h->out, "%20s\t", target); + fprintf(h->out, "[%20s]\t", target); switch_copy_string(h->last, target, sizeof(h->last)); - if ((++h->hits % 4) == 0) { - fprintf(h->out, "\n"); + if (!switch_strlen_zero(target)) { + if ((++h->hits % 4) == 0) { + fprintf(h->out, "\n"); + } } return 0; diff --git a/src/switch_core.c b/src/switch_core.c index 9a6801ed45..ee6ed580e4 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -76,9 +76,55 @@ static void send_heartbeat(void) } } +static char main_ip4[256] = ""; +static char main_ip6[256] = ""; + +static void check_ip(void) { + char guess_ip4[256] = ""; + char guess_ip6[256] = ""; + int ok4 = 1, ok6 = 1; + + switch_find_local_ip(guess_ip4, sizeof(guess_ip4), AF_INET); + switch_find_local_ip(guess_ip6, sizeof(guess_ip6), AF_INET6); + + if (!*main_ip4) { + switch_set_string(main_ip4, guess_ip4); + } else { + if (!(ok4 = !strcmp(main_ip4, guess_ip4))) { + switch_set_string(main_ip4, guess_ip4); + switch_core_set_variable("local_ip_v4", guess_ip4); + } + } + + if (!*main_ip6) { + switch_set_string(main_ip6, guess_ip6); + } else { + if (!(ok6 = !strcmp(main_ip6, guess_ip6))) { + switch_set_string(main_ip6, guess_ip6); + switch_core_set_variable("local_ip_v4", guess_ip6); + } + } + + if (!ok4 || !ok6) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); + if (!ok4) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", "%s", main_ip4); + } + if (!ok6) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", "%s", main_ip6); + } + switch_event_fire(&event); + } + } +} + SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) { send_heartbeat(); + check_ip(); /* reschedule this task */ task->runtime = switch_timestamp(NULL) + 20; diff --git a/src/switch_event.c b/src/switch_event.c index adc9c21b94..b2cf83bf9d 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -155,6 +155,8 @@ static char *EVENT_NAMES[] = { "EXE_SCHEDULE", "RE_SCHEDULE", "RELOADXML", + "NOTIFY", + "SEND_MESSAGE", "ALL" }; @@ -1068,6 +1070,46 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind(const char *id, switch_event_t } +SWITCH_DECLARE(switch_status_t) switch_event_unbind_callback(switch_event_callback_t callback) +{ + switch_event_node_t *n, *np, *lnp = NULL; + switch_status_t status = SWITCH_STATUS_FALSE; + int id; + + switch_thread_rwlock_wrlock(RWLOCK); + switch_mutex_lock(BLOCK); + /* ----------------------------------------------- */ + for (id = 0; id < SWITCH_EVENT_ALL; id++) { + lnp = NULL; + + for (np = EVENT_NODES[id]; np;) { + n = np; + np = np->next; + if (n->callback == callback) { + 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); + status = SWITCH_STATUS_SUCCESS; + } else { + lnp = n; + } + } + } + switch_mutex_unlock(BLOCK); + switch_thread_rwlock_unlock(RWLOCK); + /* ----------------------------------------------- */ + + return status; +} + + + SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node) { switch_event_node_t *n, *np, *lnp = NULL;