]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9300: Add support for disabling sofia's 100 Trying via configuration, and sending...
authorArmen Babikyan <armen@firespotter.com>
Mon, 27 Jun 2016 05:55:07 +0000 (22:55 -0700)
committerArmen Babikyan <armen@firespotter.com>
Mon, 13 Feb 2017 22:49:05 +0000 (14:49 -0800)
15 files changed:
conf/vanilla/dialplan/default.xml
conf/vanilla/sip_profiles/internal.xml
libs/sofia-sip/libsofia-sip-ua/nta/nta.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h
libs/sofia-sip/libsofia-sip-ua/nua/nua_server.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c
libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h
src/include/switch_channel.h
src/include/switch_types.h
src/mod/applications/mod_dptools/mod_dptools.c
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/switch_channel.c

index d4ae8e711a6c8979ab8dd53bfb76d4e46e0373dc..a6e26c1928bd3c315f7623e5620d9e8014fa5d7e 100644 (file)
       </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>
index 1529248097a40da1c23bc89fc8109b4bd806c6e5..1da1e0470c3150f7c4cb847381328eb560b44087 100644 (file)
     -->
     <!--<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>
index bb68025749e4f36663c0b612c6d5b96ee47efecd..9b2e295007a57bc8a1e914737a49236410c93778 100644 (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;
 
index 8ff26848819164920a93eb0425dd575bac2cbc54..2d21acbaa28dee6ae24284d255424648682da95a 100644 (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;
index 5c26e4ef1349312ae70ac490909cb8140c686a2d..d48ceca155d3f5fc275a3695d152a2ddff7d9d43 100644 (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];
index deae102ca2b6a211621deee4c4604b1f4510a5e4..cf8e23577deaa2765b2f0632adbe6ff890765239 100644 (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);
index 7670b9326861e647b357b923ba4ad4866ff50f6c..21dede4343e5827c70b6e703357f97f1583e8d8b 100644 (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)
  *
index 2c3a72ca04b0f5336047dc9a1f6b9864cf7b46b2..3a3f96e02b9085a80ef403eebbda42400ee49b8d 100644 (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; }
index b348dccc519ea57a11b1202ab86add9a36418090..bc37dd2e6c67beeee9b5360051afca303eb057c4 100644 (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);
index 0ebcef406ee78a215abd906a672999d46395139e..fff02cfcb06a7bf263f50101ecaca317946bccca 100644 (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,
index 9e9f4465499a80c87ddf0ce60562ff4eb504985c..937d214827d5ddf834ec43d06a0b3dc57990537d 100644 (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);
index 1c5d0e48a11153bcda311469e78c8df8bf8efd35..96a13be7f7840b98cbcc3be7a70dd4c774ae052d 100644 (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));
index a66fc92420a9a451fd6994d17597413fad9dc3a2..b8d1a32a0c076976151a421db68ab3445b16d185 100644 (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;
index 27750e25ba8a7306ab093f392c6eb584f72d2223..c8311dc8280ff5859e1b2dfddb9801a5d6ef5063 100644 (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);
index 8086944190277c31bce085cdd17773d38b97e3e2..44ed2ee6854c357bb85486eeaed1441d557a2c8a 100644 (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,