diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index be03dd2d43..63c92cc852 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -620,7 +620,9 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) sofia_clear_flag(tech_pvt, TFLAG_IO); if (tech_pvt->sofia_private) { - *tech_pvt->sofia_private->uuid = '\0'; + /* set to NULL so that switch_core_session_locate no longer succeeds, but don't lose the UUID in uuid_str so we + * can fire events with session UUID */ + tech_pvt->sofia_private->uuid = NULL; } switch_mutex_unlock(tech_pvt->sofia_mutex); @@ -5896,6 +5898,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_goto_status(SWITCH_STATUS_TERM, err); } + if (switch_event_reserve_subclass(MY_EVENT_BYE_RESPONSE) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_BYE_RESPONSE); + switch_goto_status(SWITCH_STATUS_TERM, err); + } + switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), &mod_sofia_globals.guess_mask, AF_INET); in.s_addr = mod_sofia_globals.guess_mask; switch_set_string(mod_sofia_globals.guess_mask_str, inet_ntoa(in)); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 966717bef7..ba4f9a6534 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -104,6 +104,8 @@ typedef struct private_object private_object_t; #define MY_EVENT_REPLACED "sofia::replaced" #define MY_EVENT_INTERCEPTED "sofia::intercepted" +#define MY_EVENT_BYE_RESPONSE "sofia::bye_response" + #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" #define SOFIA_CHAT_PROTO "sip" @@ -169,7 +171,8 @@ typedef struct sofia_dispatch_event_s { } sofia_dispatch_event_t; struct sofia_private { - char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char *uuid; char gateway_name[256]; char auth_gateway_name[256]; char *call_id; @@ -297,6 +300,7 @@ typedef enum { PFLAG_PROXY_HOLD, PFLAG_PROXY_INFO, PFLAG_PROXY_MESSAGE, + PFLAG_FIRE_BYE_RESPONSE_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 a0e0fae2c8..76208038a9 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -864,6 +864,30 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status, } +/* + * This will fire an event containing X-headers from the BYE response + */ +void sofia_handle_sip_r_bye(switch_core_session_t *session, 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, + sofia_dispatch_event_t *de, tagi_t tags[]) +{ + if (profile && sofia_test_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS) && sip && sip->sip_call_id && !zstr(sip->sip_call_id->i_id) && sofia_private && !zstr_buf(sofia_private->uuid_str)) { + switch_event_t *bye_response_event = NULL; + sip_unknown_t *un; + if (switch_event_create_subclass(&bye_response_event, SWITCH_EVENT_CUSTOM, MY_EVENT_BYE_RESPONSE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, "call-id", "%s", sip->sip_call_id->i_id); + switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", sofia_private->uuid_str); + for (un = sip->sip_unknown; un; un = un->un_next) { + if (!zstr(un->un_value)) { + switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, un->un_name, "%s", un->un_value); + } + } + switch_event_fire(&bye_response_event); + } + } +} + void sofia_handle_sip_i_bye(switch_core_session_t *session, 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, @@ -1415,7 +1439,6 @@ static void our_sofia_event_callback(nua_event_t event, if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) { - if (!zstr(sofia_private->gateway_name)) { if (!(gateway = sofia_reg_find_gateway(sofia_private->gateway_name))) { return; @@ -1549,7 +1572,6 @@ static void our_sofia_event_callback(nua_event_t event, case nua_i_fork: case nua_r_info: break; - case nua_r_bye: case nua_r_unregister: case nua_r_unsubscribe: case nua_i_terminated: @@ -1674,6 +1696,9 @@ static void our_sofia_event_callback(nua_event_t event, case nua_i_bye: sofia_handle_sip_i_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags); break; + case nua_r_bye: + sofia_handle_sip_r_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags); + break; case nua_r_notify: if (session) { sofia_handle_sip_r_notify(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags); @@ -2417,7 +2442,8 @@ void sofia_event_callback(nua_event_t event, if (uuid) { if ((session = switch_core_session_locate(uuid))) { tech_pvt = switch_core_session_get_private(session); - switch_copy_string(sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid)); + switch_copy_string(sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid_str)); + sofia_private->uuid = sofia_private->uuid_str; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-attaching to session %s\n", sofia_private->uuid); de->init_session = session; sofia_clear_flag(tech_pvt, TFLAG_BYE); @@ -2511,7 +2537,8 @@ void sofia_event_callback(nua_event_t event, goto end; } - switch_copy_string(sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid)); + switch_copy_string(sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid_str)); + sofia_private->uuid = sofia_private->uuid_str; de->init_session = session; switch_core_session_queue_signal_data(session, de); @@ -4627,6 +4654,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_ENABLE_CHAT); } + } else if (!strcasecmp(var, "fire-bye-response-events")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS); + } else { + sofia_clear_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS); + } } else if (!strcasecmp(var, "fire-message-events")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_FIRE_MESSAGE_EVENTS); @@ -8135,7 +8168,6 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, ss_state = nua_callstate_terminated; } - if (ss_state == nua_callstate_terminated) { if (tech_pvt->sofia_private) { tech_pvt->sofia_private = NULL; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 3b356c0ed8..6b523ac993 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1181,7 +1181,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } tech_pvt->sofia_private = sofia_private; - switch_copy_string(tech_pvt->sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid)); + switch_copy_string(tech_pvt->sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid_str)); + tech_pvt->sofia_private->uuid = tech_pvt->sofia_private->uuid_str; nua_handle_bind(tech_pvt->nh, tech_pvt->sofia_private); }