[Home]

Summary:ASTERISK-08983: Asterisk silently loses DTMF digits when sending them through ast_dtmf_stream()
Reporter:jcomellas (jcomellas)Labels:
Date Opened:2007-03-09 14:13:36.000-0600Date Closed:2007-07-11 19:58:48
Priority:MajorRegression?No
Status:Closed/CompleteComponents:Core/General
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:( 0) additional_delay_in_ast_dtmf_stream.patch
Description:When using the bridge features in Asterisk for a call with two SIP channels, if we enter a DTMF digit that matches the first digit of a bridge feature and another digit that doesn't (e.g. we enter '#4' and the disconnect feature in /etc/asterisk/features.conf is set to '##') sometimes the last digit is silently dropped and not passed to the other channel.

Let's go over how the bridge features work to see where the problem lies. Whenever a channel sends a DTMF digit inside a bridge (res/res_features.c:ast_bridge_call()) that has some bridge features enabled, Asterisk tries to match the sent DTMF to the DTMF sequence of any of the active bridge features. If it matches, the DTMF is "queued" in the 'featurecode' variable inside ast_bridge_call(). If, at some point, additional DTMFs are sent and Asterisk determines that they cannot form a valid bridge feature sequence, the whole queued sequence is sent at once to the other channel in the bridge using ast_dtmf_stream(). This function uses ast_write() to send the DTMFs to the channel, which sometimes silently drops the last DTMF digit of the sequence. So far, what I've been able to see is that the DTMF is dropped because of the following code (channel.c:1261):

if (chan->generatordata) {
if (ast_test_flag(chan, AST_FLAG_WRITE_INT))
ast_deactivate_generator(chan);
else {
ast_mutex_unlock(&chan->lock);
return 0;
}
}

It seems that Asterisk ast_dtmf_stream() is trying to write the second DTMF before the first one has been fully completed (chan->generatordata is not NULL here) and ast_write() fails without returning an error (the AST_FLAG_WRITE_INT flag is not set for this channel).

Here's an example of the problem (using the configuration data in the "Additional Information" field):

1. SPA941 sends DTMF '#' to Asterisk
2. Asterisk considers this DTMF as a valid prefix for a bridge feature and queues it.
3. SPA941 waits about 2 seconds
4. SPA941 sends DTMF '4'to Asterisk.
5. '#4' is not a valid bridge feature sequence, so Asterisk sends the '#4' to KPhone using ast_dtmf_stream()
6. ast_write() sends the '#' but drops the '4'.
6. KPhone only receives the '#' DTMF.

I have a workaround for this problem (included in the attached patch), which involves setting the default delay between DTMFs in ast_dtmf_stream() to 200 ms (instead of the previous value of 100 ms). The real fix, though, would be to add some code to check when a DTMF has been completely sent (maybe a loop waiting for chan->generatordata to be NULL).

****** ADDITIONAL INFORMATION ******

The setup needed to easily reproduce the bug is the following. First, we need to set the following configuration parameters in /etc/asterisk/features.conf:

 [general]
 (...)
 pickupexten = #*88888
 featuredigittimeout = 4000

 [featuremap]
 blindxfer => #*11111
 disconnect => ##
 automon => #*12222
 atxfer => #*22222

The, we need a soft phone (KPhone 4.2) registered to Asterisk using G.711u as its codec with inband DTMF signaling. I'm making calls to another SIP UA that is registered to another Asterisk instance. The callee's UA is a Linksys SPA941 phone using G.711u as its codec with RFC2833 DTMF signaling.

The DTMFs that fail are sent from the endpoint that uses RFC2833 signaling. When sending DTMFs from the endpoint with inband signaling, everything works as expected.
Comments:By: jcomellas (jcomellas) 2007-03-21 13:57:10

It looks like this problem is related to ticket ASTERISK-8693.

By: Russell Bryant (russell) 2007-04-23 13:01:35

I made a change in the 1.4 branch and trunk in revisions 61763 and 61764 that may help this issue. I made it so all digits passing through Asterisk are forced to have a reasonable minimum length. Give it a try and see if it helps. Thanks!

By: Russell Bryant (russell) 2007-05-02 14:20:30

I think I have this issue fixed.  

I have created a branch with some changes that have *significantly* improved things in my local testing. I would really appreciate it if you would give them a try before I merge them into 1.4 and trunk.

svn co http://svn.digium.com/svn/asterisk/team/russell/inband_dtmf asterisk-1.4-inband_dtmf

By: Russell Bryant (russell) 2007-05-02 18:02:01

The changes from the inband_dtmf branch have been merged into the 1.4 branch and trunk in revisions 62789 and 62791.  This should fix your issue.  If you have any problems, try enabling the internal_timing option in asterisk.conf.  If you still have problems, feel free to reopen this bug.

Thanks!