From 58043483cdb0ffdedcfa9c6dfacded7dcbe41191 Mon Sep 17 00:00:00 2001 From: karl anderson Date: Thu, 2 Apr 2015 19:23:46 -0400 Subject: [PATCH] FS-7773 [mod_sofia] transfer events #resolve --- src/mod/endpoints/mod_sofia/mod_sofia.h | 6 ++ src/mod/endpoints/mod_sofia/sofia.c | 116 ++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 2bd475fb7b..13fb98f639 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -98,6 +98,11 @@ typedef struct private_object private_object_t; #define MY_EVENT_PROFILE_START "sofia::profile_start" #define MY_EVENT_NOTIFY_WATCHED_HEADER "sofia::notify_watched_header" +#define MY_EVENT_TRANSFEROR "sofia::transferor" +#define MY_EVENT_TRANSFEREE "sofia::transferee" +#define MY_EVENT_REPLACED "sofia::replaced" +#define MY_EVENT_INTERCEPTED "sofia::intercepted" + #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" #define SOFIA_CHAT_PROTO "sip" @@ -284,6 +289,7 @@ typedef enum { PFLAG_AUTH_SUBSCRIPTIONS, PFLAG_PROXY_REFER, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER, + PFLAG_FIRE_TRANFER_EVENTS, /* No new flags below this line */ PFLAG_MAX diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 97a9a88ede..22f1699f84 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4189,6 +4189,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) //sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER); sofia_clear_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER); + sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS); profile->shutdown_type = "false"; profile->local_network = "localnet.auto"; sofia_set_flag(profile, TFLAG_ENABLE_SOA); @@ -5451,6 +5452,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER); } + } else if (!strcasecmp(var, "fire-transfer-events")) { + if(switch_true(val)) { + sofia_set_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS); + } else { + sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS); + } } } @@ -7812,6 +7819,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t char *full_ref_to = NULL; nightmare_xfer_helper_t *nightmare_xfer_helper; switch_memory_pool_t *npool; + switch_event_t *event = NULL; if (!(profile->mflags & MFLAG_REFER)) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); @@ -8034,6 +8042,24 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t moh = NULL; } + if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_b, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", br_a); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_a, event); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(a_channel, event); + switch_event_fire(&event); + } + } + if (moh) { char *xdest; xdest = switch_core_session_sprintf(a_session, "endless_playback:%s,park", moh); @@ -8080,6 +8106,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } else if (br_a && br_b) { switch_core_session_t *tmp = NULL; + switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n", switch_str_nil(br_a), switch_str_nil(br_b)); @@ -8122,6 +8149,30 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t mark_transfer_record(session, br_a, br_b); + if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_b, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", br_a); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_a, event); + switch_event_fire(&event); + } + + if ((tmp = switch_core_session_locate(br_a))) { + switch_channel_t *tchannel = switch_core_session_get_channel(tmp); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(tchannel, event); + switch_event_fire(&event); + } + + switch_core_session_rwunlock(tmp); + } + } + switch_ivr_uuid_bridge(br_a, br_b); switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER"); nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), @@ -8145,6 +8196,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } else { switch_core_session_t *t_session, *hup_session; switch_channel_t *hup_channel; + switch_event_t *event = NULL; const char *ext; if (br_a && !br_b) { @@ -8181,6 +8233,18 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_core_media_bug_transfer_recordings(hup_session, t_session); } + if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_a, event); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(t_channel, event); + switch_event_fire(&event); + } + } + if (idest) { switch_ivr_session_transfer(t_session, idest, "inline", NULL); } else { @@ -8326,6 +8390,18 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, SOFIA_REFER_TO_VARIABLE, full_ref_to); } + if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_a, event); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_fire(&event); + } + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Good Luck, you'll need it......\n"); launch_nightmare_xfer(nightmare_xfer_helper); @@ -8365,6 +8441,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t if (!zstr(br) && (b_session = switch_core_session_locate(br))) { const char *var; switch_channel_t *b_channel = switch_core_session_get_channel(b_session); + switch_event_t *event = NULL; switch_channel_set_variable(channel, "transfer_fallback_extension", from->a_user); if (!zstr(full_ref_by)) { @@ -8402,6 +8479,18 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_channel_set_variable(b_channel, "sip_h_X-FS-Refer-Params", refer_to->r_url->url_params); } + if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel_a, event); + switch_event_fire(&event); + } + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(b_channel, event); + switch_event_fire(&event); + } + } + switch_ivr_session_transfer(b_session, exten, NULL, NULL); switch_core_session_rwunlock(b_session); } else { @@ -9939,6 +10028,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia switch_core_session_t *os; switch_codec_implementation_t read_impl = { 0 }; char *codec_str = ""; + switch_event_t *event = NULL; if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) { olu = bridge_uuid; @@ -9969,6 +10059,13 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT); tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "%sanswer,intercept:%s", codec_str, 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); @@ -10007,6 +10104,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia } } else { char *a_leg = NULL; + switch_event_t *event = NULL; if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id) { a_leg = switch_find_parameter(*(sip->sip_replaces->rp_params), "a-leg", switch_core_session_get_pool(session)); } @@ -10014,10 +10112,22 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia 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 (!zstr(bridge_uuid)) { 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); + 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); @@ -10026,6 +10136,12 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia } 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); } }