<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/8637">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Matthew Fredrickson: Looks good to me, approved
  Joshua Colp: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_dahdi: Configurable dialed digit timeouts<br><br>Analog phones dial overlap dialing and it is chan_dahdi's job to read the<br>numbers.  It has three timeout constants that this commit converts to<br>channel-level configuration options:<br><br>* firstdigit_timeout: Default time (ms) to detect first digit<br><br>* interdigit_timeout: Default time (ms) to detect following digits<br><br>* matchdigit_timeout: Default time (ms) to wait in case of ambiguous<br>match.  This happens when the dialed digits match a number in the current<br>context but are also the prefix of another number.<br><br>Change-Id: Ib728fa900a4f6ae56d1ed810aba61b6593fb7213<br>---<br>M CHANGES<br>M UPGRADE.txt<br>M channels/chan_dahdi.c<br>M channels/chan_dahdi.h<br>M channels/sig_analog.c<br>M channels/sig_analog.h<br>M configs/samples/chan_dahdi.conf.sample<br>7 files changed, 118 insertions(+), 29 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index 19c8f86..7b67f8d 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -45,6 +45,11 @@<br>    headers be retrieved from the REFER message and made accessible to the<br>    dialplan in the hash TRANSFER_DATA.<br> <br>+chan_dahdi<br>+------------------<br>+ * Timeouts for reading digits from analog phones are now configurable in<br>+   chan_dahdi.conf: firstdigit_timeout, interdigit_timeout, matchdigit_timeout.<br>+<br> AMI<br> ------------------<br>  * The ContactStatus and Status fields for the manager events ContactStatus<br>diff --git a/UPGRADE.txt b/UPGRADE.txt<br>index 108c10a..154a9b7 100644<br>--- a/UPGRADE.txt<br>+++ b/UPGRADE.txt<br>@@ -50,6 +50,10 @@<br>    MALLOC_DEBUG and vice versa.  Third-party pre-compiled modules no longer<br>    need to have a special build with it enabled.<br> <br>+chan_dahdi:<br>+ - Timeouts for reading digits from analog phones are now configurable in<br>+   chan_dahdi.conf: firstdigit_timeout, interdigit_timeout, matchdigit_timeout.<br>+<br> cdr_syslog:<br>  - The cdr_syslog module is now deprecated and by default it is no longer<br>    built.<br>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c<br>index 37e2774..7c54cf3 100644<br>--- a/channels/chan_dahdi.c<br>+++ b/channels/chan_dahdi.c<br>@@ -615,15 +615,6 @@<br> static char pridebugfilename[1024] = "";<br> #endif<br> <br>-/*! \brief Wait up to 16 seconds for first digit (FXO logic) */<br>-static int firstdigittimeout = 16000;<br>-<br>-/*! \brief How long to wait for following digits (FXO logic) */<br>-static int gendigittimeout = 8000;<br>-<br>-/*! \brief How long to wait for an extra digit, if there is an ambiguous match */<br>-static int matchdigittimeout = 3000;<br>-<br> /*! \brief Protect the interface list (of dahdi_pvt's) */<br> AST_MUTEX_DEFINE_STATIC(iflock);<br> <br>@@ -977,6 +968,9 @@<br>                         .buf_no = numbufs,<br>                    .usefaxbuffers = 0,<br>                   .cc_params = ast_cc_config_params_init(),<br>+                    .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,<br>+                    .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,<br>+                    .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,<br>             },<br>            .timing = {<br>                   .prewinktime = -1,<br>@@ -3326,6 +3320,19 @@<br>    }<br> }<br> <br>+#define gen_pvt_field_callback(type, field) \<br>+     static type my_get_##field(void *pvt) \<br>+      { \<br>+          struct dahdi_pvt *p = pvt; \<br>+         return p->field; \<br>+        }<br>+<br>+gen_pvt_field_callback(int, firstdigit_timeout);<br>+gen_pvt_field_callback(int, interdigit_timeout);<br>+gen_pvt_field_callback(int, matchdigit_timeout);<br>+<br>+#undef gen_pvt_field_callback<br>+<br> struct analog_callback analog_callbacks =<br> {<br>   .play_tone = my_play_tone,<br>@@ -3394,6 +3401,9 @@<br>     .answer_polarityswitch = my_answer_polarityswitch,<br>    .hangup_polarityswitch = my_hangup_polarityswitch,<br>    .have_progressdetect = my_have_progressdetect,<br>+       .get_firstdigit_timeout = my_get_firstdigit_timeout,<br>+ .get_matchdigit_timeout = my_get_matchdigit_timeout,<br>+ .get_interdigit_timeout = my_get_interdigit_timeout,<br> };<br> <br> /*! Round robin search locations. */<br>@@ -9555,9 +9565,9 @@<br>                            dtmfbuf[len] = '\0';<br>                          while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {<br>                                       if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {<br>-                                              timeout = matchdigittimeout;<br>+                                         timeout = p->matchdigit_timeout;<br>                                   } else {<br>-                                             timeout = gendigittimeout;<br>+                                           timeout = p->interdigit_timeout;<br>                                   }<br>                                     res = ast_waitfordigit(chan, timeout);<br>                                        if (res < 0) {<br>@@ -9725,7 +9735,7 @@<br>      case SIG_FXOGS:<br>       case SIG_FXOKS:<br>               /* Read the first digit */<br>-           timeout = firstdigittimeout;<br>+         timeout = p->firstdigit_timeout;<br>           /* If starting a threeway call, never timeout on the first digit so someone<br>              can use flash-hook as a "hold" feature */<br>                if (p->subs[SUB_THREEWAY].owner)<br>@@ -9800,8 +9810,8 @@<br>                                    }<br>                             } else {<br>                                      /* It's a match, but they just typed a digit, and there is an ambiguous match,<br>-                                      so just set the timeout to matchdigittimeout and wait some more */<br>-                                        timeout = matchdigittimeout;<br>+                                    so just set the timeout to matchdigit_timeout and wait some more */<br>+                                       timeout = p->matchdigit_timeout;<br>                           }<br>                     } else if (res == 0) {<br>                                ast_debug(1, "not enough digits (and no ambiguous match)...\n");<br>@@ -9821,7 +9831,7 @@<br>                             len = 0;<br>                              ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);<br>                           memset(exten, 0, sizeof(exten));<br>-                             timeout = firstdigittimeout;<br>+                         timeout = p->firstdigit_timeout;<br> <br>                        } else if (!strcmp(exten, pickupexten)) {<br>                             /* Scan all channels and see if there are any<br>@@ -9866,7 +9876,7 @@<br>                          }<br>                             len = 0;<br>                              memset(exten, 0, sizeof(exten));<br>-                             timeout = firstdigittimeout;<br>+                         timeout = p->firstdigit_timeout;<br>                   } else if (p->callreturn && !strcmp(exten, "*69")) {<br>                             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);<br>                                break;<br>@@ -9938,7 +9948,7 @@<br>                                 }<br>                             len = 0;<br>                              memset(exten, 0, sizeof(exten));<br>-                             timeout = firstdigittimeout;<br>+                         timeout = p->firstdigit_timeout;<br>                   } else if (!strcmp(exten, "*0")) {<br>                          struct ast_channel *nbridge =<br>                                         p->subs[SUB_THREEWAY].owner;<br>@@ -9986,7 +9996,7 @@<br>                                break;<br>                        }<br>                     if (!timeout)<br>-                                timeout = gendigittimeout;<br>+                           timeout = p->interdigit_timeout;<br>                   if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))<br>                             tone_zone_play_tone(p->subs[idx].dfd, -1);<br>                 }<br>@@ -12501,6 +12511,9 @@<br>            tmp->waitfordialtone = conf->chan.waitfordialtone;<br>              tmp->dialtone_detect = conf->chan.dialtone_detect;<br>              tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;<br>+         tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;<br>+               tmp->interdigit_timeout = conf->chan.interdigit_timeout;<br>+               tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;<br>                tmp->cancallforward = conf->chan.cancallforward;<br>                tmp->dtmfrelax = conf->chan.dtmfrelax;<br>          tmp->callwaiting = tmp->permcallwaiting;<br>@@ -17713,6 +17726,21 @@<br>                      if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {<br>                              confp->chan.faxdetect_timeout = 0;<br>                         }<br>+            } else if (!strcasecmp(v->name, "firstdigit_timeout")) {<br>+                        if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1<br>+                               || confp->chan.firstdigit_timeout <= 0) {<br>+                              confp->chan.firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT;<br>+                      }<br>+            } else if (!strcasecmp(v->name, "interdigit_timeout")) {<br>+                        if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1<br>+                               || confp->chan.interdigit_timeout <= 0) {<br>+                              confp->chan.interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT;<br>+                      }<br>+            } else if (!strcasecmp(v->name, "matchdigit_timeout")) {<br>+                        if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1<br>+                               || confp->chan.matchdigit_timeout <= 0) {<br>+                              confp->chan.matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT;<br>+                      }<br>             } else if (!strcasecmp(v->name, "echocancel")) {<br>                         process_echocancel(confp, v->value, v->lineno);<br>                 } else if (!strcasecmp(v->name, "echotraining")) {<br>diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h<br>index ab5c1eb..c22ed01 100644<br>--- a/channels/chan_dahdi.h<br>+++ b/channels/chan_dahdi.h<br>@@ -617,6 +617,21 @@<br>     * \note Set from the "faxdetect_timeout" value read in from chan_dahdi.conf<br>         */<br>   unsigned int faxdetect_timeout;<br>+      /*!<br>+   * \brief Time (ms) to detect first digit (in an analog phone)<br>+        * \note Set from the "firstdigit_timeout" value read in from chan_dahdi.conf<br>+       */<br>+  int firstdigit_timeout;<br>+      /*!<br>+   * \brief Time (ms) to detect following digits (in an analog phone)<br>+   * \note Set from the "interdigit_timeout" value read in from chan_dahdi.conf<br>+       */<br>+  int interdigit_timeout;<br>+      /*!<br>+   * \brief Time (ms) to wait, in case of ambiguous match (in an analog phone)<br>+  * \note Set from the "matchdigit_timeout" value read in from chan_dahdi.conf<br>+       */<br>+  int matchdigit_timeout;<br>       struct timeval waitingfordt;                    /*!< Time we started waiting for dialtone */<br>       struct timeval flashtime;                       /*!< Last flash-hook time */<br>       /*! \brief Opaque DSP configuration structure. */<br>diff --git a/channels/sig_analog.c b/channels/sig_analog.c<br>index 110942c..53f9fb2 100644<br>--- a/channels/sig_analog.c<br>+++ b/channels/sig_analog.c<br>@@ -62,9 +62,6 @@<br> #define POLARITY_IDLE 0<br> #define POLARITY_REV    1<br> #define MIN_MS_SINCE_FLASH                    ( (2000) )      /*!< 2000 ms */<br>-static int analog_matchdigittimeout = 3000;<br>-static int analog_gendigittimeout = 8000;<br>-static int analog_firstdigittimeout = 16000;<br> static char analog_defaultcic[64] = "";<br> static char analog_defaultozz[64] = "";<br> <br>@@ -218,6 +215,21 @@<br>  /* Don't have progress detection. */<br>      return 0;<br> }<br>+<br>+#define gen_analog_field_callback(type, callback_name, def_value) \<br>+       static type analog_get_##callback_name(struct analog_pvt *p) \<br>+       { \<br>+          if (!analog_callbacks.get_##callback_name) { \<br>+                       return def_value; \<br>+          } \<br>+          return analog_callbacks.get_##callback_name(p->chan_pvt); \<br>+       }<br>+<br>+gen_analog_field_callback(int, firstdigit_timeout, ANALOG_FIRST_DIGIT_TIMEOUT);<br>+gen_analog_field_callback(int, interdigit_timeout, ANALOG_INTER_DIGIT_TIMEOUT);<br>+gen_analog_field_callback(int, matchdigit_timeout, ANALOG_MATCH_DIGIT_TIMEOUT);<br>+<br>+#undef gen_analog_field_callback<br> <br> enum analog_cid_start analog_str_to_cidstart(const char *value)<br> {<br>@@ -1886,9 +1898,9 @@<br>                              dtmfbuf[len] = '\0';<br>                          while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {<br>                                       if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {<br>-                                              timeout = analog_matchdigittimeout;<br>+                                          timeout = analog_get_matchdigit_timeout(p);<br>                                   } else {<br>-                                             timeout = analog_gendigittimeout;<br>+                                            timeout = analog_get_interdigit_timeout(p);<br>                                   }<br>                                     res = ast_waitfordigit(chan, timeout);<br>                                        if (res < 0) {<br>@@ -2074,7 +2086,7 @@<br>      case ANALOG_SIG_FXOGS:<br>        case ANALOG_SIG_FXOKS:<br>                /* Read the first digit */<br>-           timeout = analog_firstdigittimeout;<br>+          timeout = analog_get_firstdigit_timeout(p);<br>           /* If starting a threeway call, never timeout on the first digit so someone<br>              can use flash-hook as a "hold" feature */<br>                if (p->subs[ANALOG_SUB_THREEWAY].owner) {<br>@@ -2155,7 +2167,7 @@<br>                           } else {<br>                                      /* It's a match, but they just typed a digit, and there is an ambiguous match,<br>                                       so just set the timeout to analog_matchdigittimeout and wait some more */<br>-                                 timeout = analog_matchdigittimeout;<br>+                                  timeout = analog_get_matchdigit_timeout(p);<br>                           }<br>                     } else if (res == 0) {<br>                                ast_debug(1, "not enough digits (and no ambiguous match)...\n");<br>@@ -2174,7 +2186,7 @@<br>                             }<br>                             len = 0;<br>                              memset(exten, 0, sizeof(exten));<br>-                             timeout = analog_firstdigittimeout;<br>+                          timeout = analog_get_firstdigit_timeout(p);<br> <br>                        } else if (!strcmp(exten, pickupexten)) {<br>                             /* Scan all channels and see if there are any<br>@@ -2219,7 +2231,7 @@<br>                          }<br>                             len = 0;<br>                              memset(exten, 0, sizeof(exten));<br>-                             timeout = analog_firstdigittimeout;<br>+                          timeout = analog_get_firstdigit_timeout(p);<br>                   } else if (p->callreturn && !strcmp(exten, "*69")) {<br>                             res = 0;<br>                              if (!ast_strlen_zero(p->lastcid_num)) {<br>@@ -2305,7 +2317,7 @@<br>                             }<br>                             len = 0;<br>                              memset(exten, 0, sizeof(exten));<br>-                             timeout = analog_firstdigittimeout;<br>+                          timeout = analog_get_firstdigit_timeout(p);<br>                   } else if (!strcmp(exten, "*0")) {<br>                          struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner;<br>                          struct analog_pvt *pbridge = NULL;<br>@@ -2348,7 +2360,7 @@<br>                             break;<br>                        }<br>                     if (!timeout) {<br>-                              timeout = analog_gendigittimeout;<br>+                            timeout = analog_get_interdigit_timeout(p);<br>                   }<br>                     if (len && !ast_ignore_pattern(ast_channel_context(chan), exten)) {<br>                           analog_play_tone(p, idx, -1);<br>diff --git a/channels/sig_analog.h b/channels/sig_analog.h<br>index 42e00c0..3b9dcf5 100644<br>--- a/channels/sig_analog.h<br>+++ b/channels/sig_analog.h<br>@@ -34,6 +34,13 @@<br> #define READ_SIZE 160<br> #define RING_PATTERNS 3<br> <br>+/*! \brief Default time (ms) to detect first digit */<br>+#define ANALOG_FIRST_DIGIT_TIMEOUT        16000<br>+/*! \brief Default time (ms) to detect following digits */<br>+#define ANALOG_INTER_DIGIT_TIMEOUT 8000<br>+/*! \brief Default time (ms) to wait, in case of ambiguous match */<br>+#define ANALOG_MATCH_DIGIT_TIMEOUT 3000<br>+<br> /* Signalling types supported */<br> enum analog_sigtype {<br>    ANALOG_SIG_NONE = -1,<br>@@ -237,6 +244,9 @@<br> <br>         const char *(* const get_orig_dialstring)(void *pvt);<br>         int (* const have_progressdetect)(void *pvt);<br>+        int (* const get_firstdigit_timeout)(void *pvt);<br>+     int (* const get_interdigit_timeout)(void *pvt);<br>+     int (* const get_matchdigit_timeout)(void *pvt);<br> };<br> <br> /*! Global analog callbacks to the upper layer. */<br>diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample<br>index 3c5e18d..d24c22b 100644<br>--- a/configs/samples/chan_dahdi.conf.sample<br>+++ b/configs/samples/chan_dahdi.conf.sample<br>@@ -1137,6 +1137,21 @@<br> ;<br> ;faxbuffers=>6,full<br> ;<br>+; When FXO signalling (FXS device, e.g. analog phone) is used, overlap dialing<br>+; is typically used. Asterisk has several configurable (per-channel) timeouts<br>+; to know how long to wait for the next digit. All the values are in<br>+; milliseconds.<br>+; * firstdigit_timeout: a longer timeout before any digit is dialed.<br>+;   By default: 16 seconds.<br>+; * interdigit_timeout: timeout for next digits, if the current number dialed<br>+;   does not match a number in the current context. Default: 8 seconds.<br>+; * matchdigit_timeout: timeout for next digits, if the current number dialed<br>+;   matches a number in the current context. Default: 3 seconds.<br>+;<br>+;firstdigit_timeout=16000<br>+;interdigit_timeout=8000<br>+;matchdigit_timeout=3000<br>+;<br> ; Configure the default number of DAHDI buffers and the transmit policy to use.<br> ; This can be used to eliminate data drops when scheduling jitter prevents<br> ; Asterisk from writing to a DAHDI channel regularly. Most users will probably<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8637">change 8637</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8637"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ib728fa900a4f6ae56d1ed810aba61b6593fb7213 </div>
<div style="display:none"> Gerrit-Change-Number: 8637 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Tzafrir Cohen <tzafrir.cohen@xorcom.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Matthew Fredrickson <creslin@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Oron Peled <oron.peled@xorcom.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>