]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
nut n honey
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 18 Sep 2008 21:50:18 +0000 (21:50 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 18 Sep 2008 21:50:18 +0000 (21:50 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9591 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_rtp.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_ivr_bridge.c
src/switch_rtp.c

index a30c8b5d07152b4694dfb3b1daa35d5d61ed2f8f..51e7d0cf6630b953176478e54396decb087aee51 100644 (file)
@@ -163,6 +163,9 @@ SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host,
 */
 SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err);
 
+SWITCH_DECLARE(char *) switch_rtp_get_remote_host(switch_rtp_t *rtp_session);
+SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_session);
+
 SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max);
 
 /*! 
index 40ea35143ce84ba1b10cb62f877da4bc73f9e4b3..23227e1d54bb48af11d82d04b014a88080a62462 100644 (file)
@@ -110,6 +110,7 @@ SWITCH_BEGIN_EXTERN_C
 #define SWITCH_PATH_SEPARATOR "/"
 #endif
 #define SWITCH_URL_SEPARATOR "://"
+#define SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE "bypass_media_after_bridge"
 #define SWITCH_READ_RESULT_VARIABLE "read_result"
 #define SWITCH_COPY_XML_CDR_VARIABLE "copy_xml_cdr"
 #define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application"
index c2c0cd9664ce85715897863cd57865665e4542b8..875ed1e28e16698ca94994124eada3d4ef09469a 100644 (file)
@@ -114,7 +114,9 @@ static switch_status_t sofia_on_routing(switch_core_session_t *session)
        private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
        switch_assert(tech_pvt != NULL);
 
-       switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       if (!switch_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+               switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       }
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SOFIA ROUTING\n", switch_channel_get_name(switch_core_session_get_channel(session)));
 
@@ -127,7 +129,9 @@ static switch_status_t sofia_on_reset(switch_core_session_t *session)
        private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
        switch_assert(tech_pvt != NULL);
 
-       switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       if (!switch_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+               switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       }
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SOFIA RESET\n", switch_channel_get_name(switch_core_session_get_channel(session)));
 
@@ -140,7 +144,9 @@ static switch_status_t sofia_on_hibernate(switch_core_session_t *session)
        private_object_t *tech_pvt = switch_core_session_get_private(session);
        switch_assert(tech_pvt != NULL);
 
-       switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       if (!switch_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+               switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       }
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SOFIA HIBERNATE\n", switch_channel_get_name(switch_core_session_get_channel(session)));
 
@@ -152,7 +158,9 @@ static switch_status_t sofia_on_execute(switch_core_session_t *session)
        private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
        switch_assert(tech_pvt != NULL);
 
-       switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       if (!switch_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+               switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+       }
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SOFIA EXECUTE\n", switch_channel_get_name(switch_core_session_get_channel(session)));
 
        return SWITCH_STATUS_SUCCESS;
index 32f79b47aeae0031205afde9341b78c4b593ea31..d465d5f75afd0fb4233f400c7bb5b690af38247a 100644 (file)
@@ -190,7 +190,7 @@ typedef enum {
        TFLAG_VAD_IN = (1 << 11),
        TFLAG_VAD_OUT = (1 << 12),
        TFLAG_VAD = (1 << 13),
-       TFLAG_USE_ME = (1 << 14),
+       TFLAG_3PCC = (1 << 14),
        TFLAG_READY = (1 << 15),
        TFLAG_REINVITE = (1 << 16),
        TFLAG_REFER = (1 << 17),
@@ -205,7 +205,8 @@ typedef enum {
        TFLAG_VIDEO = (1 << 26),
        TFLAG_TPORT_LOG = (1 << 27),
        TFLAG_SENT_UPDATE = (1 << 28),
-       TFLAG_PROXY_MEDIA = (1 << 29)
+       TFLAG_PROXY_MEDIA = (1 << 29),
+       TFLAG_HOLD_LOCK = (1 << 30)
 } TFLAGS;
 
 struct mod_sofia_globals {
@@ -302,6 +303,12 @@ typedef enum {
        PRES_TYPE_PASSIVE = 2
 } sofia_presence_type_t;
 
+typedef enum {
+       MEDIA_OPT_NONE = 0,
+       MEDIA_OPT_MEDIA_ON_HOLD = (1 << 0),
+       MEDIA_OPT_BYPASS_AFTER_ATT_XFER = (1 << 1)
+} sofia_media_options_t;
+
 struct sofia_profile {
        int debug;
        char *name;
@@ -376,6 +383,7 @@ struct sofia_profile {
        uint32_t nat_acl_count;
        int rport_level;
        sofia_presence_type_t pres_type;
+       sofia_media_options_t media_options;
 };
 
 struct private_object {
@@ -487,6 +495,7 @@ struct private_object {
        char *remote_ip;
        int remote_port;
        int got_bye;
+       int hold_laps;
 };
 
 struct callback_t {
@@ -687,3 +696,4 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile);
 void sofia_glue_del_gateway(sofia_gateway_t *gp);
 void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent);
 void sofia_glue_restart_all_profiles(void);
+void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
index 950d4ce062e615a0111cfb8f6c758d5d1119b9a8..78aa79fb224b93bd6f5075919a8310f80a4fd904 100644 (file)
@@ -1591,6 +1591,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                                profile->mflags &= ~MFLAG_REFER;
                                        } else if (!strcasecmp(var, "disable-register") && switch_true(val)) {
                                                profile->mflags &= ~MFLAG_REGISTER;
+                                       } else if (!strcasecmp(var, "media-option")) {
+                                               if (!strcasecmp(val, "resume-media-on-hold")) {
+                                                       profile->media_options |= MEDIA_OPT_MEDIA_ON_HOLD;
+                                               } else if (!strcasecmp(val, "bypass-media-after-att-xfer")) {
+                                                       profile->media_options |= MEDIA_OPT_BYPASS_AFTER_ATT_XFER;
+                                               }
                                        } else if (!strcasecmp(var, "manage-presence")) {
                                                if (!strcasecmp(val, "passive")) {
                                                        profile->pres_type = PRES_TYPE_PASSIVE;
@@ -2144,6 +2150,50 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
        }
 }
 
+
+/* Pure black magic, if you can't understand this code you are lucky.........*/
+void *SWITCH_THREAD_FUNC media_on_hold_thread_run(switch_thread_t *thread, void *obj)
+{
+       switch_core_session_t *other_session = NULL, *session = (switch_core_session_t *) obj;
+       const char *uuid;
+       
+       if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
+               switch_channel_t *channel = switch_core_session_get_channel(session);
+               private_object_t *tech_pvt = switch_core_session_get_private(session);
+               
+               if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+                       if (switch_core_session_compare(session, other_session)) {
+                               switch_set_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
+                               switch_ivr_media(switch_core_session_get_uuid(other_session), SMF_REBRIDGE);
+                       
+                               if (tech_pvt->rtp_session) {
+                                       switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
+                               }
+
+                               sofia_glue_toggle_hold(tech_pvt, 1);
+                               switch_core_session_rwunlock(other_session);
+                       }
+               }
+
+               switch_core_session_rwunlock(session);
+       }
+       
+       return NULL;
+}
+
+static void launch_media_on_hold(switch_core_session_t *session)
+{
+       switch_thread_t *thread;
+       switch_threadattr_t *thd_attr = NULL;
+
+       switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+       switch_threadattr_priority_increase(thd_attr);
+       switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session));
+}
+
+
 static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                                         char const *phrase,
                                                                         nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
@@ -2348,6 +2398,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                                                switch_ivr_uuid_bridge(br_a, br_b);
                                                                                switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
                                                                                switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+                                                                               switch_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
                                                                                switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
                                                                        } else {
                                                                                switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR");
@@ -2377,6 +2428,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
                                                sofia_glue_tech_choose_port(tech_pvt, 0);
                                                sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
+                                               switch_set_flag_locked(tech_pvt, TFLAG_3PCC);
                                                switch_channel_set_state(channel, CS_HIBERNATE);
                                                nua_respond(tech_pvt->nh, SIP_200_OK,
                                                                        SIPTAG_CONTACT_STR(tech_pvt->profile->url),
@@ -2404,13 +2456,55 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                        sdp_parser_t *parser;
                        sdp_session_t *sdp;
                        uint8_t match = 0, is_ok = 1;
+                       tech_pvt->hold_laps = 0;
 
                        if (r_sdp) {
                                if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
+                                       
                                        if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
                                                && (other_session = switch_core_session_locate(uuid))) {
                                                switch_core_session_message_t msg = { 0 };
 
+                                               if (profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
+                                                       tech_pvt->hold_laps = 1;
+                                                       switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
+                                                       switch_channel_clear_flag(channel, CF_PROXY_MODE);
+                                                       tech_pvt->local_sdp_str = NULL;
+
+                                                       if (!switch_channel_media_ready(channel)) {
+                                                               if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
+                                                                       //const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
+
+                                                                       tech_pvt->num_codecs = 0;
+                                                                       sofia_glue_tech_prepare_codecs(tech_pvt);
+                                                                       if (sofia_glue_tech_media(tech_pvt, r_sdp) != SWITCH_STATUS_SUCCESS) {
+                                                                               switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
+                                                                               status = SWITCH_STATUS_FALSE;
+                                                                               goto done;
+                                                                       }
+                                                               }
+                                                       }
+
+                                                       if (!switch_rtp_ready(tech_pvt->rtp_session)) {
+                                                               sofia_glue_tech_prepare_codecs(tech_pvt);
+                                                               if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
+                                                                       switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                                                                       goto done;
+                                                               }
+                                                       }
+                                                       sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
+                                                       
+                                                       nua_respond(tech_pvt->nh, SIP_200_OK,
+                                                                               SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+                                                                               SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+                                                                               SOATAG_REUSE_REJECTED(1),
+                                                                               SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+                                                       launch_media_on_hold(session);
+
+                                                       switch_core_session_rwunlock(other_session);
+                                                       goto done;
+                                               }
+                                               
                                                msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
                                                msg.from = __FILE__;
                                                msg.string_arg = (char *) r_sdp;
@@ -2559,7 +2653,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP Error!\n");
                                                                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                                                        }
-                                                       if (switch_channel_get_state(channel) == CS_HIBERNATE) {
+                                                       if (switch_channel_get_state(channel) == CS_HIBERNATE && switch_test_flag(tech_pvt, TFLAG_3PCC)) {
                                                                switch_set_flag_locked(tech_pvt, TFLAG_READY);
                                                                switch_channel_set_state(channel, CS_INIT);
                                                                switch_set_flag(tech_pvt, TFLAG_SDP);
@@ -2800,25 +2894,33 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
                                                                                  switch_str_nil(br_b));
 
                                                if (br_a && br_b) {
-                                                       switch_core_session_t *new_b_session = NULL, *a_session = NULL;
-
+                                                       switch_core_session_t *new_b_session = NULL, *a_session = NULL, *tmp = NULL;
+                                                       
+                                                       if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) && (tmp = switch_core_session_locate(br_b))) {
+                                                               switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
+                                                               switch_channel_set_variable(tchannel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE, "true");
+                                                               switch_core_session_rwunlock(tmp);
+                                                       }
+                                                       
                                                        switch_ivr_uuid_bridge(br_b, br_a);
                                                        switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
                                                        nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
                                                                           NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END());
 
                                                        switch_clear_flag_locked(b_tech_pvt, TFLAG_SIP_HOLD);
+                                                       switch_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
                                                        switch_ivr_park_session(b_session);
                                                        new_b_session = switch_core_session_locate(br_b);
                                                        a_session = switch_core_session_locate(br_a);
                                                        sofia_info_send_sipfrag(a_session, new_b_session);
+
                                                        if (new_b_session) {
                                                                switch_core_session_rwunlock(new_b_session);
                                                        }
+
                                                        if (a_session) {
                                                                switch_core_session_rwunlock(a_session);
                                                        }
-                                                       //switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER);
                                                } else {
                                                        if (!br_a && !br_b) {
                                                                switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
index 956948d1ca4b8a2ac89c1d6c28c32edc1c88c483..8a6f4bbbfee1e7c3fc35f80084b6878aec20d891 100644 (file)
@@ -858,7 +858,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
                                } else {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
                                                                          tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port);
-                                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+                                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
                                                !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
                                                /* Reactivate the NAT buster flag. */
                                                switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
@@ -1749,12 +1749,18 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
        }
 
        if (tech_pvt->rtp_session && switch_test_flag(tech_pvt, TFLAG_REINVITE)) {
-               const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
-               const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
-
-               if (ip && port && !strcmp(ip, tech_pvt->adv_sdp_audio_ip) && atoi(port) == tech_pvt->remote_sdp_audio_port) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio params are unchanged.\n");
+               //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
+               //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
+               char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
+               switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
+               
+               if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n", switch_channel_get_name(tech_pvt->channel));
                        goto video;
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n", 
+                                                         switch_channel_get_name(tech_pvt->channel),
+                                                         remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
                }
        }
 
@@ -1773,7 +1779,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
 
        if (tech_pvt->rtp_session && switch_test_flag(tech_pvt, TFLAG_REINVITE)) {
                switch_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
-
+               
                if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port, &err) !=
                        SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
@@ -1944,7 +1950,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                                sofia_glue_tech_choose_video_port(tech_pvt, 1);
                        }
 
-                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
                                !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
                                flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_AUTOADJ |
                                                                                         SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_NOBLOCK | SWITCH_RTP_FLAG_RAW_WRITE);
@@ -2042,58 +2048,9 @@ switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_
        return SWITCH_STATUS_FALSE;
 }
 
-uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *sdp)
+void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
 {
-       uint8_t match = 0;
-       switch_payload_t te = 0, cng_pt = 0;
-       private_object_t *tech_pvt = switch_core_session_get_private(session);
-       sdp_media_t *m;
-       sdp_attribute_t *attr;
-       int first = 0, last = 0;
-       int ptime = 0, dptime = 0;
-       int sendonly = 0;
-       int greedy = 0, x = 0, skip = 0, mine = 0;
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       const char *val;
-       const char *crypto = NULL;
-       int got_crypto = 0, got_audio = 0, got_avp = 0, got_savp = 0;
-
-       switch_assert(tech_pvt != NULL);
-
-       greedy = !!(tech_pvt->profile->pflags & PFLAG_GREEDY);
-
-       if (!greedy) {
-               if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation")) && !strcasecmp(val, "greedy")) {
-                       greedy = 1;
-               }
-       }
-
-       if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
-               if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
-                       switch_set_flag_locked(tech_pvt, TFLAG_BUGGY_2833);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
-               }
-       }
-
-       if ((m = sdp->sdp_media) && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
-               sendonly = 2;                   /* global sendonly always wins */
-       }
-
-       for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
-               if (switch_strlen_zero(attr->a_name)) {
-                       continue;
-               }
-
-               if (!strcasecmp(attr->a_name, "sendonly") || !strcasecmp(attr->a_name, "inactive")) {
-                       sendonly = 1;
-               } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
-                       sendonly = 0;
-               } else if (!strcasecmp(attr->a_name, "ptime")) {
-                       dptime = atoi(attr->a_value);
-               }
-       }
-
-       if (sendonly && switch_channel_test_flag(channel, CF_ANSWERED)) {
+       if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
                if (!switch_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
                        const char *stream;
 
@@ -2120,6 +2077,12 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
                        }
                }
        } else {
+               if (switch_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+                       switch_set_flag(tech_pvt, TFLAG_SIP_HOLD);
+               }
+
+               switch_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
+               
                if (switch_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
                        const char *uuid;
                        switch_core_session_t *b_session;
@@ -2148,6 +2111,63 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
                        switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
                }
        }
+}
+
+uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *sdp)
+{
+       uint8_t match = 0;
+       switch_payload_t te = 0, cng_pt = 0;
+       private_object_t *tech_pvt = switch_core_session_get_private(session);
+       sdp_media_t *m;
+       sdp_attribute_t *attr;
+       int first = 0, last = 0;
+       int ptime = 0, dptime = 0;
+       int sendonly = 0;
+       int greedy = 0, x = 0, skip = 0, mine = 0;
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       const char *val;
+       const char *crypto = NULL;
+       int got_crypto = 0, got_audio = 0, got_avp = 0, got_savp = 0;
+
+       switch_assert(tech_pvt != NULL);
+
+       greedy = !!(tech_pvt->profile->pflags & PFLAG_GREEDY);
+
+       if (!greedy) {
+               if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation")) && !strcasecmp(val, "greedy")) {
+                       greedy = 1;
+               }
+       }
+
+       if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
+               if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
+                       switch_set_flag_locked(tech_pvt, TFLAG_BUGGY_2833);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
+               }
+       }
+
+       if ((m = sdp->sdp_media) && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
+               sendonly = 2;                   /* global sendonly always wins */
+       }
+
+       for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
+               if (switch_strlen_zero(attr->a_name)) {
+                       continue;
+               }
+
+               if (!strcasecmp(attr->a_name, "sendonly") || !strcasecmp(attr->a_name, "inactive")) {
+                       sendonly = 1;
+               } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
+                       sendonly = 0;
+               } else if (!strcasecmp(attr->a_name, "ptime")) {
+                       dptime = atoi(attr->a_value);
+               }
+       }
+
+       if (!tech_pvt->hold_laps) {
+               tech_pvt->hold_laps++;
+               sofia_glue_toggle_hold(tech_pvt, sendonly);
+       }
 
        for (m = sdp->sdp_media; m; m = m->m_next) {
                sdp_connection_t *connection;
index 8730bc3c49928740625b6fd902ece1b91e209d02..4b4a2a7990395b0710570a6733d8cc8492d69c34 100644 (file)
@@ -103,8 +103,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
        switch_codec_t silence_codec = { 0 };
        switch_frame_t silence_frame = { 0 };
        int16_t silence_data[SWITCH_RECOMMENDED_BUFFER_SIZE/2] = { 0 };
-       const char *silence_var;
-       int silence_val = 0;
+       const char *silence_var, *var;
+       int silence_val = 0, bypass_media_after_bridge = 0;
 #ifdef SWITCH_VIDEO_IN_THREADS
        struct vid_helper vh = { 0 };
        uint32_t vid_launch = 0;
@@ -114,7 +114,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
        if (!(session_b = switch_core_session_locate(data->b_uuid))) {
                return NULL;
        }
-
+       
        input_callback = data->input_callback;
        user_data = data->session_data;
        stream_id = data->stream_id;
@@ -141,6 +141,11 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
                goto end_of_bridge_loop;
        }
 
+       if ((var = switch_channel_get_variable(chan_a, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) && switch_true(var)) {
+               bypass_media_after_bridge = 1;
+               switch_channel_set_variable(chan_a, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE, NULL);
+       }
+
        if ((silence_var = switch_channel_get_variable(chan_a, "bridge_generate_comfort_noise"))) {
                switch_codec_t *read_codec = NULL;
                
@@ -234,6 +239,11 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
                }
 #endif
 
+               if (loop_count > 50 && bypass_media_after_bridge) {
+                       switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE);
+                       bypass_media_after_bridge = 0;
+               }
+               
                /* if 1 channel has DTMF pass it to the other */
                while (switch_channel_has_dtmf(chan_a)) {
                        switch_dtmf_t dtmf = { 0, 0 };
index 05ccf70a900447efa69aa858047f841b6fd2ab18..024525fd8f34982cfe9b333d7d73dc4c9f742f17 100644 (file)
@@ -166,6 +166,7 @@ struct switch_rtp {
        char *ice_user;
        char *user_ice;
        char *timer_name;
+       char *remote_host_str;
        switch_time_t last_stun;
        uint32_t samples_per_interval;
        uint32_t conf_samples_per_interval;
@@ -597,6 +598,17 @@ SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session
        rtp_session->max_missed_packets = max;
 }
 
+SWITCH_DECLARE(char *) switch_rtp_get_remote_host(switch_rtp_t *rtp_session)
+{
+       return switch_strlen_zero(rtp_session->remote_host_str) ? "0.0.0.0" : rtp_session->remote_host_str;
+}
+
+SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_session)
+{
+       return rtp_session->remote_port;
+}
+
+
 SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err)
 {
        switch_sockaddr_t *remote_addr;
@@ -611,6 +623,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
        switch_mutex_lock(rtp_session->write_mutex);
 
        rtp_session->remote_addr = remote_addr;
+       rtp_session->remote_host_str = switch_core_strdup(rtp_session->pool, host);
        rtp_session->remote_port = port;
 
        if (rtp_session->sock_input &&