]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-4932 FS-5090 --resolve
authorAnthony Minessale <anthm@freeswitch.org>
Mon, 29 Jul 2013 15:18:05 +0000 (10:18 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 29 Jul 2013 15:18:05 +0000 (10:18 -0500)
src/include/switch_core_media.h
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
src/switch_rtp.c

index 844a1bbb76878fab6ee3611b9c14e91ac8def223..122f9f2b65e381906e1654d379c35eb953bce644 100644 (file)
@@ -68,6 +68,7 @@ typedef enum {
        SCMF_RUNNING,
        SCMF_DISABLE_TRANSCODING,
        SCMF_AUTOFIX_TIMING,
+       SCMF_AUTOFIX_PT,
        SCMF_CODEC_GREEDY,
        SCMF_CODEC_SCROOGE,
        SCMF_DISABLE_HOLD,
@@ -242,7 +243,7 @@ SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_get_stats(switch_core_ses
 
 
 SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp);
-SWITCH_DECLARE(void) switch_core_media_reset_autofix_timing(switch_core_session_t *session, switch_media_type_t type);
+SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type);
 SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session);
 SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t media);
 SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *session);
index a847006e094a055a39fc42f21d22effae27d54bf..7f3aade715f4de7c8df516b6ce8745b3faa6d93c 100644 (file)
@@ -762,10 +762,17 @@ typedef enum {
          If this setting is enabled it will NOT do this (old behaviour).
         */
 
-       RTP_BUG_FLUSH_JB_ON_DTMF = (1 << 10)
+       RTP_BUG_FLUSH_JB_ON_DTMF = (1 << 10),
        
        /* FLUSH JITTERBUFFER When getting RFC2833 to reduce bleed through */
 
+       RTP_BUG_ACCEPT_ANY_PAYLOAD = (1 << 11)
+
+       /* 
+         Make FS accept any payload type instead of dropping and returning CNG frame. Workaround while FS only supports a single payload per rtp session.
+         This can be used by endpoint modules to detect payload changes and act appropriately (ex: sofia could send a reINVITE with single codec).
+         This should probably be a flag, but flag enum is already full!
+       */
 
 } switch_rtp_bug_flag_t;
 
index 561a887aeaf4b29811f176c52efd15374377a766..50261d7f4ed8a248441ce00fec58033e433e646f 100644 (file)
@@ -1273,8 +1273,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
                        }
 
-                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
-                               switch_core_media_reset_autofix_timing(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
+                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+                               switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
                        }
                }
                break;
index a95010539a578d657bcd337ac6d1d97ba50d27a6..b87b5a35efaeebf5359046c3417997fbbcdf272f 100644 (file)
@@ -3714,6 +3714,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                        sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
                                        profile->auto_restart = 1;
                                        sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
+                                       sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
                                        sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
                                        profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
                                        sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
@@ -4325,6 +4326,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                } else {
                                                        sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING);
                                                }
+                                       } else if (!strcasecmp(var, "rtp-autofix-pt")) {
+                                               if (switch_true(val)) {
+                                                       sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
+                                               } else {
+                                                       sofia_clear_media_flag(profile, SCMF_AUTOFIX_PT);
+                                               }
                                        } else if (!strcasecmp(var, "contact-user")) {
                                                profile->contact_user = switch_core_strdup(profile->pool, val);
                                        } else if (!strcasecmp(var, "nat-options-ping")) {
@@ -5188,8 +5195,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
                        
                        sofia_update_callee_id(session, profile, sip, SWITCH_FALSE);
 
-                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
-                               switch_core_media_reset_autofix_timing(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
+                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+                               switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
                        }
 
                }
index 96ab5f7892d5e537f136e41ff67458ab3d9977ef..6dde6cf3e6b1d744aa31a6990b568ed781d1f43c 100644 (file)
@@ -591,6 +591,14 @@ SWITCH_DECLARE(void) switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *fla
                *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
        }
 
+       if (switch_stristr("ACCEPT_ANY_PAYLOAD", str)) {
+               *flag_pole |= RTP_BUG_ACCEPT_ANY_PAYLOAD;
+       }
+
+       if (switch_stristr("~ACCEPT_ANY_PAYLOAD", str)) {
+               *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PAYLOAD;
+       }
+
        if (switch_stristr("GEN_ONE_GEN_ALL", str)) {
                *flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL;
        }
@@ -1333,8 +1341,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                        return SWITCH_STATUS_GENERR;
                                }
 
-                               if ((engine->read_frame.datalen % 10) == 0 &&
-                                       (smh->media_flags[SCMF_AUTOFIX_TIMING]) && engine->check_frames < MAX_CODEC_CHECK_FRAMES) {
+                               /* check for timing or codec issues */
+                               if ((smh->media_flags[SCMF_AUTOFIX_TIMING] || smh->media_flags[SCMF_AUTOFIX_PT]) &&
+                                       engine->check_frames < MAX_CODEC_CHECK_FRAMES) {
+
+                                       int reset_codec = 0;
+
                                        engine->check_frames++;
 
                                        if (!engine->read_impl.encoded_bytes_per_packet) {
@@ -1342,111 +1354,172 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                                goto skip;
                                        }
 
-                                       if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
-                                               uint32_t codec_ms = (int) (engine->read_frame.timestamp -
-                                                                                                  engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
-
-                                               if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) {
-                                                       engine->last_ts = 0;
-                                                       goto skip;
+                                       /* autofix payload type */
+                                       if (smh->media_flags[SCMF_AUTOFIX_PT] &&
+                                               engine->read_frame.payload != smh->mparams->cng_pt &&
+                                               engine->read_frame.payload != smh->mparams->recv_te &&
+                                               engine->read_frame.payload != smh->mparams->te &&
+                                               engine->read_frame.payload != engine->codec_params.recv_pt &&
+                                               engine->read_frame.payload != engine->codec_params.agreed_pt &&
+                                               engine->read_frame.payload != engine->codec_params.pt) {
+
+                                               int i = 0;
+
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                 "Invalid payload received (received %d, expecting %d). "
+                                                                                 "FS doesn't support multiple payload types in a single RTP session.\n",
+                                                                                 (int) engine->read_frame.payload, (int) engine->codec_params.agreed_pt);
+
+                                               /* search for payload type */
+                                               for (i = 0; i < smh->mparams->num_codecs; i++) {
+                                                       if (engine->read_frame.payload == smh->ianacodes[i]) {
+                                                               const switch_codec_implementation_t *imp = smh->codecs[i];
+
+                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                                 "Changing current codec to %s (payload type %d).\n",
+                                                                                                 imp->iananame, (int) engine->read_frame.payload);
+
+                                                               engine->codec_params.iananame = switch_core_session_strdup(smh->session, imp->iananame);
+                                                               engine->codec_params.pt = imp->ianacode;
+                                                               engine->codec_params.agreed_pt = imp->ianacode;
+                                                               engine->codec_params.recv_pt = imp->ianacode;
+                                                               engine->codec_params.rm_encoding = switch_core_session_strdup(smh->session, imp->iananame);
+                                                               engine->codec_params.rm_fmtp = NULL;
+                                                               engine->codec_params.rm_rate = imp->samples_per_second;
+                                                               engine->codec_params.codec_ms = imp->microseconds_per_packet / 1000;
+                                                               engine->codec_params.bitrate = imp->bits_per_second;
+                                                               engine->codec_params.channels = 1;
+
+                                                               /* mark to re-set codec */
+                                                               reset_codec = 1;
+                                                               break;
+                                                       }
                                                }
 
-
-                                               if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
-                                                       engine->mismatch_count++;
+                                               if (!reset_codec) {
+                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                         "Could not change to payload type %d, ignoring...\n",
+                                                                                         (int) engine->read_frame.payload);
                                                }
 
-                                               engine->last_codec_ms = codec_ms;
-
-                                               if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
-                                                       if (switch_rtp_ready(engine->rtp_session) && codec_ms != engine->codec_params.codec_ms) {
-                                                               const char *val;
-                                                               int rtp_timeout_sec = 0;
-                                                               int rtp_hold_timeout_sec = 0;
-
-                                                               if (codec_ms > 120) {   /* yeah right */
-                                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
-                                                                                                         "Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
-                                                                                                         "That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
-                                                                                                         (int) codec_ms);
-                                                                       engine->check_frames = MAX_CODEC_CHECK_FRAMES;
-                                                                       goto skip;
-                                                               }
+                                       /* autofix timing */
+                                       } else if (smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0) {
 
-                                                               engine->read_frame.datalen = 0;
+                                               if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
 
-                                                               if (codec_ms != engine->codec_params.codec_ms) {
-                                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
-                                                                                                         "Asynchronous PTIME not supported, changing our end from %d to %d\n",
-                                                                                                         (int) engine->codec_params.codec_ms,
-                                                                                                         (int) codec_ms
-                                                                                                         );
+                                                       uint32_t codec_ms = (int) (engine->read_frame.timestamp -
+                                                                                                          engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
 
-                                                                       switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
-                                                                                                                                          (int) engine->codec_params.codec_ms, (int) codec_ms);
+                                                       if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) {
+                                                               engine->last_ts = 0;
+                                                               goto skip;
+                                                       }
 
-                                                                       engine->codec_params.codec_ms = codec_ms;
-                                                               }
 
+                                                       if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
+                                                               engine->mismatch_count++;
+                                                       }
 
-                                                               if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) {
-                                                                       *frame = NULL;
-                                                                       return SWITCH_STATUS_GENERR;
-                                                               }
+                                                       engine->last_codec_ms = codec_ms;
 
-                                                               if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
-                                                                       int v = atoi(val);
-                                                                       if (v >= 0) {
-                                                                               rtp_timeout_sec = v;
-                                                                       }
-                                                               }
+                                                       if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
+                                                               if (codec_ms != engine->codec_params.codec_ms) {
 
-                                                               if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
-                                                                       int v = atoi(val);
-                                                                       if (v >= 0) {
-                                                                               rtp_hold_timeout_sec = v;
+                                                                       if (codec_ms > 120) {   /* yeah right */
+                                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                                                 "Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
+                                                                                                                 "That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
+                                                                                                                 (int) codec_ms);
+                                                                               engine->check_frames = MAX_CODEC_CHECK_FRAMES;
+                                                                               goto skip;
                                                                        }
-                                                               }
-
-                                                               if (rtp_timeout_sec) {
-                                                                       engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
-                                                                               engine->read_impl.samples_per_packet;
 
-                                                                       switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
-                                                                       if (!rtp_hold_timeout_sec) {
-                                                                               rtp_hold_timeout_sec = rtp_timeout_sec * 10;
-                                                                       }
-                                                               }
+                                                                       engine->read_frame.datalen = 0;
 
-                                                               if (rtp_hold_timeout_sec) {
-                                                                       engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
-                                                                               engine->read_impl.samples_per_packet;
-                                                               }
+                                                                       if (codec_ms != engine->codec_params.codec_ms) {
+                                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                                                 "Asynchronous PTIME not supported, changing our end from %d to %d\n",
+                                                                                                                 (int) engine->codec_params.codec_ms,
+                                                                                                                 (int) codec_ms
+                                                                                                                 );
 
+                                                                               switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
+                                                                                                                                                  (int) engine->codec_params.codec_ms, (int) codec_ms);
 
-                                                               engine->check_frames = 0;
-                                                               engine->last_ts = 0;
+                                                                               engine->codec_params.codec_ms = codec_ms;
 
-                                                               *frame = &engine->read_frame;
-                                                               switch_set_flag((*frame), SFF_CNG);
-                                                               (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
-                                                               memset((*frame)->data, 0, (*frame)->datalen);
-                                                               return SWITCH_STATUS_SUCCESS;
+                                                                               /* mark to re-set codec */
+                                                                               reset_codec = 2;
+                                                                       }
+                                                               }
                                                        }
 
+                                               } else {
+                                                       engine->mismatch_count = 0;
                                                }
 
+                                               engine->last_ts = engine->read_frame.timestamp;
+
+
                                        } else {
                                                engine->mismatch_count = 0;
+                                               engine->last_ts = 0;
                                        }
 
-                                       engine->last_ts = engine->read_frame.timestamp;
+                                       /* re-set codec if necessary */
+                                       if (reset_codec > 0) {
+                                               const char *val;
+                                               int rtp_timeout_sec = 0;
+                                               int rtp_hold_timeout_sec = 0;
 
+                                               if (switch_rtp_ready(engine->rtp_session)) {
+                                                       if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) {
+                                                               *frame = NULL;
+                                                               return SWITCH_STATUS_GENERR;
+                                                       }
 
-                               } else {
-                                       engine->mismatch_count = 0;
-                                       engine->last_ts = 0;
+                                                       if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
+                                                               int v = atoi(val);
+                                                               if (v >= 0) {
+                                                                       rtp_timeout_sec = v;
+                                                               }
+                                                       }
+
+                                                       if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
+                                                               int v = atoi(val);
+                                                               if (v >= 0) {
+                                                                       rtp_hold_timeout_sec = v;
+                                                               }
+                                                       }
+
+                                                       if (rtp_timeout_sec) {
+                                                               engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
+                                                                       engine->read_impl.samples_per_packet;
+
+                                                               switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
+                                                               if (!rtp_hold_timeout_sec) {
+                                                                       rtp_hold_timeout_sec = rtp_timeout_sec * 10;
+                                                               }
+                                                       }
+
+                                                       if (rtp_hold_timeout_sec) {
+                                                               engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
+                                                                       engine->read_impl.samples_per_packet;
+                                                       }
+                                               }
+
+                                               engine->check_frames = 0;
+                                               engine->last_ts = 0;
+
+                                               /* return CNG for now */
+                                               *frame = &engine->read_frame;
+                                               switch_set_flag((*frame), SFF_CNG);
+                                               (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
+                                               memset((*frame)->data, 0, (*frame)->datalen);
+                                               return SWITCH_STATUS_SUCCESS;
+                                       }
                                }
+
                        skip:
 
                                if ((bytes = engine->read_impl.encoded_bytes_per_packet)) {
@@ -3372,7 +3445,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                                                /* Reactivate the NAT buster flag. */
                                                switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
                                        }
-                                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) {
+                                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
                                                v_engine->check_frames = 0;
                                        }
                                }
@@ -3410,7 +3483,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                                /* Reactivate the NAT buster flag. */
                                switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
                        }
-                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) {
+                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
                                a_engine->check_frames = 0;
                        }
                        status = SWITCH_STATUS_SUCCESS;
@@ -3514,7 +3587,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_ext_address_lookup(switch_core
 }
 
 //?
-SWITCH_DECLARE(void) switch_core_media_reset_autofix_timing(switch_core_session_t *session, switch_media_type_t type)
+SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type)
 {
        switch_rtp_engine_t *engine;
        switch_media_handle_t *smh;
index 785d51fbb009a9eb25886a8429af8a0701017bb8..d961d7df5862955747f0d7d85152c8f22884f030 100644 (file)
@@ -4819,7 +4819,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        rtp_session->recv_msg.header.pt != 13 && 
                        rtp_session->recv_msg.header.pt != rtp_session->recv_te && 
                        (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) && 
-                       rtp_session->recv_msg.header.pt != rtp_session->rpayload && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) {
+                       rtp_session->recv_msg.header.pt != rtp_session->rpayload && 
+                       !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PAYLOAD) && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) {
                        /* drop frames of incorrect payload number and return CNG frame instead */
                        return_cng_frame();                     
                }