diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 629019fbf4..1ccc54e445 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -43,6 +43,9 @@ + + + diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 38a9249c79..6df083bca6 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -933,6 +933,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *ses SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point); SWITCH_DECLARE(switch_status_t) switch_ivr_create_message_reply(switch_event_t **reply, switch_event_t *message, const char *new_proto); +SWITCH_DECLARE(char *) switch_ivr_check_presence_mapping(const char *exten_name, const char *domain_name); /** @} */ diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 49732723bd..318ecea2ce 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -253,6 +253,7 @@ typedef enum { PFLAG_AUTO_ASSIGN_PORT, PFLAG_AUTO_ASSIGN_TLS_PORT, PFLAG_SHUTDOWN, + PFLAG_PRESENCE_MAP, /* No new flags below this line */ PFLAG_MAX } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index a0a18cdd21..173f16692d 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2875,6 +2875,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL); } + } else if (!strcasecmp(var, "presence-proto-lookup")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_MAP); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP); + } } else if (!strcasecmp(var, "liberal-dtmf")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF); @@ -3590,6 +3596,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL); } + } else if (!strcasecmp(var, "presence-proto-lookup")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_MAP); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP); + } } else if (!strcasecmp(var, "liberal-dtmf")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 2b6c6ed5fc..7f34669e0e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -2632,6 +2632,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, char *my_to_user = NULL; char *sql, *event = NULL; char *proto = "sip"; + char *alt_proto = NULL; char *d_user = NULL; char *contact_str = ""; const char *call_id = NULL; @@ -2647,6 +2648,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, const char *ipv6; const char *contact_user; sofia_nat_parse_t np = { { 0 } }; + int found_proto = 0; if (!sip) { return; @@ -2730,6 +2732,8 @@ void sofia_presence_handle_sip_i_subscribe(int status, nua_respond(nh, SIP_404_NOT_FOUND, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); goto end; } + + found_proto++; } call_id = sip->sip_call_id->i_id; @@ -2740,6 +2744,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, sip->sip_expires->ex_delta = 31536000; } + if (sofia_test_pflag(profile, PFLAG_PRESENCE_MAP) && !found_proto && (alt_proto = switch_ivr_check_presence_mapping(to_user, to_host))) { + proto = alt_proto; + } if ((sub_state == nua_substate_active) && (switch_stristr("dialog", (const char *) event))) { @@ -3047,6 +3054,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_safe_free(d_user); switch_safe_free(to_str); switch_safe_free(contact_str); + switch_safe_free(alt_proto); if (!sent_reply) { nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END()); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 3904d07e5f..99fa2ff290 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -3137,6 +3137,57 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_create_message_reply(switch_event_t * return status; } +SWITCH_DECLARE(char *) switch_ivr_check_presence_mapping(const char *exten_name, const char *domain_name) +{ + char *cf = "presence_map.conf"; + switch_xml_t cfg, xml, x_domains, x_domain, x_exten; + char *r = NULL; + switch_regex_t *re = NULL; + int proceed = 0, ovector[100]; + + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); + return NULL; + } + + if (!(x_domains = switch_xml_child(cfg, "domains"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find any domains!\n"); + return NULL; + } + + for (x_domain = switch_xml_child(x_domains, "domain"); x_domain; x_domain = x_domain->next) { + const char *dname = switch_xml_attr(x_domain, "name"); + if (!dname || strcasecmp(domain_name, dname)) continue; + + for (x_exten = switch_xml_child(x_domain, "exten"); x_exten; x_exten = x_exten->next) { + const char *regex = switch_xml_attr(x_exten, "regex"); + const char *proto = switch_xml_attr(x_exten, "proto"); + + if (regex && proto) { + proceed = switch_regex_perform(exten_name, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); + switch_regex_safe_free(re); + + if (proceed) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Mapping %s@%s to proto %s matching expression [%s]\n", + exten_name, domain_name, proto, regex); + r = strdup(proto); + goto end; + } + + } + } + } + + end: + + if (xml) { + switch_xml_free(xml); + } + + return r; + +} + /* For Emacs: * Local Variables: