Author: anthm Date: Wed Oct 17 21:02:01 2007 New Revision: 5956 Modified: freeswitch/trunk/conf/sofia.conf.xml freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c Log: experimental multiple registrations in sofia conf <param name="multiple-registrations" value="true"/> in dialplan <action application="bridge" data="$sofia_contact(mysofia_profile_name/user@regtodomain.com)"/> or <action application="bridge" data="$sofia_contact(mysofia_profile_name_same_as_regto_domain.com/user)"/> or <action application="bridge" data="$sofia_contact(user@mysofia_profile_name_same_as_regto_domain.com)"/> Modified: freeswitch/trunk/conf/sofia.conf.xml ============================================================================== --- freeswitch/trunk/conf/sofia.conf.xml (original) +++ freeswitch/trunk/conf/sofia.conf.xml Wed Oct 17 21:02:01 2007 @@ -54,6 +54,7 @@ <param name="sip-ip" value="$${local_ip_v4}"/> <!--enable to use presense and mwi --> <param name="manage-presence" value="true"/> + <!--<param name="multiple-registrations" value="true"/>--> <!--set to 'greedy' if you want your codec list to take precedence --> <param name="inbound-codec-negotiation" value="generous"/> <!-- if you want to send any special bind params of your own --> Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Wed Oct 17 21:02:01 2007 @@ -1248,6 +1248,96 @@ 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 @@ management_interface->management_function = sofia_manage; SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, "<cmd> <args>"); + 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); /* indicate that the module should continue to be loaded */ Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Wed Oct 17 21:02:01 2007 @@ -112,7 +112,8 @@ 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; Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Wed Oct 17 21:02:01 2007 @@ -260,7 +260,8 @@ 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 @@ 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 @@ 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; Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c Wed Oct 17 21:02:01 2007 @@ -329,7 +329,7 @@ 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 @@ } 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 @@ 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 @@ 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");