[Asterisk-Users] Re: Sipura SPA-3000 and PSTN dtmf

Arsen Chaloyan achaloyan at yahoo.com
Thu Mar 2 05:06:10 MST 2006


>Actually,
>
>I believe that something is wrong with the way
asterisk >implements the 
>whole rfc2833 in rtp.c , moreover, the default value
of >100ms in 
>dtmf_tones[] in do_senddigit() inchannel.c is to
short >to be detected 
>for lots of commercially available fxo gateways.

I can't agree on this. 100ms for inband DTMFs should
be more than enough to detect, while for rfc2833 DTMFs
even one packet can be enough, it depends on
implementation.
The main problem of asterisk isn't duration, but the
way rtp stream is constructed.

>This was reported several times but as of today the
>issue is there.
Seems there are a lot of other open issues concerning
DTMFs in asterisk none trivial to fix.

>I ended up with the following ugly hack for rtp.c &
>channel.c:
Increasing duration of dtmf events is not good idea.
May be it force SPA-3000 to work, but this can be the
source for another missfunctionalities.

Please, find below my patch against 1.2.4, which makes
asterisk more compliant to rfc2833 and reliable enough
for SPA-3000.

Index: rtp.c
===================================================================
--- rtp.c       (revision 10625)
+++ rtp.c       (working copy)
@@ -1111,6 +1111,7 @@
        int hdrlen = 12;
        int res;
        int x;
+       unsigned short duration = 0;
        int payload;
        char data[256];
        char iabuf[INET_ADDRSTRLEN];
@@ -1143,7 +1144,9 @@
        rtpheader[1] = htonl(rtp->lastdigitts);
        rtpheader[2] = htonl(rtp->ssrc); 
        rtpheader[3] = htonl((digit << 24) | (0xa <<
16) | (0));
-       for (x = 0; x < 6; x++) {
+
+
+       for (x = 0; x < 5; x++) {
                if (rtp->them.sin_port &&
rtp->them.sin_addr.s_addr) {
                        res = sendto(rtp->s, (void *)
rtpheader, hdrlen + 4, 0, (struct sockaddr *)
&rtp->them, sizeof(rtp->them));
                        if (res < 0) 
@@ -1155,35 +1158,46 @@
                                           
ast_inet_ntoa(iabuf, sizeof(iabuf),
rtp->them.sin_addr),
                                           
ntohs(rtp->them.sin_port), payload, rtp->seqno,
rtp->lastdigitts, res - hdrlen);
                }
-               /* Sequence number of last two end
packets does not get incremented */
-               if (x < 3)
-                       rtp->seqno++;
+
+               /* Sequence number must be incremented
for every packet*/
+               rtp->seqno++;
                /* Clear marker bit and set seqno */
                rtpheader[0] = htonl((2 << 30) |
(payload << 16) | (rtp->seqno));
-               /* For the last three packets, set the
duration and the end bit */
-               if (x == 2) {
-#if 0
-                       /* No, this is wrong...  Do
not increment lastdigitts, that's not according
-                          to the RFC, as best we can
determine */
-                       rtp->lastdigitts++; /* or else
the SPA3000 will click instead of beeping... */
-                       rtpheader[1] =
htonl(rtp->lastdigitts);
-#endif
-                       /* Make duration 800 (100ms)
*/
-                       rtpheader[3] |= htonl((800));
-                       /* Set the End bit */
-                       rtpheader[3] |= htonl((1 <<
23));
+               /* Increment duration for 160 (20ms)
*/
+               duration += 160;
+               rtpheader[3] = htonl((digit << 24) |
(0xa << 16) | (duration));
+       }
+
+       /* Set the End bit */
+       rtpheader[3] |= htonl((1 << 23));
+
+       /* Send last packet and repeat it 2 times */
+       for (x = 0; x < 3; x++) {
+               if (rtp->them.sin_port &&
rtp->them.sin_addr.s_addr) {
+                       res = sendto(rtp->s, (void *)
rtpheader, hdrlen + 4, 0, (struct sockaddr *)
&rtp->them, sizeof(rtp->them));
+                       if (res < 0) 
+                               ast_log(LOG_ERROR,
"RTP Transmission error to %s:%d: %s\n",
+                                      
ast_inet_ntoa(iabuf, sizeof(iabuf),
rtp->them.sin_addr),
+                                      
ntohs(rtp->them.sin_port), strerror(errno));
+                       if
(rtp_debug_test_addr(&rtp->them))
+                               ast_verbose("Sent RTP
packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
+                                          
ast_inet_ntoa(iabuf, sizeof(iabuf),
rtp->them.sin_addr),
+                                          
ntohs(rtp->them.sin_port), payload, rtp->seqno,
rtp->lastdigitts, res - hdrlen);
                }
+
+               /* Sequence number must be incremented
for every packet, even for retransmitted last two
packets */
+               rtp->seqno++;
+               /* Set seqno */
+               rtpheader[0] = htonl((2 << 30) |
(payload << 16) | (rtp->seqno));
        }
+
        /* Increment the digit timestamp by 120ms, to
ensure that digits
           sent sequentially with no intervening
non-digit packets do not
           get sent with the same timestamp, and that
sequential digits
           have some 'dead air' in between them
        */
-       rtp->lastdigitts += 960;
-       /* Increment the sequence number to reflect
the last packet
-          that was sent
-       */
-       rtp->seqno++;
+       duration += 160;
+       rtp->lastdigitts += duration;
        return 0;
 }


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the asterisk-users mailing list