sig_analog: Allow '#' to end the inter-digit timeout when dialing.

It is customary to allow # to terminate digit collection immediately
when there would normally be a timeout. However, currently, users are
forced to wait for the timeout to expire when dialing numbers that
are prefixes of other valid matches, and there is no way to end the
timeout early. Customarily, # terminates the timeout, but at the moment,
this is just rejected unless there happens to be a matching extension
ending in #.

Allow # to terminate the timeout in cases where there is no dialplan
match. This ensures that the dialplan is always respected, but if a
valid extension has been dialed that happens to prefix other valid
matches, # can be used to dial it immediately.

Resolves: #1510
This commit is contained in:
Naveen Albert
2025-10-03 15:56:06 -04:00
parent 621744274e
commit e8d97e5d60

View File

@@ -2422,6 +2422,7 @@ static void *__analog_ss_thread(void *data)
while (len < AST_MAX_EXTENSION-1) {
int is_exten_parking = 0;
int is_lastnumredial = 0;
int is_endofdialing = 0;
/* Read digit unless it's supposed to be immediate, in which case the
only answer is 's' */
@@ -2440,6 +2441,25 @@ static void *__analog_ss_thread(void *data)
ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
exten[len++] = res;
exten[len] = '\0';
if (len > 1 && res == '#' && !ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
/* The user was dialing something that matched, but as soon as he dialed #, we no longer have a match.
* Check if what was dialed immediately prior to the # is an extension that exists.
* If so, we can treat "#" as the end of dialing terminator to allow user to complete the call without a timeout.
* This is fully compatible with the user's dialplan, since we only do this if there isn't a dialplan match. */
exten[--len] = '\0'; /* Remove '#' from the buffer to test the extension without it */
if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
/* The number dialed prior to the # exists as a valid extension.
* Since the number with # does not exist, treat # as end of dialing. */
ast_debug(1, "Interpreting '#' as end of dialing\n");
is_endofdialing = 1;
} else {
/* Even without the #, the number in the buffer is not a valid extension.
* In this case, it's still invalid; do nothing special.
* We simply reverse the removal of '#' from the buffer, i.e. we append it again. */
exten[len++] = res;
exten[len ] = '\0';
}
}
}
if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
analog_play_tone(p, idx, -1);
@@ -2468,7 +2488,7 @@ static void *__analog_ss_thread(void *data)
}
}
if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
if (!res || is_lastnumredial || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
if (!res || is_lastnumredial || is_endofdialing || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
if (getforward) {
/* Record this as the forwarding extension */
analog_lock_private(p);