*/
- RTP_BUG_IGNORE_MARK_BIT = (1 << 2)
+ RTP_BUG_IGNORE_MARK_BIT = (1 << 2),
/*
A Huawei SBC has been discovered that sends the mark bit on every single RTP packet.
*/
+
+ RTP_BUG_SEND_LINEAR_TIMESTAMPS = (1 << 3),
+
+ /*
+ Our friends at Sonus get real mad when the timestamps are not in perfect sequence even during periods of silence.
+ With this flag, we will only increment the timestamp when write packets even if they are eons apart.
+
+ */
+
+ RTP_BUG_START_SEQ_AT_ZERO = (1 << 4),
+
+ /*
+ Our friends at Sonus also get real mad if the sequence number does not start at 0.
+ Typically, we set this to a random starting value for your saftey.
+ This is a security risk you take upon yourself when you enable this flag.
+ */
+
+
+ RTP_BUG_NEVER_SEND_MARKER = (1 << 5),
+
+ /*
+ Our friends at Sonus are on a roll, They also get easily dumbfounded by marker bits.
+ This flag will never send any. Sheesh....
+ */
+
+
+
+
} switch_rtp_bug_flag_t;
char *user_agent_filter;
uint32_t max_registrations_perext;
switch_rtp_bug_flag_t auto_rtp_bugs;
+ switch_rtp_bug_flag_t manual_rtp_bugs;
uint32_t ib_calls;
uint32_t ob_calls;
uint32_t ib_failed_calls;
switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt);
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl);
void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
+void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str);
}
}
-static void parse_rtp_bugs(sofia_profile_t *profile, const char *str)
-{
-
- if (switch_stristr("clear", str)) {
- profile->auto_rtp_bugs = 0;
- }
-
- if (switch_stristr("CISCO_SKIP_MARK_BIT_2833", str)) {
- profile->auto_rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
- }
-
- if (switch_stristr("~CISCO_SKIP_MARK_BIT_2833", str)) {
- profile->auto_rtp_bugs &= ~RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
- }
-
- if (switch_stristr("SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
- profile->auto_rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
- }
-
- if (switch_stristr("~SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
- profile->auto_rtp_bugs &= ~RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
- }
-
- if (switch_stristr("IGNORE_MARK_BIT", str)) {
- profile->auto_rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
- }
-
- if (switch_stristr("~IGNORE_MARK_BIT", str)) {
- profile->auto_rtp_bugs &= ~RTP_BUG_IGNORE_MARK_BIT;
- }
-
-}
-
switch_status_t reconfig_sofia(sofia_profile_t *profile)
{
switch_xml_t cfg, xml = NULL, xprofile, profiles, gateways_tag, domain_tag, domains_tag, aliases_tag, alias_tag, settings, param;
sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
}
} else if (!strcasecmp(var, "auto-rtp-bugs")) {
- parse_rtp_bugs(profile, val);
+ sofia_glue_parse_rtp_bugs(&profile->auto_rtp_bugs, val);
+ } else if (!strcasecmp(var, "manual-rtp-bugs")) {
+ sofia_glue_parse_rtp_bugs(&profile->manual_rtp_bugs, val);
} else if (!strcasecmp(var, "user-agent-string")) {
profile->user_agent = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "auto-restart")) {
profile->rport_level = 2;
}
} else if (!strcasecmp(var, "auto-rtp-bugs")) {
- parse_rtp_bugs(profile, val);
+ sofia_glue_parse_rtp_bugs(&profile->auto_rtp_bugs, val);
+ } else if (!strcasecmp(var, "manual-rtp-bugs")) {
+ sofia_glue_parse_rtp_bugs(&profile->manual_rtp_bugs, val);
} else if (!strcasecmp(var, "dbname")) {
profile->dbname = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "presence-hosts")) {
tech_pvt->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
}
- switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs);
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_rtp_bugs"))) {
+ sofia_glue_parse_rtp_bugs(&tech_pvt->rtp_bugs, val);
+ }
+
+ switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs);
if ((vad_in && inb) || (vad_out && !inb)) {
switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING);
}
+void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str)
+{
+
+ if (switch_stristr("clear", str)) {
+ *flag_pole = 0;
+ }
+
+ if (switch_stristr("CISCO_SKIP_MARK_BIT_2833", str)) {
+ *flag_pole |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
+ }
+
+ if (switch_stristr("~CISCO_SKIP_MARK_BIT_2833", str)) {
+ *flag_pole &= ~RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
+ }
+
+ if (switch_stristr("SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
+ *flag_pole |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
+ }
+
+ if (switch_stristr("~SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
+ *flag_pole &= ~RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
+ }
+
+ if (switch_stristr("IGNORE_MARK_BIT", str)) {
+ *flag_pole |= RTP_BUG_IGNORE_MARK_BIT;
+ }
+
+ if (switch_stristr("~IGNORE_MARK_BIT", str)) {
+ *flag_pole &= ~RTP_BUG_IGNORE_MARK_BIT;
+ }
+
+ if (switch_stristr("SEND_LINEAR_TIMESTAMPS", str)) {
+ *flag_pole |= RTP_BUG_SEND_LINEAR_TIMESTAMPS;
+ }
+
+ if (switch_stristr("~SEND_LINEAR_TIMESTAMPS", str)) {
+ *flag_pole &= ~RTP_BUG_SEND_LINEAR_TIMESTAMPS;
+ }
+
+ if (switch_stristr("START_SEQ_AT_ZERO", str)) {
+ *flag_pole |= RTP_BUG_START_SEQ_AT_ZERO;
+ }
+
+ if (switch_stristr("~START_SEQ_AT_ZERO", str)) {
+ *flag_pole &= ~RTP_BUG_START_SEQ_AT_ZERO;
+ }
+
+ if (switch_stristr("NEVER_SEND_MARKER", str)) {
+ *flag_pole |= RTP_BUG_NEVER_SEND_MARKER;
+ }
+
+ if (switch_stristr("~NEVER_SEND_MARKER", str)) {
+ *flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER;
+ }
+}
+
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
switch_sockaddr_info_get(&rtp_session->rtcp_from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
}
- rtp_session->seq = (uint16_t) rand();
+ rtp_session->seq = (rtp_session->rtp_bugs & RTP_BUG_START_SEQ_AT_ZERO) ? 0 : (uint16_t) rand();
rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL));
rtp_session->send_msg.header.ssrc = htonl(rtp_session->ssrc);
send_msg = &rtp_session->send_msg;
send_msg->header.pt = payload;
- if (timestamp) {
+ if (rtp_session->rtp_bugs & RTP_BUG_SEND_LINEAR_TIMESTAMPS) {
+ rtp_session->ts += rtp_session->samples_per_interval;
+ if (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->ts > 0) {
+ rtp_session->ts = rtp_session->last_write_ts + rtp_session->samples_per_interval;
+ }
+ } else if (timestamp) {
rtp_session->ts = (uint32_t) timestamp;
/* Send marker bit if timestamp is lower/same as before (resetted/new timer) */
- if (rtp_session->ts <= rtp_session->last_write_ts) {
+ if (rtp_session->ts <= rtp_session->last_write_ts && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
m++;
}
} else if (rtp_session->timer.timer_interface) {
rtp_session->cn = 0;
m++;
}
-
- send_msg->header.m = m ? 1 : 0;
+
+ send_msg->header.m = (m && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) ? 1 : 0;
memcpy(send_msg->body, data, datalen);
bytes = datalen + rtp_header_len;
if (diff >= rtp_session->vad_data.diff_level || ++rtp_session->vad_data.hangunder_hits >= rtp_session->vad_data.hangunder) {
switch_set_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING);
- send_msg->header.m = 1;
+ if (!(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
+ send_msg->header.m = 1;
+ }
rtp_session->vad_data.hangover_hits = rtp_session->vad_data.hangunder_hits = rtp_session->vad_data.cng_count = 0;
if (switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_EVENTS_TALK)) {
switch_event_t *event;
rtp_session->write_msg.header.seq = htons(++rtp_session->seq);
rtp_session->write_msg.header.ts = htonl(ts);
rtp_session->write_msg.header.pt = payload;
- rtp_session->write_msg.header.m = m ? 1 : 0;
+ rtp_session->write_msg.header.m = (m && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) ? 1 : 0;
memcpy(rtp_session->write_msg.body, data, datalen);
bytes = rtp_header_len + datalen;