]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-6833 #comment please test this branch
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 2 Jul 2015 20:17:26 +0000 (15:17 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Tue, 1 Sep 2015 21:31:23 +0000 (16:31 -0500)
src/include/switch_ivr.h
src/include/switch_types.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/sofia.c
src/switch_core_media.c
src/switch_ivr.c
src/switch_ivr_bridge.c

index 7bb00cb06bab4577d50b7878cec4ceacae45cd2d..999d028eba6a3b83cf510855eebeb556b159fbbc 100644 (file)
@@ -588,7 +588,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
   \return SWITCH_STATUS_SUCCESS if all is well
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_flag_t flags);
-
+SWITCH_DECLARE(switch_status_t) switch_ivr_3p_media(const char *uuid, switch_media_flag_t flags);
 /*!
   \brief Signal a session to request indirect media allowing it to exchange media directly with another device
   \param uuid the uuid of the session to request
@@ -596,6 +596,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_
   \return SWITCH_STATUS_SUCCESS if all is well
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_media_flag_t flags);
+SWITCH_DECLARE(switch_status_t) switch_ivr_3p_nomedia(const char *uuid, switch_media_flag_t flags);
 
 /*!
   \brief Signal the session with a protocol specific hold message.
index 068df98dadf2c0bc747722827087b840ab1e3b5b..c6090eaa08a5c71cf029a9537b7ae6acc02cd6f4 100644 (file)
@@ -1038,7 +1038,9 @@ typedef enum {
        SWITCH_MESSAGE_INDICATE_TRANSFER,
        SWITCH_MESSAGE_INDICATE_RINGING,
        SWITCH_MESSAGE_INDICATE_MEDIA,
+       SWITCH_MESSAGE_INDICATE_3P_MEDIA,
        SWITCH_MESSAGE_INDICATE_NOMEDIA,
+       SWITCH_MESSAGE_INDICATE_3P_NOMEDIA,
        SWITCH_MESSAGE_INDICATE_HOLD,
        SWITCH_MESSAGE_INDICATE_UNHOLD,
        SWITCH_MESSAGE_INDICATE_REDIRECT,
@@ -1489,6 +1491,9 @@ typedef enum {
        CF_VIDEO_MIRROR_INPUT,
        CF_VIDEO_READ_FILE_ATTACHED,
        CF_VIDEO_WRITE_FILE_ATTACHED,
+       CF_3P_MEDIA_REQUESTED,
+       CF_3P_NOMEDIA_REQUESTED,
+       CF_3P_NOMEDIA_REQUESTED_BLEG,
        /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
        /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
        CF_FLAG_MAX
index 68e8d2a605d850ecb2f1455b089300b2bb1929d2..768f1709886922a71c80c2df6e9db0ef9e415279 100644 (file)
@@ -3404,6 +3404,37 @@ SWITCH_STANDARD_API(uuid_media_function)
        return SWITCH_STATUS_SUCCESS;
 }
 
+#define MEDIA_SYNTAX "[off] <uuid>"
+SWITCH_STANDARD_API(uuid_media_3p_function)
+{
+       char *mycmd = NULL, *argv[4] = { 0 };
+       int argc = 0;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+               argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (zstr(cmd) || argc < 1 || zstr(argv[0])) {
+               stream->write_function(stream, "-USAGE: %s\n", MEDIA_SYNTAX);
+       } else {
+               if (!strcasecmp(argv[0], "off")) {
+                       status = switch_ivr_3p_nomedia(argv[1], SMF_REBRIDGE);
+               } else {
+                       status = switch_ivr_3p_media(argv[0], SMF_REBRIDGE);
+               }
+       }
+
+       if (status == SWITCH_STATUS_SUCCESS) {
+               stream->write_function(stream, "+OK Success\n");
+       } else {
+               stream->write_function(stream, "-ERR Operation failed\n");
+       }
+
+       switch_safe_free(mycmd);
+       return SWITCH_STATUS_SUCCESS;
+}
+
 #define MEDIA_RENEG_SYNTAX "<uuid>[ <codec_string>]"
 SWITCH_STANDARD_API(uuid_media_neg_function)
 {
@@ -6959,6 +6990,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
        SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX);
        SWITCH_ADD_API(commands_api_interface, "uuid_loglevel", "Set loglevel on session", uuid_loglevel, UUID_LOGLEVEL_SYNTAX);
        SWITCH_ADD_API(commands_api_interface, "uuid_media", "Reinvite FS in or out of media path", uuid_media_function, MEDIA_SYNTAX);
+       SWITCH_ADD_API(commands_api_interface, "uuid_media_3p", "Reinvite FS in or out of media path using 3pcc", uuid_media_3p_function, MEDIA_SYNTAX);
        SWITCH_ADD_API(commands_api_interface, "uuid_media_reneg", "Media negotiation", uuid_media_neg_function, MEDIA_RENEG_SYNTAX);
        SWITCH_ADD_API(commands_api_interface, "uuid_park", "Park channel", park_function, PARK_SYNTAX);
        SWITCH_ADD_API(commands_api_interface, "uuid_pause", "Pause media on a channel", pause_function, PAUSE_SYNTAX);
index 29281d0cd6a1261ed200d06d4726d60793629c26..b2f37b381574d56e83ed1c8737876e08fbf30248 100644 (file)
@@ -969,8 +969,9 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
                return SWITCH_STATUS_FALSE;
        }
 
-       while (!(switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
+       while (!(switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO))){// && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
                switch_ivr_parse_all_messages(tech_pvt->session);
+
                if (--sanity && switch_channel_up(channel)) {
                        switch_yield(10000);
                } else {
@@ -1374,7 +1375,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                                          switch_channel_get_name(channel), msg->string_arg);
                        switch_core_media_set_local_sdp(session, msg->string_arg, SWITCH_TRUE);
 
-                       if(zstr(tech_pvt->mparams.local_sdp_str)) {
+                       if (zstr(tech_pvt->mparams.local_sdp_str)) {
                                sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
                        }
 
@@ -1447,6 +1448,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                }
                break;
 
+       case SWITCH_MESSAGE_INDICATE_3P_NOMEDIA:
+               {
+                       nua_invite(tech_pvt->nh, NUTAG_MEDIA_ENABLE(0), SIPTAG_PAYLOAD_STR(msg->string_arg), TAG_END());
+               }
+               break;
+       case SWITCH_MESSAGE_INDICATE_3P_MEDIA:
+               {
+                       nua_invite(tech_pvt->nh, NUTAG_MEDIA_ENABLE(0), SIPTAG_PAYLOAD_STR(""), TAG_END());
+               }
+               break;
+
        case SWITCH_MESSAGE_INDICATE_MEDIA:
                {
                        uint32_t send_invite = 1;
index 96d2466e1503269e2dc8613013fb895cfd7f09d8..35038c4645bb31a9e9a9dea9ab1eb5d8d2a2dbe2 100644 (file)
@@ -6929,6 +6929,93 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                }
                        }
 
+                       if (switch_channel_test_flag(channel, CF_3P_NOMEDIA_REQUESTED)) {
+                               switch_channel_clear_flag(channel, CF_3P_NOMEDIA_REQUESTED);
+                               if (switch_channel_test_flag(channel, CF_3P_NOMEDIA_REQUESTED_BLEG)) {
+                                       switch_core_session_t *other_session;
+                                       
+                                       switch_channel_clear_flag(channel, CF_3P_NOMEDIA_REQUESTED_BLEG);
+                                       
+                                       if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
+                                               if (switch_core_session_compare(session, other_session)) {
+                                                       //switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+                                                       private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
+
+                                                       nua_ack(other_tech_pvt->nh,
+                                                                       NUTAG_MEDIA_ENABLE(0),
+                                                                       TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
+                                                                       SIPTAG_CONTACT_STR(other_tech_pvt->reply_contact),
+                                                                       SIPTAG_PAYLOAD_STR(r_sdp),
+                                                                       TAG_END());
+
+
+                                                       nua_ack(tech_pvt->nh,
+                                                                       TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
+                                                                       SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+                                                                       TAG_END());
+                                                       
+                                               }
+                                               switch_core_session_rwunlock(other_session);
+                                       }
+                               } else {
+                                       switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
+                               }
+                               
+                               goto done;
+
+                       } else if (switch_channel_test_flag(channel, CF_3P_MEDIA_REQUESTED)) {
+                               uint8_t match = 0;
+                               
+                               switch_channel_clear_flag(channel, CF_3P_MEDIA_REQUESTED);
+                               switch_channel_clear_flag(channel, CF_PROXY_MODE);
+                               
+                               switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
+                               switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
+
+                               if (tech_pvt->mparams.num_codecs) {
+                                       match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
+                               }
+
+                               if (!match) {
+                                       if (switch_channel_get_state(channel) != CS_NEW) {
+                                               nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
+                                       }
+                               } else {
+                                       switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
+                                       switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED");
+                                       sofia_set_flag_locked(tech_pvt, TFLAG_READY);
+                                       
+                                       sofia_set_flag(tech_pvt, TFLAG_SDP);
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RESTABLISH MEDIA SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
+
+                                       switch_channel_set_flag(channel, CF_REQ_MEDIA);
+                                       switch_channel_set_flag(channel, CF_MEDIA_ACK);
+                                       switch_channel_set_flag(channel, CF_MEDIA_SET);
+
+                                       switch_core_media_activate_rtp(session);
+                                       
+                                       nua_ack(tech_pvt->nh,
+                                                       TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
+                                                       SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+                                                       //SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
+                                                       SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
+                                                       //SOATAG_REUSE_REJECTED(1),
+                                                       //SOATAG_RTP_SELECT(1), 
+                                                       SOATAG_AUDIO_AUX("cn telephone-event"),
+                                                       //TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
+                                                       TAG_END());
+                                       
+                                       goto done;
+                               }
+
+                               switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "NO CODECS");
+                               switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+
+                               goto done;
+                               //ss_state = nua_callstate_ready;
+                               //goto state_process;
+                       }
+
                        if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE) && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
                                sofia_set_flag(tech_pvt, TFLAG_SDP);
                                if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
@@ -7139,6 +7226,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                }
                                goto done;
                        }
+
+
+                       switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
+
                        nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
                        goto done;
                } else if (r_sdp && !sofia_use_soa(tech_pvt)) {
@@ -7481,7 +7572,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                int is_ok = 1;
 
                                if (tech_pvt->mparams.num_codecs) {
-                                       match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
+                                       match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
                                }
 
                                if (match) {
index 24395b129257a5867820e6508a0adce7836cdb41..e09612a0ec662f9d2f4d30d4df6c69f44906696d 100644 (file)
@@ -9042,7 +9042,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
                        switch_rtp_flush(v_engine->rtp_session);
                }
                goto end;
-
+       case SWITCH_MESSAGE_INDICATE_3P_MEDIA:
        case SWITCH_MESSAGE_INDICATE_MEDIA:
                {
 
@@ -9054,6 +9054,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
                        }
                }
                break;
+
+       case SWITCH_MESSAGE_INDICATE_3P_NOMEDIA:
+               switch_channel_set_flag(session->channel, CF_PROXY_MODE);
+               switch_core_media_set_local_sdp(session, NULL, SWITCH_FALSE); 
+               break;
        case SWITCH_MESSAGE_INDICATE_NOMEDIA:
                {
                        const char *uuid;
index 1bf876c44192cf1227b1837a81bedffcf47ec670..3e514d1e617ff599deae6aa756f9a1625ee82060 100644 (file)
@@ -1548,6 +1548,114 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_unhold_uuid(const char *uuid)
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_3p_media(const char *uuid, switch_media_flag_t flags)
+{
+       const char *other_uuid = NULL;
+       switch_channel_t *channel, *other_channel = NULL;
+       switch_core_session_t *session, *other_session;
+       switch_core_session_message_t msg = { 0 };
+       switch_status_t status = SWITCH_STATUS_GENERR;
+       uint8_t swap = 0;
+       //switch_frame_t *read_frame = NULL;
+
+       msg.message_id = SWITCH_MESSAGE_INDICATE_3P_MEDIA;
+       msg.from = __FILE__;
+
+       if ((session = switch_core_session_locate(uuid))) {
+               channel = switch_core_session_get_channel(session);
+               
+               if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
+                       switch_core_session_rwunlock(session);
+                       return SWITCH_STATUS_INUSE;
+               }
+
+               switch_channel_set_flag(channel, CF_MEDIA_TRANS);
+
+               if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
+                       swap = 1;
+               }
+
+               if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
+                       status = SWITCH_STATUS_SUCCESS;
+
+                       /* If we had early media in bypass mode before, it is no longer relevant */
+                       if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
+                               switch_core_session_message_t msg2 = { 0 };
+                               
+                               msg2.message_id = SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS;
+                               msg2.from = __FILE__;
+                               switch_core_session_receive_message(session, &msg2);
+                       }
+                       
+                       if ((flags & SMF_REPLYONLY_A)) {
+                               msg.numeric_arg = 1;
+                       }
+                       
+                       switch_channel_set_flag(channel, CF_3P_MEDIA_REQUESTED);
+
+                       if (switch_core_session_receive_message(session, &msg) != SWITCH_STATUS_SUCCESS) {
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
+                               switch_channel_clear_flag(channel, CF_3P_MEDIA_REQUESTED);
+                               switch_core_session_rwunlock(session);
+                               return SWITCH_STATUS_GENERR;
+                       }
+
+                       if ((flags & SMF_REPLYONLY_B)) {
+                               msg.numeric_arg = 1;
+                       } else {
+                               msg.numeric_arg = 0;
+                       }
+
+                       if ((flags & SMF_IMMEDIATE)) {
+                               switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 250, NULL);
+                               switch_yield(250000);
+                       } else {
+                               switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
+                               switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
+                               switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
+                               //switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+                       }
+
+                       if ((flags & SMF_REBRIDGE)
+                               && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE))
+                               && (other_session = switch_core_session_locate(other_uuid))) {
+
+                               other_channel = switch_core_session_get_channel(other_session);
+                               switch_assert(other_channel != NULL);
+                               
+                               switch_channel_set_flag(other_channel, CF_3P_MEDIA_REQUESTED);
+                               switch_channel_set_variable(other_channel, "rtp_secure_media", "optional");
+                               
+                               switch_core_session_receive_message(other_session, &msg);
+                               switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
+                               switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
+                               switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
+                               //switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+                               switch_channel_clear_state_handler(other_channel, NULL);
+                               switch_core_session_rwunlock(other_session);
+                       }
+                       if (other_channel) {
+                               switch_channel_clear_state_handler(channel, NULL);
+                       }
+               }
+
+               switch_channel_clear_flag(channel, CF_MEDIA_TRANS);
+               switch_core_session_rwunlock(session);
+
+               if (other_channel) {
+                       if (swap) {
+                               switch_ivr_uuid_bridge(other_uuid, uuid);
+                       } else {
+                               switch_ivr_uuid_bridge(uuid, other_uuid);
+                       }
+                       switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
+                       switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
+               }
+       }
+
+       return status;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_flag_t flags)
 {
        const char *other_uuid = NULL;
@@ -1648,6 +1756,104 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_
        return status;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_3p_nomedia(const char *uuid, switch_media_flag_t flags)
+{
+       const char *other_uuid;
+       switch_channel_t *channel, *other_channel = NULL;
+       switch_core_session_t *session, *other_session = NULL;
+       switch_core_session_message_t msg = { 0 };
+       switch_status_t status = SWITCH_STATUS_GENERR;
+       uint8_t swap = 0;
+
+       msg.message_id = SWITCH_MESSAGE_INDICATE_3P_NOMEDIA;
+       msg.from = __FILE__;
+
+       if ((session = switch_core_session_locate(uuid))) {
+               status = SWITCH_STATUS_SUCCESS;
+               channel = switch_core_session_get_channel(session);
+               
+               if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
+                       switch_core_session_rwunlock(session);
+                       return SWITCH_STATUS_INUSE;
+               }
+
+               switch_channel_set_flag(channel, CF_MEDIA_TRANS);
+
+               if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
+                       swap = 1;
+               }
+
+               if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
+                       if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
+                               (other_session = switch_core_session_locate(other_uuid))) {
+                               other_channel = switch_core_session_get_channel(other_session);
+               
+                               switch_channel_set_flag(channel, CF_REDIRECT);
+                               switch_channel_set_flag(channel, CF_RESET);
+                               
+                               switch_channel_set_flag(other_channel, CF_RESET);
+                               switch_channel_set_flag(other_channel, CF_REDIRECT);
+
+                               switch_channel_set_flag(channel, CF_3P_NOMEDIA_REQUESTED);
+                               switch_core_session_receive_message(session, &msg);
+
+                               if (!switch_core_session_in_thread(session)) {
+                                       switch_channel_set_state(channel, CS_PARK);
+                               }
+                               switch_channel_set_state(other_channel, CS_PARK);
+                               if (switch_core_session_in_thread(session)) {
+                                       switch_yield(100000);
+                               } else {
+                                       switch_channel_wait_for_state(other_channel, channel, CS_PARK);
+                               }
+                               
+                               msg.string_arg = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
+                               switch_channel_set_flag(other_channel, CF_3P_NOMEDIA_REQUESTED);
+                               switch_channel_set_flag(other_channel, CF_3P_NOMEDIA_REQUESTED_BLEG);
+                               
+                               switch_core_session_receive_message(other_session, &msg);
+                               switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
+                               switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
+                       }
+
+                       if (other_channel) {
+                               if (!switch_core_session_in_thread(session)) {
+                                       switch_channel_wait_for_state(channel, NULL, CS_PARK);
+                                       switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
+                                       switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
+                                       switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
+                               }
+
+                               if (swap) {
+                                       switch_ivr_signal_bridge(other_session, session);
+                               } else {
+                                       switch_ivr_signal_bridge(session, other_session);
+                               }
+
+                               if (switch_core_session_in_thread(session)) {
+                    switch_yield(100000);
+                } else {
+                                       switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
+                               }
+
+                               if (!switch_core_session_in_thread(session)) {
+                                       switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
+                               }
+                               switch_core_session_rwunlock(other_session);
+                       }
+               }
+
+               switch_channel_clear_flag(channel, CF_MEDIA_TRANS);
+               switch_core_session_rwunlock(session);
+       }
+
+       
+
+       return status;
+}
+
+
+
 SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_media_flag_t flags)
 {
        const char *other_uuid;
index ccf0f9c5bd947086dd7435f54c32ac096630f89a..ecad0171aebc3b2a4f345d864a63b826cadd3222 100644 (file)
@@ -1762,7 +1762,8 @@ static void cleanup_proxy_mode_a(switch_core_session_t *session)
        switch_channel_t *channel = switch_core_session_get_channel(session);
        int done = 0;
 
-       if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
+       if (!switch_channel_test_flag(channel, CF_3P_MEDIA_REQUESTED) && 
+               switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_test_flag(channel, CF_3P_NOMEDIA_REQUESTED)) {
                if (switch_core_session_get_partner(session, &sbsession) == SWITCH_STATUS_SUCCESS) {
                        switch_channel_t *sbchannel = switch_core_session_get_channel(sbsession);
 
@@ -1844,7 +1845,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
                        if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) {
                                switch_channel_clear_flag(originatee_channel, CF_DIALPLAN);
                        }
-
+                       
                        cleanup_proxy_mode_a(originator_session);
                        cleanup_proxy_mode_a(originatee_session);