]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-6341: --resolve add 3pcc invite w/o sdp support for 100rel/PRACK
authorMichael Jerris <mike@jerris.com>
Mon, 17 Mar 2014 16:27:42 +0000 (12:27 -0400)
committerMichael Jerris <mike@jerris.com>
Mon, 17 Mar 2014 16:27:42 +0000 (12:27 -0400)
libs/sofia-sip/.update
libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/sofia.c
src/switch_core_media.c

index 42af2ffe4bd4c87c8930e7c943224bfd467c4490..5c7c7bea09bf46cb36d223c89e933dda231958db 100644 (file)
@@ -1 +1 @@
-Fri Mar 14 12:27:15 CDT 2014
+Mon Mar 17 12:22:51 EDT 2014
index f0b4d35d58bb113285a8f031c1e175be1d6d4818..c9736387be1f0af47685ef9c275cc76d9ed7c7ea 100644 (file)
@@ -2952,7 +2952,7 @@ int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags)
   nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage);
   nua_server_request_t *sri = nta_incoming_magic(sr->sr_irq, NULL);
   int status = sr->sr_status; char const *phrase = sr->sr_phrase;
-  int offer_recv_or_answer_sent = sr->sr_offer_recv || sr->sr_answer_sent;
+  int offer_recv_or_answer_sent = sr->sr_offer_recv || sr->sr_answer_sent || sr->sr_offer_sent || sr->sr_answer_recv;
   int retval;
 
   retval = nua_base_server_report(sr, tags), sr = NULL; /* destroys sr */
index c373804c08c4479020b5f14beffb8f49b034fc76..1be1a96a00945c2fcde929847407507c54925ea5 100644 (file)
@@ -1399,6 +1399,7 @@ typedef enum {
        CF_DTLS,
        CF_VERBOSE_SDP,
        CF_DTLS_OK,
+       CF_3PCC,
        CF_VIDEO_PASSIVE,
        CF_NOVIDEO,
        CF_VIDEO_ECHO,
index 06925863f07199c555ec43d8c18abec05638e147..d9a3df256c1dc619ba1d750bba104e1630c7b074 100644 (file)
@@ -663,11 +663,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
                /* This if statement check and handles the 3pcc proxy mode */
                if (is_3pcc) {
 
+                       switch_channel_set_flag(channel, CF_3PCC);
+
                        if(!is_proxy) {
                        switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
                        tech_pvt->mparams.local_sdp_str = NULL;
 
                        switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
+                       switch_core_session_set_ice(session);
                        switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                        } else {
                                switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
@@ -2035,7 +2038,99 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                        char *sticky = NULL;
                        const char *val = NULL;
                        const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
+                       const char *b_sdp = NULL;
+                       int is_proxy = 0, is_3pcc = 0;
+
+                       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 = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));
+
+                       if (b_sdp && is_proxy && !is_3pcc) {
+                               switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
+
+                               if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
+                                       switch_core_media_patch_sdp(tech_pvt->session);
+                                       if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+                                               return SWITCH_STATUS_FALSE;
+                                       }
+                               }
+                       } else {
+                               if (is_3pcc) {
+                                       switch_channel_set_flag(channel, CF_3PCC);
+
+                                       if(!is_proxy) {
+                                               switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
+                                               tech_pvt->mparams.local_sdp_str = NULL;
+
+                                               switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
+                                               switch_core_session_set_ice(session);
+                                               switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL            ,    0, NULL, 0);
+                                       } else {
+                                               switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
+
+                                               if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
+                                                       switch_core_media_patch_sdp(tech_pvt->session);
+                                                       if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "failed to activate rtp\n");
+                                                               return SWITCH_STATUS_FALSE;
+                                                       }
+                                               }
+                                       }
+                                       /* Send the 183 */
+                                       if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+                                               char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
+                                               if (sofia_use_soa(tech_pvt)) {
+
+                                                       nua_respond(tech_pvt->nh, SIP_183_SESSION_PROGRESS,
+                                                                               TAG_IF(is_proxy, NUTAG_AUTOANSWER(0)),
+                                                                               SIPTAG_CONTACT_STR(tech_pvt->profile->url),
+                                                                               SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
+                                                                               TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
+                                                                               SOATAG_REUSE_REJECTED(1),
+                                                                               SOATAG_RTP_SELECT(1),
+                                                                               SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
+                                                                               TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
+                                                                               TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
+                                                                                          SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
+                                               } else {
+                                                       nua_respond(tech_pvt->nh, SIP_183_SESSION_PROGRESS,
+                                                                               NUTAG_MEDIA_ENABLE(0),
+                                                                               SIPTAG_CONTACT_STR(tech_pvt->profile->url),
+                                                                               TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
+                                                                               TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
+                                                                               SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+                                                                               SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
+                                                                               TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
+                                                                                          SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
+                                               }
+
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 183 SESSION PROGRESS, waiting for PRACK\n");
+                                               switch_safe_free(extra_headers);
+                                       }
 
+                                       /* Unlock the session signal to allow the ack to make it in */
+                                       // Maybe we should timeout?
+                                       switch_mutex_unlock(tech_pvt->sofia_mutex);
+
+                                       while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) {
+                                               switch_cond_next();
+                                       }
+
+                                       /*  Regain lock on sofia */
+                                       switch_mutex_lock(tech_pvt->sofia_mutex);
+
+                                       if(is_proxy || !switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE)) {
+                                               sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
+                                               sofia_clear_flag(tech_pvt, TFLAG_3PCC);
+                                               // This sends the message to the other leg that causes it to call the TFLAG_3PCC_INVITE code at the start of this function.
+                                               // Is there another message it would be better to hang this on though?
+                                               switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
+                                       }
+
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for PRACK\n");
+                                       return SWITCH_STATUS_SUCCESS;
+                               }
+                       }
 
                        if (!sofia_test_flag(tech_pvt, TFLAG_ANS) && !sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
 
index feb42dd4d3fd953862f17c85a2c39852f5d4955a..430f0311aff879658da2490e7cef9a0a13447f81 100644 (file)
@@ -6578,6 +6578,38 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 
                break;
        case nua_callstate_early:
+               if (answer_recv) {
+                       uint8_t match = 0;
+                       int is_ok = 0;
+                       sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
+                       switch_channel_mark_pre_answered(channel);
+                       sofia_set_flag(tech_pvt, TFLAG_SDP);
+
+                       if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my PRACK\n");
+                               sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
+                       }
+
+                       match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
+                       if (match) {
+                               if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
+                                       goto done;
+                               }
+
+                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
+
+                               if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media RTP Error!\n");
+                                       is_ok = 0;
+                                       switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                               }
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
+                       } else {
+                               switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media Codec Error!\n");
+                               is_ok = 0;
+                       }
+               }
                break;
        case nua_callstate_completed:
                if (r_sdp) {
index 778bd2ff8aa32cb0238936726fa505a5c228a790..f296a5105599da7404d97da0e545e1facfafac4c 100644 (file)
@@ -2455,6 +2455,10 @@ SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session
 {
        switch_call_direction_t r = switch_channel_direction(session->channel);
 
+       if (switch_channel_test_flag(session->channel, CF_3PCC)) {
+               r = (r == SWITCH_CALL_DIRECTION_INBOUND) ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
+       }
+
        if ((switch_channel_test_flag(session->channel, CF_REINVITE) || switch_channel_test_flag(session->channel, CF_RECOVERING)) 
                && switch_channel_test_flag(session->channel, CF_WEBRTC)) {
                r = SWITCH_CALL_DIRECTION_OUTBOUND;
@@ -5087,6 +5091,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                if (!zstr(a_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
                        dtls_type_t xtype, dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
 
+                       if (switch_channel_test_flag(smh->session->channel, CF_3PCC)) {
+                               dtype = (dtype == DTLS_TYPE_CLIENT) ? DTLS_TYPE_SERVER : DTLS_TYPE_CLIENT;
+                       }
 
                        xtype = DTLS_TYPE_RTP;
                        if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP;
@@ -6048,7 +6055,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                switch_channel_clear_flag(smh->session->channel, CF_DTLS);
        }
 
-       if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
+       if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING) ||
+               switch_channel_test_flag(session->channel, CF_3PCC)) {
                if (!switch_channel_test_flag(session->channel, CF_WEBRTC) && 
                        switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
                        switch_channel_set_flag(session->channel, CF_WEBRTC);