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
This commit is contained in:
Anthony Minessale 2008-07-22 22:23:50 +00:00
parent 1636bc635c
commit 5fc5658e5e
10 changed files with 322 additions and 20 deletions

View File

@ -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

View File

@ -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
</pre>
@ -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;

View File

@ -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/]<user>@<domain>");
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) {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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);
/* <LOCKED> ----------------------------------------------- */
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);
/* </LOCKED> ----------------------------------------------- */
return status;
}
SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node)
{
switch_event_node_t *n, *np, *lnp = NULL;