diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 2791692cab..6e07a1c963 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3783,7 +3783,12 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session } if (!strncasecmp(dest, "sip:", 4) || !strncasecmp(dest, "sips:", 5)) { + char *c; tech_pvt->dest = switch_core_session_strdup(nsession, dest); + if ((c = strchr(tech_pvt->dest, ':'))) { + c++; + tech_pvt->e_dest = switch_core_session_strdup(nsession, c); + } } else if ((host = strchr(dest, '%'))) { char buf[1024]; *host = '@'; @@ -3812,6 +3817,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session } else { host++; tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5); + tech_pvt->e_dest = switch_core_session_strdup(nsession, dest); switch_snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest); } } @@ -4173,40 +4179,45 @@ static void general_event_handler(switch_event_t *event) const char *body = switch_event_get_body(event); sofia_profile_t *profile; nua_handle_t *nh; - + if (profile_name && ct && user && host) { char *id = NULL; char *contact, *p; - char buf[512] = ""; - + switch_console_callback_match_t *list = NULL; + switch_console_callback_match_node_t *m; + if (!(profile = sofia_glue_find_profile(profile_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name); return; } - - - 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); + + if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered 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); - if ((p = strstr(contact, ";fs_"))) { - *p = '\0'; + for (m = list->head; m; m = m->next) { + contact = sofia_glue_get_url_from_contact(m->val, 0); + + if ((p = strstr(contact, ";fs_"))) { + *p = '\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), + TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject)), TAG_END()); + + + free(id); } + switch_console_free_matches(&list); - 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), - TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject)), TAG_END()); - - - free(id); sofia_glue_release_profile(profile); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 98ea119359..78db36e8d5 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -216,6 +216,7 @@ typedef enum { PFLAG_EXTENDED_INFO_PARSING, PFLAG_T38_PASSTHRU, PFLAG_CID_IN_1XX, + PFLAG_IN_DIALOG_CHAT, /* No new flags below this line */ PFLAG_MAX } PFLAGS; @@ -698,6 +699,7 @@ struct private_object { struct callback_t { char *val; switch_size_t len; + switch_console_callback_match_t *list; int matches; }; @@ -1003,3 +1005,4 @@ void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_ switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *session, const char *r_sdp); char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type); void sofia_glue_tech_simplify(private_object_t *tech_pvt); +switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index b9ff9e35a8..0a0c641365 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2211,6 +2211,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_PASS_CALLEE_ID); } + } else if (!strcasecmp(var, "in-dialog-chat")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_IN_DIALOG_CHAT); + } else { + sofia_clear_pflag(profile, PFLAG_IN_DIALOG_CHAT); + } } else if (!strcasecmp(var, "disable-hold")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_DISABLE_HOLD); @@ -2865,6 +2871,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL); } + } else if (!strcasecmp(var, "in-dialog-chat")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_IN_DIALOG_CHAT); + } else { + sofia_clear_pflag(profile, PFLAG_IN_DIALOG_CHAT); + } } else if (!strcasecmp(var, "t38-passthru")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_T38_PASSTHRU); @@ -6748,7 +6760,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ sofia_private->is_call++; tech_pvt->sofia_private = sofia_private; - if ((profile->pres_type)) { + if (profile->pres_type && sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) { sofia_presence_set_chat_hash(tech_pvt, sip); } switch_copy_string(tech_pvt->sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid)); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index d78e690797..580b5e70b6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1968,7 +1968,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) nua_handle_bind(tech_pvt->nh, tech_pvt->sofia_private); } - if (tech_pvt->e_dest) { + if (tech_pvt->e_dest && sofia_test_pflag(tech_pvt->profile, PFLAG_IN_DIALOG_CHAT)) { char *user = NULL, *host = NULL; char hash_key[256] = ""; diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 845fb60583..c6c0ccaa23 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -73,7 +73,6 @@ struct presence_helper { switch_status_t sofia_presence_chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint) { - char buf[256]; char *prof = NULL, *user = NULL, *host = NULL; sofia_profile_t *profile = NULL; char *ffrom = NULL; @@ -84,6 +83,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co const char *ct = "text/html"; sofia_destination_t *dst = NULL; char *to_uri = NULL; + switch_console_callback_match_t *list = NULL; + switch_console_callback_match_node_t *m; if (!to) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n"); @@ -133,17 +134,19 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co host = prof; } } - - if (!to_uri && !sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find user. [%s][%s]\n", user, host); + + if (to_uri) { + switch_console_push_match(&list, to_uri); + } else if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host); goto end; } - + if (!strcasecmp(proto, SOFIA_CHAT_PROTO)) { from = hint; } else { char *fp, *p = NULL; - + fp = strdup(from); if (!fp) { @@ -168,23 +171,28 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co switch_safe_free(fp); } - if (!(dst = sofia_glue_get_destination(to_uri ? to_uri : buf))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); - goto end; - } + for (m = list->head; m; m = m->next) { - /* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */ - - status = SWITCH_STATUS_SUCCESS; - /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ - msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), - SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END()); - nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private); - nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), TAG_END()); + if (!(dst = sofia_glue_get_destination(m->val))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + break; + } + + /* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */ + status = SWITCH_STATUS_SUCCESS; + /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ + msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), + SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END()); + nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private); + nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), TAG_END()); + sofia_glue_free_destination(dst); + } + + switch_console_free_matches(&list); end: - sofia_glue_free_destination(dst); + switch_safe_free(contact); switch_safe_free(ffrom); switch_safe_free(dup); @@ -2597,8 +2605,11 @@ void sofia_presence_handle_sip_i_message(int status, from_addr = switch_mprintf("%s@%s", from_user, from_host); - sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip); - if ((tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) { + if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) { + sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip); + } + + if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT) && (tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) { channel = switch_core_session_get_channel(tech_pvt->session); if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index be6041ff4f..33f26e98dc 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -417,9 +417,15 @@ int sofia_reg_find_callback(void *pArg, int argc, char **argv, char **columnName { struct callback_t *cbt = (struct callback_t *) pArg; + if (!cbt->len) { + switch_console_push_match(&cbt->list, argv[0]); + cbt->matches++; + return 0; + } + switch_copy_string(cbt->val, argv[0], cbt->len); cbt->matches++; - return 0; + return cbt->matches == 1 ? 0 : 1; } int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames) @@ -709,6 +715,30 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c } +switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host) +{ + struct callback_t cbt = { 0 }; + char sql[512] = ""; + + if (!user) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n"); + return NULL; + } + + if (host) { + switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')", + user, host, host); + } else { + switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user); + } + + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_callback, &cbt); + + return cbt.list; +} + + void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_regtype_t regtype, const char *realm, int stale) { switch_uuid_t uuid; diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index b32a61f1a2..b9a2feafbb 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -379,7 +379,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0); } - if (event->event_id != SWITCH_EVENT_COMMAND || switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) { + if ((event->event_id != SWITCH_EVENT_COMMAND && event->event_id != SWITCH_EVENT_MESSAGE) + || switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); }