delay update till after media has been confirmed to prevent SOA race in sip

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15159 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2009-10-14 19:26:10 +00:00
parent 1172afedb5
commit 39f93c4eea
7 changed files with 92 additions and 46 deletions

View File

@ -80,6 +80,7 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_
#define switch_channel_media_ready(_channel) switch_channel_test_ready(_channel, SWITCH_TRUE)
#define switch_channel_up(_channel) (switch_channel_get_state(_channel) < CS_HANGUP)
#define switch_channel_down(_channel) (switch_channel_get_state(_channel) >= CS_HANGUP)
#define switch_channel_media_ack(_channel) (!switch_channel_test_cap(_channel, CC_MEDIA_ACK) || switch_channel_test_flag(_channel, CF_MEDIA_ACK))
SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state);
SWITCH_DECLARE(void) switch_channel_wait_for_state_timeout(switch_channel_t *other_channel, switch_channel_state_t want_state, uint32_t timeout);
@ -297,6 +298,10 @@ SWITCH_DECLARE(uint32_t) switch_channel_test_flag(switch_channel_t *channel, swi
SWITCH_DECLARE(void) switch_channel_set_flag(switch_channel_t *channel, switch_channel_flag_t flag);
SWITCH_DECLARE(void) switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag);
SWITCH_DECLARE(void) switch_channel_set_cap(switch_channel_t *channel, switch_channel_cap_t cap);
SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap);
SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap);
/*!
\brief Set given flag(s) on a given channel's bridge partner
\param channel channel to derive the partner channel to set flag on

View File

@ -866,6 +866,12 @@ CF_STOP_BROADCAST - Signal to stop broadcast
</pre>
*/
typedef enum {
CC_MEDIA_ACK = 1,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CC_FLAG_MAX
} switch_channel_cap_t;
typedef enum {
CF_ANSWERED = 1,
CF_OUTBOUND,
@ -906,6 +912,7 @@ typedef enum {
CF_TIMESTAMP_SET,
CF_ORIGINATOR,
CF_XFER_ZOMBIE,
CF_MEDIA_ACK,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;

View File

@ -1289,43 +1289,45 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
number = tech_pvt->caller_profile->destination_number;
}
if (switch_strlen_zero(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
switch_strlen_zero(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
if (ua && switch_stristr("snom", ua)) {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if ((ua && (switch_stristr("polycom", ua) ||
switch_stristr("UPDATE", tech_pvt->x_actually_support_remote)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", name, number);
nua_update(tech_pvt->nh,
TAG_IF(!switch_strlen_zero_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Callee-Name", name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Callee-Number", number);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_channel_set_variable(channel, "sip_callee_id_name", name);
switch_channel_set_variable(channel, "sip_callee_id_number", number);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
if (switch_strlen_zero(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
switch_strlen_zero(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
if (ua && switch_stristr("snom", ua)) {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if ((ua && (switch_stristr("polycom", ua) ||
switch_stristr("UPDATE", tech_pvt->x_actually_support_remote)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", name, number);
nua_update(tech_pvt->nh,
TAG_IF(!switch_strlen_zero_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Callee-Name", name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Callee-Number", number);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
}
}
}
switch_safe_free(arg);

View File

@ -603,12 +603,15 @@ void sofia_event_callback(nua_event_t event,
case nua_r_cancel:
case nua_i_error:
case nua_i_active:
case nua_i_ack:
case nua_i_terminated:
case nua_r_set_params:
case nua_i_prack:
case nua_r_prack:
break;
case nua_i_ack:
case nua_r_ack:
if (channel) switch_channel_set_flag(channel, CF_MEDIA_ACK);
break;
case nua_r_shutdown:
if (status >= 200) su_root_break(profile->s_root);
break;
@ -1021,6 +1024,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
NUTAG_APPL_METHOD("REGISTER"),
NUTAG_APPL_METHOD("NOTIFY"),
NUTAG_APPL_METHOD("INFO"),
NUTAG_APPL_METHOD("ACK"),
#ifdef MANUAL_BYE
NUTAG_APPL_METHOD("BYE"),
#endif
@ -3109,11 +3113,12 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
caller_profile->network_addr = switch_core_strdup(caller_profile->pool, network_ip);
}
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
if ((status == 180 || status == 183 || status == 200)) {
const char *x_actually_support;
switch_channel_set_flag(channel, CF_MEDIA_ACK);
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
if ((x_actually_support = sofia_glue_get_unknown_header(sip, "X-Actually-Support"))) {
tech_pvt->x_actually_support_remote = switch_core_session_strdup(session, x_actually_support);
}

View File

@ -521,6 +521,8 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
tech_pvt->session = session;
tech_pvt->channel = switch_core_session_get_channel(session);
switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK);
switch_core_session_set_private(session, tech_pvt);
switch_snprintf(name, sizeof(name), "sofia/%s/%s", profile->name, channame);

View File

@ -1,4 +1,3 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
@ -120,6 +119,7 @@ struct switch_channel {
switch_channel_state_t state;
switch_channel_state_t running_state;
uint32_t flags[CF_FLAG_MAX];
uint32_t caps[CC_FLAG_MAX];
uint8_t state_flags[CF_FLAG_MAX];
uint32_t private_flags;
uint32_t app_flags;
@ -841,6 +841,33 @@ SWITCH_DECLARE(switch_status_t) switch_channel_wait_for_flag(switch_channel_t *c
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void) switch_channel_set_cap(switch_channel_t *channel, switch_channel_cap_t cap)
{
switch_assert(channel);
switch_assert(channel->flag_mutex);
switch_mutex_lock(channel->flag_mutex);
channel->caps[cap] = 1;
switch_mutex_unlock(channel->flag_mutex);
}
SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap)
{
switch_assert(channel != NULL);
switch_assert(channel->flag_mutex);
switch_mutex_lock(channel->flag_mutex);
channel->caps[cap] = 0;
switch_mutex_unlock(channel->flag_mutex);
}
SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
{
switch_assert(channel != NULL);
return channel->caps[cap] ? 1 : 0;
}
SWITCH_DECLARE(void) switch_channel_set_flag(switch_channel_t *channel, switch_channel_flag_t flag)
{
switch_assert(channel);

View File

@ -161,7 +161,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
const char *silence_var, *var;
int silence_val = 0, bypass_media_after_bridge = 0;
const char *bridge_answer_timeout = NULL;
int answer_timeout, sent_update = -50;
int answer_timeout, sent_update = 0;
time_t answer_limit = 0;
@ -184,6 +184,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
chan_b = switch_core_session_get_channel(session_b);
ans_a = switch_channel_test_flag(chan_a, CF_ANSWERED);
if ((originator = switch_channel_test_flag(chan_a, CF_BRIDGE_ORIGINATOR))) {
pre_b = switch_channel_test_flag(chan_a, CF_EARLY_MEDIA);
ans_b = switch_channel_test_flag(chan_b, CF_ANSWERED);
@ -397,12 +398,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
}
}
if (originator && sent_update < 0 && ans_a && ans_b) {
if (!++sent_update) {
switch_ivr_bridge_display(session_a, session_b);
sent_update = 1;
}
if (originator && !sent_update && ans_a && ans_b && switch_channel_media_ack(chan_a) && switch_channel_media_ack(chan_b)) {
switch_ivr_bridge_display(session_a, session_b);
sent_update = 1;
}
#ifndef SWITCH_VIDEO_IN_THREADS