]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 370271,370274,370277 via svnmerge from
authorAutomerge script <automerge@asterisk.org>
Thu, 19 Jul 2012 22:24:05 +0000 (22:24 +0000)
committerAutomerge script <automerge@asterisk.org>
Thu, 19 Jul 2012 22:24:05 +0000 (22:24 +0000)
file:///srv/subversion/repos/asterisk/branches/10

................
  r370271 | mjordan | 2012-07-19 16:37:09 -0500 (Thu, 19 Jul 2012) | 49 lines

  Handle extremely out of order RFC 2833 DTMF

  The current implementation of RFC 2833 DTMF handling in res_rtp_asterisk will,
  if a packet arrives out of order, drop the packet.  This is to prevent
  duplicate ton generation in the Asterisk core.  Since the RTP layer does not
  buffer data itself, this is the only option the RTP layer currently has for
  handling packets that arrive out of order.

  For the most part, this doesn't matter.  For a particular digit, so long as a
  BEGIN packet arrives before the first END packet, the digit will be produced.
  If subsequent BEGIN packets arrive interleaved with the ENDs, they will be
  dropped; likewise, if the BEGIN or END packets themselves are out of order,
  those packets are dropped but sufficient information is conveyed to the
  Asterisk core to produce the appropriate digit.

  For certain sequences of DTMF packets - most notably when, for a particular
  digit, an END packet arrives before any BEGIN packet for that digit - this
  is a real problem.  When an END arrives before any BEGINs, the END packet is
  dropped - but at the same time, it causes subsequent BEGIN packets for that
  digit to be ignored.  When the next in order END packet arrives, it too is
  dropped - Asterisk believes that there was no initial BEGIN.

  The solution this patch provides is to trust the END packet to convey the
  information needed for the Asterisk core to produce the DTMF digit.  If we
  receive an END packet, and it:
    * Has a timestamp greater then the last timestamp received from an END
      packet
    * Does not have the same sequence number as the last received sequence
      number (and is thus not an END packet retransmission)
  Then we send the END frame up to the Asterisk core.  It contains enough
  DTMF information for Asterisk to produce the digit.

  On the other hand, if we receive a BEGIN or continuation packet that occurs
  with a timestamp equal to or less then the last END timestamp, then we've
  received something out of order - but we already have received enough
  information to produce the digit.  These packets are dropped.

  Much thanks goes to Olle Johansson (oej) for providing the idea for this
  solution.

  Review: https://reviewboard.asterisk.org/r/2033/

  (issue ASTERISK-18404)
  Reporter: Stephane Chazelas
  Tested by: Matt Jordan
  ........

  Merged revisions 370252 from http://svn.asterisk.org/svn/asterisk/branches/1.8
................
  r370274 | mjordan | 2012-07-19 17:01:32 -0500 (Thu, 19 Jul 2012) | 17 lines

  Fix compilation error when MALLOC_DEBUG is enabled

  To fix a memory leak in CEL, a channel datastore was introduced whose
  destruction function pointer was pointed to the ast_free macro.  Without
  MALLOC_DEBUG enabled this compiles as fine, as ast_free is defined as free.
  With MALLOC_DEBUG enabled, however, ast_free takes on a definition from a
  different place then utils.h, and became undefined.  This patch resolves this
  by using a reference to ast_free_ptr.  When MALLOC_DEBUG is enabled, this
  calls ast_free; when MALLOC_DEBUG is not enabled, this is defined to be
  ast_free, which is defined to be free.

  (issue AST-916)
  Reported by: Thomas Arimont
  ........

  Merged revisions 370273 from http://svn.asterisk.org/svn/asterisk/branches/1.8
................
  r370277 | rmudgett | 2012-07-19 17:11:48 -0500 (Thu, 19 Jul 2012) | 7 lines

  Fix compiler warnings.

  gcc (GCC) 4.2.4 has problems casting away constness.
  ........

  Merged revisions 370275 from http://svn.asterisk.org/svn/asterisk/branches/1.8
................

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@370297 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/cel.c
res/res_rtp_asterisk.c

index bb8723bfcf17d7ccc5a4824ffb1bbf8eb74ae11b..a5d82a606fd3f1d5320057bc4bc482b370415a36 100644 (file)
@@ -395,7 +395,7 @@ void ast_cel_check_retire_linkedid(struct ast_channel *chan)
  */
 static const struct ast_datastore_info fabricated_channel_datastore = {
        .type = "CEL fabricated channel",
-       .destroy = ast_free,
+       .destroy = ast_free_ptr,
 };
 
 struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event)
@@ -499,11 +499,10 @@ struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event
                return NULL;
        }
 
-       tchan->appl = app_data;
-       tchan->data = app_data + strlen(record.application_name) + 1;
+       tchan->appl = strcpy(app_data, record.application_name);
+       tchan->data = strcpy(app_data + strlen(record.application_name) + 1,
+               record.application_data);
 
-       strcpy((char *) tchan->appl, record.application_name);
-       strcpy((char *) tchan->data, record.application_data);
        datastore->data = app_data;
        ast_channel_datastore_add(tchan, datastore);
 
index b5819b0f2476f41b334dda20333cb98a96a26d95..4e2757082d5ac7f74ff3b8d5309e76c04da7b635 100644 (file)
@@ -147,12 +147,13 @@ struct ast_rtp {
        int rtpkeepalive;               /*!< Send RTP comfort noice packets for keepalive */
 
        /* DTMF Reception Variables */
-       char resp;
-       unsigned int lastevent;
-       unsigned int dtmf_duration;     /*!< Total duration in samples since the digit start event */
-       unsigned int dtmf_timeout;      /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
+       char resp;                        /*!< The current digit being processed */
+       unsigned int last_seqno;          /*!< The last known sequence number for any DTMF packet */
+       unsigned int last_end_timestamp;  /*!< The last known timestamp received from an END packet */
+       unsigned int dtmf_duration;       /*!< Total duration in samples since the digit start event */
+       unsigned int dtmf_timeout;        /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
        unsigned int dtmfsamples;
-       enum ast_rtp_dtmf_mode dtmfmode;/*!< The current DTMF mode of the RTP stream */
+       enum ast_rtp_dtmf_mode dtmfmode;  /*!< The current DTMF mode of the RTP stream */
        /* DTMF Transmission Variables */
        unsigned int lastdigitts;
        char sending_digit;     /*!< boolean - are we sending digits */
@@ -1496,8 +1497,10 @@ static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, en
                rtp->dtmfsamples = 0;
                return &ast_null_frame;
        }
-       ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp,
-                 ast_sockaddr_stringify(&remote_address));
+       ast_debug(1, "Creating %s DTMF Frame: %d (%c), at %s\n",
+               type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
+               rtp->resp, rtp->resp,
+               ast_sockaddr_stringify(&remote_address));
        if (rtp->resp == 'X') {
                rtp->f.frametype = AST_FRAME_CONTROL;
                rtp->f.subclass.integer = AST_CONTROL_FLASH;
@@ -1561,12 +1564,12 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
        }
 
        if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
-               if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
+               if ((rtp->last_end_timestamp != timestamp) || (rtp->resp && rtp->resp != resp)) {
                        rtp->resp = resp;
                        rtp->dtmf_timeout = 0;
                        f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)));
                        f->len = 0;
-                       rtp->lastevent = timestamp;
+                       rtp->last_end_timestamp = timestamp;
                        AST_LIST_INSERT_TAIL(frames, f, frame_list);
                }
        } else {
@@ -1583,31 +1586,41 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
                }
                new_duration = (new_duration & ~0xFFFF) | samples;
 
-               /* The second portion of this check is to not mistakenly
-                * stop accepting DTMF if the seqno rolls over beyond
-                * 65535.
-                */
-               if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) {
-                       /* Out of order frame. Processing this can cause us to
-                        * improperly duplicate incoming DTMF, so just drop
-                        * this.
-                        */
-                       return;
-               }
-
                if (event_end & 0x80) {
                        /* End event */
-                       if ((rtp->lastevent != seqno) && rtp->resp) {
+                       if ((rtp->last_seqno != seqno) && (timestamp > rtp->last_end_timestamp)) {
+                               rtp->last_end_timestamp = timestamp;
                                rtp->dtmf_duration = new_duration;
+                               rtp->resp = resp;
                                f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
                                f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
                                rtp->resp = 0;
                                rtp->dtmf_duration = rtp->dtmf_timeout = 0;
                                AST_LIST_INSERT_TAIL(frames, f, frame_list);
+                       } else if (rtpdebug) {
+                               ast_debug(1, "Dropping duplicate or out of order DTMF END frame (seqno: %d, ts %d, digit %c)\n",
+                                       seqno, timestamp, resp);
                        }
                } else {
                        /* Begin/continuation */
 
+                       /* The second portion of the seqno check is to not mistakenly
+                        * stop accepting DTMF if the seqno rolls over beyond
+                        * 65535.
+                        */
+                       if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
+                               || timestamp <= rtp->last_end_timestamp) {
+                               /* Out of order frame. Processing this can cause us to
+                                * improperly duplicate incoming DTMF, so just drop
+                                * this.
+                                */
+                               if (rtpdebug) {
+                                       ast_debug(1, "Dropping out of order DTMF frame (seqno %d, ts %d, digit %c)\n",
+                                               seqno, timestamp, resp);
+                               }
+                               return;
+                       }
+
                        if (rtp->resp && rtp->resp != resp) {
                                /* Another digit already began. End it */
                                f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
@@ -1631,7 +1644,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
                        rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
                }
 
-               rtp->lastevent = seqno;
+               rtp->last_seqno = seqno;
        }
 
        rtp->dtmfsamples = samples;