diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index e6c41e51e9..2cd6d46806 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -276,6 +276,21 @@
+
+ W/O Duration in ms for which to wait for dial tone on the current call.
+ This setting is will temporarily override the waitfordialtone
+ setting in chan_dahdi.conf (typically if that setting is disabled).
+ You must call this in a pre-dial handler when making a call on an analog trunk
+ (e.g. FXS-signalled interface).
+ This allows, for example, being able to barge in on an in-use trunk,
+ if dialed specifically, but allows skipping the trunk when routing calls
+ if dial tone is not present on a channel.
+ This setting will only apply to the current (next) call made on the
+ DAHDI channel, and will not persist for future calls.
+ Please keep in mind that due to the way that chan_dahdi implements dial tone detection,
+ DTMF digits on an in-use channel will temporarily relay to any other channels attempting to use the channel for a call.
+ However, voice transmission will not leak.
+
@@ -2104,11 +2119,40 @@ static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
{
struct dahdi_pvt *p = pvt;
- if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
- ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
- gettimeofday(&p->waitingfordt, NULL);
- ast_setstate(ast, AST_STATE_OFFHOOK);
+ /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
+ * but we also need to check against this value until we get dialtone
+ * or the timer expires, since waitingfordt is when the timer started,
+ * not when it should expire.
+ *
+ * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
+ * has already been set, as waitingfordt is what is checked at runtime to determine
+ * if we should be waiting for dial tone. This ensures that if a second call
+ * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
+ * preventing leaking to other calls while remaining available to check on the first one while dialing.
+ */
+ p->waitfordialtoneduration = p->waitfordialtonetemp ? p->waitfordialtonetemp : p->waitfordialtone;
+ p->waitfordialtonetemp = 0;
+
+ if (!(p->waitfordialtoneduration && CANPROGRESSDETECT(p))) {
+ return;
+ }
+
+ /* Because the DSP is allocated when the channel is created,
+ * if we requested waitfordialtone later (in a predial handler),
+ * we need to create it now */
+ if (!p->dsp) {
+ p->dsp = ast_dsp_new();
+ if (!p->dsp) {
+ ast_log(LOG_ERROR, "Unable to allocate DSP\n");
+ return;
+ }
}
+ p->dsp_features |= DSP_FEATURE_WAITDIALTONE;
+ ast_dsp_set_features(p->dsp, p->dsp_features);
+
+ ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
+ gettimeofday(&p->waitingfordt, NULL);
+ ast_setstate(ast, AST_STATE_OFFHOOK);
}
static int my_check_waitingfordt(void *pvt)
@@ -7254,6 +7298,21 @@ static int dahdi_func_write(struct ast_channel *chan, const char *function, char
res = -1;
}
ast_mutex_unlock(&p->lock);
+ } else if (!strcasecmp(data, "waitfordialtone")) {
+ if (ast_strlen_zero(value)) {
+ ast_log(LOG_WARNING, "waitfordialtone requires a duration in ms\n");
+ return -1;
+ }
+
+ ast_mutex_lock(&p->lock);
+ if (!CANPROGRESSDETECT(p)) {
+ ast_log(LOG_WARNING, "%s only supported on analog trunks\n", data);
+ ast_mutex_unlock(&p->lock);
+ return -1;
+ }
+ /* Only set the temp waitfordialtone setting, not the permanent one. */
+ p->waitfordialtonetemp = atoi(value);
+ ast_mutex_unlock(&p->lock);
} else {
res = -1;
}
@@ -9093,9 +9152,9 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
/* DSP clears us of being pulse */
p->pulsedial = 0;
} else if (p->waitingfordt.tv_sec) {
- if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
+ if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtoneduration) {
p->waitingfordt.tv_sec = 0;
- ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
+ ast_log(LOG_NOTICE, "Never saw dialtone on channel %d\n", p->channel);
ast_frfree(f);
f = NULL;
} else if (f->frametype == AST_FRAME_VOICE) {
diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h
index b7955cdddf..4431efd913 100644
--- a/channels/chan_dahdi.h
+++ b/channels/chan_dahdi.h
@@ -654,6 +654,14 @@ struct dahdi_pvt {
* \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
*/
int waitfordialtone;
+ /*!
+ * \brief Transient variable. Same as waitfordialtone, but temporarily set for a specific call, rather than permanently for the channel.
+ */
+ int waitfordialtonetemp;
+ /*!
+ * \brief Transient variable. Stored off waitfordialtone duration at runtime.
+ */
+ int waitfordialtoneduration;
/*!
* \brief Number of frames to watch for dialtone in incoming calls
* \note Set from the "dialtone_detect" value read in from chan_dahdi.conf