From aca07987006bc8e6be96e06da0942d945776c99d Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 6 Mar 2019 04:38:39 +0000 Subject: [PATCH] FS-9942 [mod_sofia] allow intercept for other channels --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 353 +++++++++++++----------- 2 files changed, 186 insertions(+), 168 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 46d215a2d5..56e2c53735 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -964,6 +964,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_status_t sofia_proxy_sip_i_message(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[]); void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[]); +void sofia_handle_sip_i_invite_replaces(switch_core_session_t *session, switch_channel_t *channel, switch_channel_t *b_channel, char* uuid, private_object_t *tech_pvt, sip_call_info_t *call_info, sofia_profile_t *profile, char *is_nat, sip_t const *sip); void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private, sip_t const *sip, diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 617446e983..b070862cf4 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -11038,182 +11038,22 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia sofia_private_t *b_private = NULL; if ((b_private = nua_handle_magic(bnh))) { switch_core_session_t *b_session = NULL; - if ((b_session = switch_core_session_locate(b_private->uuid))) { switch_channel_t *b_channel = switch_core_session_get_channel(b_session); - const char *bridge_uuid; - switch_caller_profile_t *orig_cp, *cp; - //const char *sent_name, *sent_number; - orig_cp = switch_channel_get_caller_profile(b_channel); - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); - - if (!call_info) { - tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); - tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); - } - - if (orig_cp) { - cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp); - switch_channel_set_originator_caller_profile(channel, cp); - } - -#if 0 - sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name"); - sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number"); - - if (!zstr(sent_name) && !zstr(sent_number)) { - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name); - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number); - } else { - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); - } else { - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); - } - } -#endif - - if (is_nat) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat); - } - - tech_pvt->caller_profile->dialplan = "inline"; - - bridge_uuid = switch_channel_get_partner_uuid(b_channel); - - if (call_info) { - switch_event_t *event = NULL; - - if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) { - const char *b_call_id = switch_channel_get_variable(b_channel, "sip_call_id"); - - if (b_call_id) { - char *sql = switch_mprintf("update sip_dialogs set call_info_state='idle' where call_id='%q'", b_call_id); - if (mod_sofia_globals.debug_sla > 1) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql); - } - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - - switch_channel_presence(b_channel, "unknown", "idle", NULL); - } - switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT); - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, - "answer,intercept:%s", bridge_uuid); - - if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) - && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(b_channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id); - switch_event_fire(&event); - } - } else { - switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel); - - if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) { - switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR); - } - - if (!zstr(bcp->callee_id_name)) { - tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name); - } - - if (!zstr(bcp->callee_id_number)) { - tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number); - } - - - if (!zstr(bcp->caller_id_name)) { - tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name); - } - - if (!zstr(bcp->caller_id_number)) { - tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number); - } - - if (bcp->originatee_caller_profile) { - switch_caller_profile_t *cp; - - cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, - bcp->originatee_caller_profile); - - switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp); - } - - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, - "answer,sofia_sla:%s", b_private->uuid); - } - } else { - char const *a_leg = NULL; - char const *nightmare_xfer_uuid = NULL; - - switch_event_t *event = NULL; - if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id) { - a_leg = msg_header_find_param(sip->sip_replaces->rp_common, "a-leg"); - } - if(a_leg && switch_true(a_leg)) { - switch_channel_mark_hold(b_channel, SWITCH_FALSE); - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", sip->sip_replaces->rp_call_id); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s picked up on a-leg\n", sip->sip_replaces->rp_call_id); - if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) - && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(b_channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id); - switch_event_fire(&event); - } - } else { - if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-For"))) { - switch_channel_set_variable(b_channel, "transfer_refer_for", nightmare_xfer_uuid); - } - if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-From"))) { - switch_channel_set_variable(b_channel, "transfer_refer_from", nightmare_xfer_uuid); - } - - if (!zstr(bridge_uuid)) { - if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id && switch_channel_test_flag(b_channel, CF_BRIDGED) && - switch_true(switch_find_parameter(*(sip->sip_replaces->rp_params), "early-only", switch_core_session_get_pool(session)))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercept rejected\n", bridge_uuid); - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "hangup:CALL_REJECTED"); - } else { - switch_channel_mark_hold(b_channel, SWITCH_FALSE); - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", bridge_uuid); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercepted\n", bridge_uuid); - if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) && - switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(b_channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id); - switch_event_fire(&event); - } - } - } else { - const char *b_app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE); - const char *b_data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE); - if (b_data && b_app) { - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s:%s", b_app, b_data); - } else if (b_app) { - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s", b_app); - } - if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) - && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(b_channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id); - switch_event_fire(&event); - } - switch_channel_hangup(b_channel, SWITCH_CAUSE_ATTENDED_TRANSFER); - } - } - } - + sofia_handle_sip_i_invite_replaces(session, channel, b_channel, b_private->uuid, tech_pvt, call_info, profile, is_nat, sip); switch_core_session_rwunlock(b_session); } } nua_handle_unref(bnh); + } else if (sip && sip->sip_replaces && sip->sip_replaces->rp_call_id) { + switch_core_session_t *b_session = NULL; + if ((b_session = switch_core_session_locate((char*) sip->sip_replaces->rp_call_id))) { + switch_channel_t *b_channel = switch_core_session_get_channel(b_session); + sofia_handle_sip_i_invite_replaces(session, channel, b_channel, (char*) sip->sip_replaces->rp_call_id, tech_pvt, call_info, profile, is_nat, sip); + switch_core_session_rwunlock(b_session); + } } - - if (tech_pvt->caller_profile) { int first_history_info = 1; @@ -11428,6 +11268,183 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia } +void sofia_handle_sip_i_invite_replaces(switch_core_session_t *session, switch_channel_t *channel, switch_channel_t *b_channel, char* uuid, private_object_t *tech_pvt, sip_call_info_t *call_info, sofia_profile_t *profile, char *is_nat, sip_t const *sip) +{ + const char *bridge_uuid; + switch_caller_profile_t *orig_cp, *cp; + //const char *sent_name, *sent_number; + orig_cp = switch_channel_get_caller_profile(b_channel); + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); + + if (!call_info) { + tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); + tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); + } + + if (orig_cp) { + cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp); + switch_channel_set_originator_caller_profile(channel, cp); + } + +#if 0 + sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name"); + sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number"); + + if (!zstr(sent_name) && !zstr(sent_number)) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number); + } else { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); + } else { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); + } + } +#endif + + if (is_nat) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat); + } + + tech_pvt->caller_profile->dialplan = "inline"; + + bridge_uuid = switch_channel_get_partner_uuid(b_channel); + if (bridge_uuid) { + switch_core_session_t *bridge_session = NULL; + if ((bridge_session = switch_core_session_locate(bridge_uuid))) { + switch_core_session_rwunlock(bridge_session); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "could not locate partner_uuid %s, resetting\n", bridge_uuid); + bridge_uuid = NULL; + } + } + + if (call_info) { + switch_event_t *event = NULL; + + if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) { + const char *b_call_id = switch_channel_get_variable(b_channel, "sip_call_id"); + + if (b_call_id) { + char *sql = switch_mprintf("update sip_dialogs set call_info_state='idle' where call_id='%q'", b_call_id); + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql); + } + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + + switch_channel_presence(b_channel, "unknown", "idle", NULL); + } + switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,intercept:%s", bridge_uuid); + + if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) + && sip && sip->sip_call_id + && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(b_channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id); + switch_event_fire(&event); + } + } else { + switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel); + + if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) { + switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR); + } + + if (!zstr(bcp->callee_id_name)) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name); + } + + if (!zstr(bcp->callee_id_number)) { + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number); + } + + + if (!zstr(bcp->caller_id_name)) { + tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name); + } + + if (!zstr(bcp->caller_id_number)) { + tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number); + } + + if (bcp->originatee_caller_profile) { + switch_caller_profile_t *cp; + + cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, + bcp->originatee_caller_profile); + + switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp); + } + + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,sofia_sla:%s", uuid); + } + } else { + char const *nightmare_xfer_uuid = NULL; + switch_event_t *event = NULL; + if (switch_channel_var_true(channel, "sip_replaces_a-leg")) { + switch_channel_mark_hold(b_channel, SWITCH_FALSE); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", sip->sip_replaces->rp_call_id); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s picked up on a-leg\n", sip->sip_replaces->rp_call_id); + if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) + && sip && sip->sip_call_id + && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(b_channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id); + switch_event_fire(&event); + } + } else { + if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-For"))) { + switch_channel_set_variable(b_channel, "transfer_refer_for", nightmare_xfer_uuid); + } + if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-From"))) { + switch_channel_set_variable(b_channel, "transfer_refer_from", nightmare_xfer_uuid); + } + + if (!zstr(bridge_uuid)) { + if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id && switch_channel_test_flag(b_channel, CF_BRIDGED) && + switch_true(switch_find_parameter(*(sip->sip_replaces->rp_params), "early-only", switch_core_session_get_pool(session)))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercept rejected\n", bridge_uuid); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "hangup:CALL_REJECTED"); + } else { + switch_channel_mark_hold(b_channel, SWITCH_FALSE); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", bridge_uuid); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercepted\n", bridge_uuid); + if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) + && sip && sip->sip_call_id + && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(b_channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id); + switch_event_fire(&event); + } + } + } else { + const char *b_app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE); + const char *b_data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE); + if (b_data && b_app) { + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s:%s", b_app, b_data); + } else if (b_app) { + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s", b_app); + } + if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) + && sip && sip->sip_call_id + && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(b_channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id); + switch_event_fire(&event); + } + switch_channel_hangup(b_channel, SWITCH_CAUSE_ATTENDED_TRANSFER); + } + } + } + +} + void sofia_handle_sip_i_options(int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,