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