From b278dd2379e455ef1f256b703fdec1c292bf4179 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 10 Nov 2010 16:55:56 -0600 Subject: [PATCH] add manual_rtp_bugs to profile and chan var and 3 new RTP bugs SEND_LINEAR_TIMESTAMPS|START_SEQ_AT_ZERO|NEVER_SEND_MARKER 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.... --- src/include/switch_types.h | 30 +++++++++++- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 + src/mod/endpoints/mod_sofia/sofia.c | 41 +++------------- src/mod/endpoints/mod_sofia/sofia_glue.c | 62 +++++++++++++++++++++++- src/switch_rtp.c | 21 +++++--- 5 files changed, 112 insertions(+), 44 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 272d435068..c01638089f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -596,7 +596,7 @@ typedef enum { */ - 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. @@ -606,6 +606,34 @@ typedef enum { */ + + 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; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 6978e34ffc..750fb60c15 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -558,6 +558,7 @@ struct sofia_profile { 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; @@ -1035,3 +1036,4 @@ void sofia_glue_proxy_codec(switch_core_session_t *session, const char *r_sdp); 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); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 7cb4c5b528..e5672061bd 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2220,39 +2220,6 @@ static void parse_domain_tag(sofia_profile_t *profile, switch_xml_t x_domain_tag } } -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; @@ -2382,7 +2349,9 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) 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")) { @@ -3103,7 +3072,9 @@ switch_status_t config_sofia(int reload, char *profile_name) 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")) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index fbd270d41b..6e9aacb126 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3106,7 +3106,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f 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); @@ -5990,6 +5994,62 @@ void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const } +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; + } +} + diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 1792de08b3..f0eead3c42 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1366,7 +1366,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session 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); @@ -3179,10 +3179,15 @@ static int rtp_common_write(switch_rtp_t *rtp_session, 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) { @@ -3216,8 +3221,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session, 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; @@ -3287,7 +3292,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session, 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; @@ -3755,7 +3762,7 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session, 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;