]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9325 [mod_dptools] Priority flag for faster bind_digit_action matches
authorAndy Newlands <andynewlands@gmail.com>
Tue, 8 Nov 2016 13:47:37 +0000 (13:47 +0000)
committerAndy Newlands <andynewlands@gmail.com>
Tue, 8 Nov 2016 13:47:37 +0000 (13:47 +0000)
Add exec: flag, 'P' (for "Priority") to bind_digit_action so that a
match is returned as soon as it is found, without waiting for the
inter-digit timeout to expire.

This can be very useful where the system needs to be more responsive
to the user.

By default, if multiple bindings are enabled and one or more use a
regex, switch_ivr_dmachine_check_match waits for the inter-digit
timeout to expire before returning a match.  This ensures overlapping
patterns, such as "^\d{4}$" and "^\12{3}$" can both be reliably matched

When the 'P' flag is specified with bind_digit_action, whose action is
exec, a match is returned as soon as the condition is satisfied,
regardless of whether or not a longer match may be possible if further
digits were entered.

For example:

<action application="bind_digit_action" data="test,~^*\d{2}$,
exec[P]:execute_extension,myextn,self,self"/>

<action application="bind_digit_action" data="test,~^#\d{2}$",
exec:execute_extension,myotherextn,self,peer"/>

The first example causes a match to be returned immediately
after the 2nd digit is received, whereas the second example
defaults to waiting for the inter-digit timeout to expire
before returning.

In cases where the 'P' flag is used with a regex and string, and both
are matched, the more explicit, string match will be returned.

For example:

<action application="bind_digit_action" data="test,~^*\d{2}$,
exec[P]:execute_extension,myextn,self,self"/>

<action application="bind_digit_action" data="test,*12,
exec[P]:execute_extension,myotherextn,self,self"/>

If "*12" is matched, myotherextn is executed, because "*12" is
more explicit/specific than "^*\d{2}$"

If the 'P'(riority) flag is not used, behaviour is unchanged from
previous versions.  This ensures backward compatibility.

FS-9325 #resolve

src/include/switch_ivr.h
src/mod/applications/mod_conference/conference_member.c
src/mod/applications/mod_dptools/mod_dptools.c
src/mod/applications/mod_httapi/mod_httapi.c
src/switch_ivr_async.c

index 712179d7838b56fb9685adf3ec60b95b0eaaaeb2..00488380ed961de16a5788c16439eaa6362716bc 100644 (file)
@@ -989,6 +989,7 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachin
 SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, 
                                                                                                                 const char *realm,
                                                                                                                 const char *digits, 
+                             switch_byte_t is_priority, 
                                                                                                                 int32_t key,
                                                                                                                 switch_ivr_dmachine_callback_t callback,
                                                                                                                 void *user_data);
index 064d12edac6bfe8f5afc67db2f87e5607f6d7348..71b50984f2c5f90d91e42d31bf327d8b67b6d6a8 100644 (file)
@@ -85,8 +85,7 @@ void conference_member_do_binding(conference_member_t *member, conference_key_ca
        }
 
        binding->handler = handler;
-       switch_ivr_dmachine_bind(member->dmachine, "conf", digits, 0, conference_loop_dmachine_dispatcher, binding);
-
+       switch_ivr_dmachine_bind(member->dmachine, "conf", digits, 0, 0, conference_loop_dmachine_dispatcher, binding);
 }
 
 void conference_member_bind_controls(conference_member_t *member, const char *controls)
index 28b1de428fd38824b076230fa84d68b9f0c5ce5a..6c952c9944f511377d93e4666c705fab4b8a403c 100644 (file)
@@ -346,6 +346,7 @@ static void bind_to_session(switch_core_session_t *session,
        switch_ivr_dmachine_t *dmachine;
        switch_channel_t *channel = switch_core_session_get_channel(session);
        const char *terminators = NULL;
+       switch_byte_t is_priority = 0;
 
        if (!(dmachine = switch_core_session_get_dmachine(session, target))) {
                uint32_t digit_timeout = 1500;
@@ -372,8 +373,27 @@ static void bind_to_session(switch_core_session_t *session,
        act->value = switch_core_session_strdup(session, arg3);
        act->target = bind_target;
        act->session = session;
-       switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act);
 
+       if (!strncasecmp(act->string, "exec", 4) || !strncasecmp(act->string, "api:", 4)) {
+               char *flags, *e;
+               char *string = switch_core_session_strdup(session, act->string);
+
+               string += 4;
+               if (*string == '[') {
+                       flags = string;
+                       if ((e = switch_find_end_paren(flags, '[', ']'))) {
+                               if (e && *(e+1) == ':') {
+                                       flags++;
+                                       *e = '\0';
+                                       if (strchr(flags, 'P'))
+                                               is_priority = 1;
+                               }
+                       }
+               }
+       }
+
+       switch_ivr_dmachine_bind(dmachine, act->realm, act->input, is_priority, 0, digit_action_callback, act);
+       
        if ((terminators = switch_channel_get_variable(channel, "bda_terminators"))) {
                switch_ivr_dmachine_set_terminators(dmachine, terminators);
        }
index 74de05e842a7b346d83fe4bdb29470de637cb78b..50c534c2d464bf3ddce1c4e9ae1ff6e85fef2cb2 100644 (file)
@@ -563,7 +563,7 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw
                        action_binding->error_file = (char *) error_file;
                        action_binding->parent = top_action_binding;
                        
-                       switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
+                       switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, 0, digit_action_callback, action_binding);
                        bind = bind->next;
                }
                
@@ -1067,7 +1067,7 @@ static switch_status_t parse_record(const char *tag_name, client_t *client, swit
                        action_binding->error_file = (char *) error_file;
                        action_binding->parent = top_action_binding;
                        
-                       switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
+                       switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, 0, digit_action_callback, action_binding);
                        bind = bind->next;
                }
                
index 8df35b5a0bbfbcc9ed5d059d4b6d6ce075b8282c..6b8e4d933d77e6e8ae52cd3e5d01641bf88fec8a 100644 (file)
@@ -44,6 +44,7 @@ struct switch_ivr_dmachine_binding {
        uint8_t rmatch;
        switch_ivr_dmachine_callback_t callback;
        switch_byte_t is_regex;
+       switch_byte_t is_priority;
        void *user_data;
        struct switch_ivr_dmachine_binding *next;
 };
@@ -247,7 +248,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmach
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, 
                                                                                                                 const char *realm,
-                                                                                                                const char *digits, 
+                                                                                                                const char *digits,
+                                                                                                                switch_byte_t is_priority,                                                                                                              
                                                                                                                 int32_t key,
                                                                                                                 switch_ivr_dmachine_callback_t callback,
                                                                                                                 void *user_data)
@@ -291,6 +293,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *
 
        binding->key = key;
        binding->digits = switch_core_strdup(dmachine->pool, digits);
+       binding->is_priority = is_priority;
        binding->callback = callback;
        binding->user_data = user_data;
 
@@ -348,11 +351,7 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
                if (bp->is_regex) {
                        switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits);
                        
-                       if (r_status == SWITCH_STATUS_SUCCESS) {
-                               bp->rmatch++;
-                       } else {
-                               bp->rmatch = 0;
-                       }
+                       bp->rmatch = r_status == SWITCH_STATUS_SUCCESS;
 
                        rmatches++;
                        pmatches++;
@@ -360,7 +359,9 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
                } else {
                        if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) {
                                pmatches++;
-                               ematches = 1;
+                               if (dmachine->cur_digit_len == strlen(bp->digits)) {
+                                       ematches++;
+                               }
                        }
                }
        }
@@ -382,7 +383,7 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
        for(bp = dmachine->realm->binding_list; bp; bp = bp->next) {
                if (bp->is_regex) {
                        if (bp->rmatch) {
-                               if (is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) {
+                               if ((bp->is_priority && ! ematches) || is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) {                                      
                                        best = DM_MATCH_EXACT;
                                        exact_bp = bp;
                                        break;
@@ -392,10 +393,10 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
                } else {
                        int pmatch = !strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits));
 
-                       if (!exact_bp && pmatch && (((pmatches == 1 || ematches == 1) && !rmatches) || is_timeout) && !strcmp(bp->digits, dmachine->digits)) {
+                       if (!exact_bp && pmatch && (!rmatches || bp->is_priority || is_timeout) && !strcmp(bp->digits, dmachine->digits)) {                             
                                best = DM_MATCH_EXACT;
                                exact_bp = bp;
-                               if (dmachine->cur_digit_len == dmachine->max_digit_len) break;
+                               if (bp->is_priority || dmachine->cur_digit_len == dmachine->max_digit_len) break;                               
                        } 
 
                        if (!(both_bp && partial_bp) && strlen(bp->digits) != strlen(dmachine->digits) && pmatch) {