From 7c93a4e4eb26cfab2c400dff32d4bf19f8a12f7d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 18 Oct 2007 01:02:01 +0000 Subject: [PATCH] experimental multiple registrations in sofia conf in dialplan or or git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5956 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- conf/sofia.conf.xml | 1 + src/mod/endpoints/mod_sofia/mod_sofia.c | 91 +++++++++++++++++++++++++ src/mod/endpoints/mod_sofia/mod_sofia.h | 3 +- src/mod/endpoints/mod_sofia/sofia.c | 38 +++++++---- src/mod/endpoints/mod_sofia/sofia_reg.c | 79 ++++++++++++++------- 5 files changed, 175 insertions(+), 37 deletions(-) diff --git a/conf/sofia.conf.xml b/conf/sofia.conf.xml index 2effd5a8d0..362416a34b 100644 --- a/conf/sofia.conf.xml +++ b/conf/sofia.conf.xml @@ -54,6 +54,7 @@ + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 092b37451e..c11c31dbb4 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1248,6 +1248,96 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t return SWITCH_STATUS_SUCCESS; } +static int contact_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct cb_helper *cb = (struct cb_helper *) pArg; + char *contact; + + if (!switch_strlen_zero(argv[0]) && (contact = sofia_glue_get_url_from_contact(argv[0], 1))) { + cb->stream->write_function(cb->stream, "sofia/%s/%s,", cb->profile->name, contact + 4); + free(contact); + } + + return 0; +} + +SWITCH_STANDARD_API(sofia_contact_function) +{ + char *data; + char *user = NULL; + char *domain = NULL; + char *profile_name = NULL; + char *p; + + if (!cmd) { + stream->write_function(stream, "%s", ""); + return SWITCH_STATUS_SUCCESS; + } + + data = strdup(cmd); + assert(data); + + if ((p = strchr(data, '/'))) { + profile_name = data; + *p++ = '\0'; + user = p; + } else { + user = data; + } + + if ((domain = strchr(user, '@'))) { + *domain++ = '\0'; + } + + if (!profile_name && domain) { + profile_name = domain; + } + + if (user && profile_name) { + char *sql; + sofia_profile_t *profile; + + if (!(profile = sofia_glue_find_profile(profile_name))) { + profile_name = domain; + domain = NULL; + } + + if (!profile && profile_name) { + profile = sofia_glue_find_profile(profile_name); + } + + if (profile) { + struct cb_helper cb; + switch_stream_handle_t mystream = { 0 }; + if (!domain || !strchr(domain, '.')) { + domain = profile->name; + } + + SWITCH_STANDARD_STREAM(mystream); + cb.profile = profile; + cb.stream = &mystream; + + sql = switch_mprintf("select contact from sip_registrations where user='%q' and host='%q'", user, domain); + assert(sql); + sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, contact_callback, &cb); + switch_safe_free(sql); + if (mystream.data) { + char *str = mystream.data; + *(str + (strlen(str) - 1)) = '\0'; + } + stream->write_function(stream, "%s", mystream.data); + switch_safe_free(mystream.data); + goto end; + } + } + + stream->write_function(stream, "%s", ""); + end: + + switch_safe_free(data); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(sofia_function) { char *argv[1024] = { 0 }; @@ -1589,6 +1679,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) management_interface->management_function = sofia_manage; SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, " "); + 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); /* indicate that the module should continue to be loaded */ diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 06d9a2e2bb..a882993072 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -112,7 +112,8 @@ typedef enum { PFLAG_REWRITE_TIMESTAMPS = (1 << 7), PFLAG_RUNNING = (1 << 8), PFLAG_RESPAWN = (1 << 9), - PFLAG_GREEDY = (1 << 10) + PFLAG_GREEDY = (1 << 10), + PFLAG_MULTIREG = (1 << 11) } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 6f06750f1a..c46bd0cb82 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -260,7 +260,8 @@ void event_handler(switch_event_t *event) long expires = (long) time(NULL) + atol(exp_str); char *profile_name = switch_event_get_header(event, "orig-profile-name"); sofia_profile_t *profile = NULL; - char buf[512]; + char *icontact = NULL, *p; + if (!rpid) { rpid = "unknown"; @@ -270,26 +271,33 @@ void event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n"); return; } - - - if (!sofia_reg_find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) { - sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Regestered', '%q', %ld)", - from_user, from_host, contact_str, rpid, expires); + if (sofia_test_pflag(profile, PFLAG_MULTIREG)) { + icontact = sofia_glue_get_url_from_contact(contact_str, 1); + + if ((p = strchr(icontact, ';'))) { + *p = '\0'; + } + sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q' and contact like '%%%q%%'", from_user, from_host, icontact); + switch_safe_free(icontact); } else { - sql = - switch_mprintf - ("update sip_registrations set contact='%q', rpid='%q', expires=%ld where user='%q' and host='%q'", - contact_str, rpid, expires, from_user, from_host); - + sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q'", from_user, from_host); } + switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); + switch_safe_free(sql); + + sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Regestered', '%q', %ld)", + from_user, from_host, contact_str, rpid, expires); + if (sql) { - sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); switch_safe_free(sql); sql = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating registration for %s@%s->%s\n", from_user, from_host, contact_str); - } + switch_mutex_unlock(profile->ireg_mutex); + if (profile) { sofia_glue_release_profile(profile); @@ -844,6 +852,10 @@ switch_status_t config_sofia(int reload, char *profile_name) if (switch_true(val)) { profile->pflags |= PFLAG_PRESENCE; } + } else if (!strcasecmp(var, "multiple-registrations")) { + if (switch_true(val)) { + profile->pflags |= PFLAG_MULTIREG; + } } else if (!strcasecmp(var, "NDLB-to-in-200-contact")) { if (switch_true(val)) { profile->ndlb |= PFLAG_NDLB_TO_IN_200_CONTACT; diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 734a160330..3071a0ee1b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -329,7 +329,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han const char *to_user = NULL; const char *to_host = NULL; char contact_str[1024] = ""; - char buf[512]; + //char buf[512]; uint8_t stale = 0, forbidden = 0; auth_res_t auth_res; long exptime = 60; @@ -461,16 +461,32 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han } if (exptime) { - if (!sofia_reg_find_reg_url(profile, to_user, to_host, buf, sizeof(buf))) { - sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','%q', '%q', %ld)", - to_user, to_host, contact_str, cd ? "Registered(NATHACK)" : "Registered", rpid, (long) time(NULL) + (long) exptime * 2); + + if (sofia_test_pflag(profile, PFLAG_MULTIREG)) { + char *icontact, *p; + icontact = sofia_glue_get_url_from_contact(contact_str, 1); + if ((p = strchr(icontact, ';'))) { + *p = '\0'; + } + + sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q' and contact like '%%%q%%'", to_user, to_host, icontact); + switch_safe_free(icontact); } else { - sql = - switch_mprintf - ("update sip_registrations set contact='%q', expires=%ld, rpid='%q' where user='%q' and host='%q'", - contact_str, (long) time(NULL) + (long) exptime * 2, rpid, to_user, to_host); - + sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q'", to_user, to_host); } + switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); + switch_safe_free(sql); + sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','%q', '%q', %ld)", + to_user, to_host, contact_str, cd ? "Registered(NATHACK)" : "Registered", rpid, (long) time(NULL) + (long) exptime * 2); + + + if (sql) { + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL); + switch_safe_free(sql); + sql = NULL; + } + switch_mutex_unlock(profile->ireg_mutex); if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile-name", "%s", profile->name); @@ -482,11 +498,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han switch_event_fire(&s_event); } - if (sql) { - sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); - switch_safe_free(sql); - sql = NULL; - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Register:\nFrom: [%s@%s]\nContact: [%s]\nExpires: [%ld]\n", to_user, to_host, contact_str, (long) exptime); @@ -503,15 +515,36 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han switch_event_fire(&event); } } else { - if ((sql = switch_mprintf("delete from sip_subscriptions where user='%q' and host='%q'", to_user, to_host))) { - sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); - switch_safe_free(sql); - sql = NULL; - } - if ((sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q'", to_user, to_host))) { - sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); - switch_safe_free(sql); - sql = NULL; + if (sofia_test_pflag(profile, PFLAG_MULTIREG)) { + char *icontact, *p; + icontact = sofia_glue_get_url_from_contact(contact_str, 1); + if ((p = strchr(icontact, ';'))) { + *p = '\0'; + } + if ((sql = switch_mprintf("delete from sip_subscriptions where user='%q' and host='%q' and contact like '%%%q%%'", to_user, to_host, icontact))) { + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + switch_safe_free(sql); + sql = NULL; + } + + if ((sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q' and contact like '%%%q%%'", to_user, to_host, icontact))) { + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + switch_safe_free(sql); + sql = NULL; + } + switch_safe_free(icontact); + } else { + if ((sql = switch_mprintf("delete from sip_subscriptions where user='%q' and host='%q'", to_user, to_host))) { + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + switch_safe_free(sql); + sql = NULL; + } + + if ((sql = switch_mprintf("delete from sip_registrations where user='%q' and host='%q'", to_user, to_host))) { + sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + switch_safe_free(sql); + sql = NULL; + } } if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");