]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
sig_analog: Allow '#' to end the inter-digit timeout when dialing.
authorNaveen Albert <asterisk@phreaknet.org>
Fri, 3 Oct 2025 19:56:06 +0000 (15:56 -0400)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 30 Oct 2025 16:05:56 +0000 (16:05 +0000)
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

channels/sig_analog.c

index 879007658d04f9556ffd49dad31be0f2b61aeec1..d45644fa1d8a913f8d260b64cf114eebe3e6e0bc 100644 (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' */
@@ -2438,8 +2439,27 @@ static void *__analog_ss_thread(void *data)
                                goto quit;
                        } else if (res) {
                                ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
-                               exten[len++]=res;
+                               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);