add rtp_bug flags so we can keep track of all the bugs we have to emulate

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10991 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2008-12-29 21:23:17 +00:00
parent 97656065cd
commit 604f1b1ee2
5 changed files with 49 additions and 10 deletions

View File

@ -431,6 +431,8 @@ SWITCH_DECLARE(void *) switch_rtp_get_private(switch_rtp_t *rtp_session);
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_session, const char *stun_ip, switch_port_t stun_port,
uint32_t packet_count, switch_bool_t funny);
SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs);
/*!
\}
*/

View File

@ -460,6 +460,38 @@ typedef enum {
} switch_rtp_flag_enum_t;
typedef uint32_t switch_rtp_flag_t;
typedef enum {
RTP_BUG_NONE = 0, /* won't be using this one much ;) */
RTP_BUG_CISCO_SKIP_MARK_BIT_2833 = (1 << 0),
/* Some Cisco devices get mad when you send the mark bit on new 2833 because it makes
them flush their jitterbuffer and the dtmf along with it.
This flag will disable the sending of the mark bit on the first DTMF packet.
*/
RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833 = (1 << 1)
/*
Sonus wrongly expects that, when sending a multi-packet 2833 DTMF event, The sender
should increment the RTP timestamp in each packet when, in reality, the sender should
send the same exact timestamp and increment the duration field in the 2833 payload.
This allows a reconstruction of the duration if any of the packets are lost.
final_duration - initial_timestamp = total_samples
However, if the duration value exceeds the space allocated (16 bits), The sender should increment
the timestamp one unit and reset the duration to 0.
Always sending a duration of 0 with a new timestamp should be tolerated but is rarely intentional
and is mistakenly done by many devices.
The issue is that the Sonus expects everyone to do it this way instead of tolerating eiher way.
Sonus will actually ignore every packet with the same timestamp before concluding if it's DTMF.
This flag will cause each packet to have a new timestamp.
*/
} switch_rtp_bug_flag_t;
#ifdef _MSC_VER
#pragma pack(push, r1, 1)

View File

@ -208,7 +208,7 @@ typedef enum {
TFLAG_NOHUP = (1 << 18),
TFLAG_NOSDP_REINVITE = (1 << 19),
TFLAG_NAT = (1 << 20),
TFLAG_BUGGY_2833 = (1 << 21),
TFLAG_USEME = (1 << 21),
TFLAG_SIP_HOLD = (1 << 22),
TFLAG_INB_NOMEDIA = (1 << 23),
TFLAG_LATE_NEGOTIATION = (1 << 24),
@ -552,6 +552,7 @@ struct private_object {
uint32_t mismatch_count;
uint32_t last_codec_ms;
nua_event_t want_event;
switch_rtp_bug_flag_t rtp_bugs;
};
struct callback_t {

View File

@ -1775,10 +1775,6 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT);
}
if (switch_test_flag(tech_pvt, TFLAG_BUGGY_2833)) {
flags |= SWITCH_RTP_FLAG_BUGGY_2833;
}
if ((val = switch_channel_get_variable(tech_pvt->channel, "dtmf_type"))) {
if (!strcasecmp(val, "rfc2833")) {
tech_pvt->dtmf_type = DTMF_2833;
@ -1923,7 +1919,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
tech_pvt->ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
switch_set_flag(tech_pvt, TFLAG_RTP);
switch_set_flag(tech_pvt, TFLAG_IO);
switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->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);
switch_set_flag(tech_pvt, TFLAG_VAD);
@ -2205,12 +2203,12 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
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);
tech_pvt->rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
}
if (strstr(tech_pvt->origin, "Sonus_UAC")) {
switch_set_flag_locked(tech_pvt, TFLAG_BUGGY_2833);
tech_pvt->rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Hello,\nI see you have a Sonus!\n"
"FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"

View File

@ -199,6 +199,7 @@ struct switch_rtp {
switch_port_t stun_port;
int from_auto;
uint32_t cng_count;
switch_rtp_bug_flag_t rtp_bugs;
};
static int global_init = 0;
@ -486,6 +487,11 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip)
return port;
}
SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs)
{
rtp_session->rtp_bugs = bugs;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err)
{
switch_socket_t *new_sock = NULL, *old_sock = NULL;
@ -1204,7 +1210,7 @@ static void do_2833(switch_rtp_t *rtp_session)
rtp_session->dtmf_data.timestamp_dtmf,
rtp_session->dtmf_data.out_digit_sofar,
rtp_session->dtmf_data.out_digit_sub_sofar, rtp_session->dtmf_data.out_digit_dur, rtp_session->seq);
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BUGGY_2833)) {
if (rtp_session->rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) {
rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts + samples;
}
}
@ -1257,7 +1263,7 @@ static void do_2833(switch_rtp_t *rtp_session)
switch_rtp_write_manual(rtp_session,
rtp_session->dtmf_data.out_digit_packet,
4,
switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BUGGY_2833) ? 0 : 1,
rtp_session->rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833 ? 0 : 1,
rtp_session->te, rtp_session->dtmf_data.timestamp_dtmf, &flags);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send start packet for [%c] ts=%u dur=%d/%d/%d seq=%d\n",