FS-9300: Add support for disabling sofia's 100 Trying via configuration, and sending 100 Trying from dialplan

This commit is contained in:
Armen Babikyan 2016-06-26 22:55:07 -07:00
parent 9e971e5602
commit 6ed86abf9f
15 changed files with 133 additions and 5 deletions

View File

@ -828,5 +828,13 @@
</condition>
</extension>
<extension name="acknowledge_call">
<condition field="destination_number" expression="^(.*)$">
<action application="acknowledge_call"/>
<action application="ring_ready"/>
<action application="playback" data="$${hold_music}"/>
</condition>
</extension>
</context>
</include>

View File

@ -418,5 +418,9 @@
-->
<!--<param name="renegotiate-codec-on-hold" value="true"/>-->
<!-- By default mod_sofia will send "100 Trying" in response to a SIP INVITE. Set this to false if
you want to turn off this behavior and manually send the "100 Trying" via the acknowledge_call application.
-->
<!--<param name="auto-invite-100" value="false"/>-->
</settings>
</profile>

View File

@ -6460,8 +6460,14 @@ static int nta_incoming_response_headers(nta_incoming_t *irq,
clone = 1, sip->sip_call_id = sip_call_id_copy(home, irq->irq_call_id);
if (!sip->sip_cseq)
clone = 1, sip->sip_cseq = sip_cseq_copy(home, irq->irq_cseq);
if (!sip->sip_via)
clone = 1, sip->sip_via = sip_via_copy(home, irq->irq_via);
if (!sip->sip_via) {
clone = 1;
/* 100 responses are not forwarded by proxies, so only include the topmost Via header */
if (sip->sip_status && sip->sip_status->st_status == 100)
sip->sip_via = (sip_via_t *)msg_header_copy_one(home, (msg_header_t const *)irq->irq_via);
else
sip->sip_via = sip_via_copy(home, irq->irq_via);
}
if (clone)
msg_set_parent(msg, (msg_t *)irq->irq_home);
@ -6530,7 +6536,7 @@ int nta_incoming_complete_response(nta_incoming_t *irq,
if (sip_to_tag(home, sip->sip_to, irq->irq_tag) < 0)
return -1;
if (status < 300 && !sip->sip_record_route && irq->irq_record_route)
if (status > 100 && status < 300 && !sip->sip_record_route && irq->irq_record_route)
if (sip_add_dup(msg, sip, (sip_header_t *)irq->irq_record_route) < 0)
return -1;

View File

@ -173,6 +173,8 @@ int nua_stack_set_defaults(nua_handle_t *nh,
NHP_SET(nhp, keepalive, 120000);
NHP_SET(nhp, auto_invite_100, 1);
NHP_SET(nhp, appl_method,
sip_allow_make(home, "INVITE, REGISTER, PUBLISH, SUBSCRIBE"));
@ -1013,6 +1015,10 @@ static int nhp_set_tags(su_home_t *home,
else if (tag == ntatag_default_proxy) {
NHP_SET_STR_BY_URL(nhp, url_string_t, proxy, value);
}
/* NUTAG_AUTO_INVITE_100() */
else if (tag == nutag_auto_invite_100) {
NHP_SET(nhp, auto_invite_100, value != 0);
}
/* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */
else if (ngp && tag == nutag_detect_network_updates) {
int detector = (int)value;

View File

@ -115,6 +115,9 @@ struct nua_handle_preferences
/** Enable Retry-After */
unsigned nhp_retry_after_enable:1;
/** Enable/Disable automatic 100 Trying when receiving INVITE */
unsigned nhp_auto_invite_100:1;
unsigned:0;
/* Default lifetime for implicit subscriptions created by REFER */
@ -215,6 +218,7 @@ struct nua_handle_preferences
unsigned nhb_proxy:1;
unsigned nhb_timer_autorequire:1;
unsigned nhb_retry_after_enable:1;
unsigned nhb_auto_invite_100:1;
unsigned :0;
} set_bits;
unsigned set_unsigned[2];

View File

@ -262,7 +262,8 @@ int nua_stack_process_request(nua_handle_t *nh,
if (sr->sr_status <= 100) {
SR_STATUS1(sr, SIP_100_TRYING);
if (method == sip_method_invite || sip->sip_timestamp) {
if ((method == sip_method_invite && nh->nh_prefs->nhp_auto_invite_100) ||
sip->sip_timestamp) {
nta_incoming_treply(irq, SIP_100_TRYING,
SIPTAG_USER_AGENT_STR(user_agent),
TAG_END());
@ -459,7 +460,12 @@ nua_stack_respond(nua_t *nua, nua_handle_t *nh,
nua_server_params(sr, tags);
nua_server_respond(sr, tags);
nua_server_report(sr);
if (!(sr->sr_method == sip_method_invite && status == 100)) {
/* Since we don't change state, do not notify application when
we send 100 Trying for INVITE */
nua_server_report(sr);
}
}
int nua_server_params(nua_server_request_t *sr, tagi_t const *tags)
@ -528,6 +534,13 @@ int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags)
goto internal_error;
}
if (sr->sr_status == 100) {
return nta_incoming_treply(sr->sr_irq, SIP_100_TRYING,
SIPTAG_USER_AGENT_STR(NH_PGET(nh, user_agent)),
TAG_END());
return 0;
}
if (sr->sr_status < 200) {
next.msg = nta_incoming_create_response(sr->sr_irq, 0, NULL);
next.sip = sip_object(next.msg);

View File

@ -2796,6 +2796,13 @@ tag_typedef_t nutag_auth_cache = INTTAG_TYPEDEF(auth_cache);
* Reference tag for NUTAG_AUTH_CACHE().
*/
/**@def NUTAG_AUTO_INVITE_100(x)
*/
tag_typedef_t nutag_auto_invite_100 = INTTAG_TYPEDEF(auto_invite_100);
/**@def NUTAG_AUTO_INVITE_100(x)
* Reference tag for NUTAG_AUTO_INVITE_100().
*/
/**@def NUTAG_DETECT_NETWORK_UPDATES(x)
*

View File

@ -611,6 +611,13 @@ SOFIAPUBVAR tag_typedef_t nutag_shutdown_events;
nutag_shutdown_events_ref, tag_bool_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_shutdown_events_ref;
#define NUTAG_AUTO_INVITE_100(x) \
nutag_auto_invite_100, tag_bool_v(x)
SOFIAPUBVAR tag_typedef_t nutag_auto_invite_100;
#define NUTAG_AUTO_INVITE_100_REF(x) \
nutag_auto_invite_100_ref, tag_bool_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_auto_invite_100_ref;
/* Pass nua handle as tagged argument */
#if SU_INLINE_TAG_CAST
su_inline tag_value_t nutag_handle_v(nua_handle_t *v) { return (tag_value_t)v; }

View File

@ -447,6 +447,10 @@ SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel);
*/
#define switch_channel_mark_pre_answered(channel) switch_channel_perform_mark_pre_answered(channel, __FILE__, __SWITCH_FUNC__, __LINE__)
SWITCH_DECLARE(switch_status_t) switch_channel_perform_acknowledge_call(switch_channel_t *channel,
const char *file, const char *func, int line);
#define switch_channel_acknowledge_call(channel) switch_channel_perform_acknowledge_call(channel, __FILE__, __SWITCH_FUNC__, __LINE__)
SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_channel_t *channel,
switch_ring_ready_t rv,
const char *file, const char *func, int line);

View File

@ -1052,6 +1052,7 @@ typedef enum {
SWITCH_MESSAGE_REDIRECT_AUDIO,
SWITCH_MESSAGE_TRANSMIT_TEXT,
SWITCH_MESSAGE_INDICATE_ANSWER,
SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL,
SWITCH_MESSAGE_INDICATE_PROGRESS,
SWITCH_MESSAGE_INDICATE_BRIDGE,
SWITCH_MESSAGE_INDICATE_UNBRIDGE,

View File

@ -1048,6 +1048,11 @@ SWITCH_STANDARD_APP(capture_text_function)
switch_ivr_capture_text(session, switch_true((char *)data));
}
SWITCH_STANDARD_APP(acknowledge_call_function)
{
switch_channel_acknowledge_call(switch_core_session_get_channel(session));
}
SWITCH_STANDARD_APP(ring_ready_function)
{
if (!zstr(data)) {
@ -6298,6 +6303,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "capture_text", "capture text", "capture text", capture_text_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "acknowledge_call", "Indicate Call Acknowledged", "Indicate Call Acknowledged on a channel.", acknowledge_call_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "[<function>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);

View File

@ -55,6 +55,7 @@ static switch_status_t sofia_on_init(switch_core_session_t *session);
static switch_status_t sofia_on_exchange_media(switch_core_session_t *session);
static switch_status_t sofia_on_soft_execute(switch_core_session_t *session);
static switch_status_t sofia_acknowledge_call(switch_core_session_t *session);
static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
@ -137,6 +138,14 @@ static switch_status_t sofia_on_routing(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_INVITE_100) &&
!switch_channel_test_flag(channel, CF_ANSWERED) &&
switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if (sofia_acknowledge_call(session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Call appears to be already acknowledged\n");
}
}
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
@ -642,6 +651,19 @@ static switch_status_t sofia_on_soft_execute(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_acknowledge_call(switch_core_session_t *session)
{
struct private_object *tech_pvt = switch_core_session_get_private(session);
if (!tech_pvt->sent_100) {
nua_respond(tech_pvt->nh, SIP_100_TRYING, TAG_END());
tech_pvt->sent_100 = 1;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t sofia_answer_channel(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
@ -656,6 +678,10 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
if (switch_channel_test_flag(channel, CF_CONFERENCE) && !switch_stristr(";isfocus", tech_pvt->reply_contact)) {
tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
}
@ -2176,6 +2202,12 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
}
/* Dialplan should really use acknowledge_call application instead of respond application to send 100 */
if (code == 100) {
status = sofia_acknowledge_call(session);
goto end_lock;
}
if (tech_pvt->proxy_refer_uuid) {
if (tech_pvt->proxy_refer_msg) {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
@ -2295,10 +2327,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
}
break;
case SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL:
status = sofia_acknowledge_call(session);
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
{
switch_ring_ready_t ring_ready_val = msg->numeric_arg;
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
if (!switch_channel_test_flag(channel, CF_RING_READY) && !sofia_test_flag(tech_pvt, TFLAG_BYE) &&
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
@ -2360,6 +2399,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
int send_sip_code = 183;
const char * p_send_sip_msg = sip_183_Session_progress;
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
is_3pcc_proxy = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));

View File

@ -307,6 +307,7 @@ typedef enum {
PFLAG_PROXY_INFO,
PFLAG_PROXY_MESSAGE,
PFLAG_FIRE_BYE_RESPONSE_EVENTS,
PFLAG_AUTO_INVITE_100,
/* No new flags below this line */
PFLAG_MAX
@ -839,6 +840,7 @@ struct private_object {
sip_contact_t *contact;
int q850_cause;
int got_bye;
int sent_100;
nua_event_t want_event;
switch_rtp_bug_flag_t rtp_bugs;
char *user_via;

View File

@ -3155,6 +3155,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
NTATAG_TCP_RPORT(0),
NTATAG_TLS_RPORT(0),
NUTAG_RETRY_AFTER_ENABLE(0),
NUTAG_AUTO_INVITE_100(0),
TAG_IF(!strchr(profile->sipip, ':'),
SOATAG_AF(SOA_AF_IP4_ONLY)),
TAG_IF(strchr(profile->sipip, ':'),
@ -4517,6 +4518,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
}
profile->tls_verify_policy = TPTLS_VERIFY_NONE;
sofia_set_pflag(profile, PFLAG_AUTO_INVITE_100);
/* lib default */
profile->tls_verify_depth = 2;
@ -5326,6 +5328,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_SECURE);
}
} else if (!strcasecmp(var, "auto-invite-100")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_AUTO_INVITE_100);
} else {
sofia_clear_pflag(profile, PFLAG_AUTO_INVITE_100);
}
} else {
found = 0;
}
@ -9833,6 +9841,8 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
switch_channel_t *channel = NULL;
private_object_t *tech_pvt = NULL;
nua_respond(nh, SIP_100_TRYING, TAG_END());
if (session) {
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);

View File

@ -3305,6 +3305,13 @@ static switch_status_t send_ind(switch_channel_t *channel, switch_core_session_m
return switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
}
SWITCH_DECLARE(switch_status_t) switch_channel_perform_acknowledge_call(switch_channel_t *channel,
const char *file, const char *func, int line)
{
send_ind(channel, SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL, file, func, line);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(switch_channel_t *channel,
switch_ring_ready_t rv,