[Freeswitch-users] Stacked conditions are not acting like logical AND

Michael Collins msc at freeswitch.org
Tue Jan 17 03:29:00 MSK 2012


Hi Herman,

These are common questions when dealing with the dialplan. I highly
recommend that you acquire the FreeSWITCH "bridge book" (see link near top
of wiki.freeswitch.org) and read chapters 5 and 8. (Full disclosure: I
wrote chapter 5 and Darren Schreiber wrote chapter 8.) Both of these
chapters cover the break attribute in detail. I think you might be
confusing the purpose of the break attribute.

Consider this dp fragment:
<extension name="test">
  <condition field="foo" expression="bar"/>
  <condition field="foo2" expression="bar2">
    <!-- actions here get added to task list only if both conditions are
true -->
    <!-- anti-actions here get added to task list only if foo is true and
foo2 is false -->
  </condition>
</extension>

When the dialplan parser gets to this extension, the first thing it does is
test the "foo" field. If the test fails then the parser *does not even look
at the rest of this extension*. Why not? Because all conditions have an
implied break="on-false". The following two conditions are identical in
function:
  <condition field="foo" expression="bar"/>
  <condition field="foo" expression="bar" break="on-false/>

So, if you want a set of actions to be included only if more than one
condition is met then "stacking" will work, however you cannot do
break="never". Why not? Because break="never" tells the dialplan parser,
"Hey, even if this condition fails, go ahead and evaluate the next
condition in this extension." If you have break="on-false" (or no 'break'
attribute at all) then that tells the dialplan parser, "Hey, if this
condition fails then 'break out' of this extension and continue parsing the
dialplan."

Using what we've just discussed, let's look at the example you cited in
your second post.
Dialplan extension "emergency_set_variables":

<condition field="${caller_id_name}" expression="^Emerg_" break="never">
   <action application="set" data="emergency_call=true" inline="true"/>
 </condition>

 <condition wday="2-6" time-of-day="22:00-23:59" break="never">
    <action application="set" data="open=true" inline="true"/>
 </condition>

 <condition wday="1,7" time-of-day="05:00-23:59" break="never">
    <action application="set" data="open=true" inline="true"/>
 </condition>

The dialplan parser logged this:

Dialplan: sofia/external/Unknown at 72.37.252.18 Regex (FAIL)
[emergency_set_variables] ${caller_id_name}(Unknown) =~ /^Emerg_/
break=never
Dialplan: sofia/external/Unknown at 72.37.252.18 Date/TimeMatch (FAIL)
[emergency_set_variables] break=never
Dialplan: sofia/external/Unknown at 72.37.252.18 Date/Time Match (PASS)
[emergency_set_variables] break=never
Dialplan: sofia/external/Unknown at 72.37.252.18 Action set(open=true) INLINE
EXECUTE sofia/external/Unknown at 72.37.252.18 set(open=true)

Note: I added the color so that you could see which dialplan lines
correspond to the log output.

The first condition (purple) fails. ({$caller_id_name} has the value
"Unknown" which fails the regex test against /^Emerg_/) However, since you
have break="never", the parser continues on to the next condition inside
this extension. Had you done break="on-false" (or no break attribute) then
the parser would have moved on to the next extension in the dialplan.

The second condition (orange) also fails. Again, you have break="never", so
even though it fails, the parser moves on to the next condition.

The third condition (green) passes, so the parser adds the <action> to the
task list. (Since you have inline="true" the action gets executed
immediately during dialplan parsing instead later on during the "execution
phase".)

In other words, the log output is exactly what I would expect it to be.

As to your other question about anti-actions in a stack: this also is a
common question. It looks like you are trying to do something like this:

IF (cond1 AND cond2 AND cond3) THEN
do actions
ELSE
do other actions
ENDIF

You cannot do this particular construct just with conditions and
anti-actions. Instead you'll need the brand spanking new "regex" syntax
mentioned here:
http://wiki.freeswitch.org/wiki/Dialplan_XML#Multiple_Conditions_.28Logical_OR.2C_XOR.29

So, to do what you wanted to do in the second example (in your second post)
you could try this:

<condition regex="all">
  <regex field="${sip_gateway}" expression="^${default_provider}$"/>
  <regex field="${emergency_call}" expression="^true$"/>
  <regex field="${db(select/emergency/autoanswer)}" expression="^1$"/>
  <!-- the following actions get executed if all regexes PASS -->
   <action application="set" data="call_timeout=60"/>
   <action application="set"
data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|Auto%1)}"/>
   <action application="set" data="autoanswered=true"/>
   <action application="answer" data=""/>
   <action application="set"
data="group_confirm_file=/usr/local/freeswitch/sounds/en/us/callie/emergency/press_to_accept.wav"/>
   <action application="set" data="group_confirm_key=1"/>
   <action application="bridge"
data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>
  <!-- the following anti-actions are executed if any of the regexes FAIL
-->
   <anti-action application="set"
data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|NotAuto%1)}"/>
   <anti-action application="set" data="call_timeout=30"/>
   <anti-action application="set" data="autoanswered=false"/>
   <anti-action application="set"
data="group_confirm_file=/usr/local/freeswitch/sounds/en/us/callie/emergency/press_to_accept.wav"/>
   <anti-action application="set" data="group_confirm_key=1"/>
   <anti-action application="bridge"
data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>
</condition>

The <condition regex="all"> tells the parser, "Hey, execute the <action>'s
only if all regexes PASS, otherwise execute any <anti-action>'s". That
should give you what you need.

Hope this helps!

-Michael



On Sat, Jan 14, 2012 at 7:39 PM, Herman Griffin <herman.griffin at gmail.com>wrote:

> Hello everyone,
>
> In irc SwK said that freeswitch AND operator is lazy. To me this means
> that if a condition is set to break=true and it evaluates to FAIL,
> then the that break=never will invert the meaning of FAIL; Change it
> to a PASS . But why doesn't break=false behave in this same manner
> when there is only a single condition?
>
> Take this call trace and dialplan for example. I use a single
> condition with break=false. However, unlike the stacked conditions,
> the action is not executed when the single condition evaluates to
> FAIL. Why doesn't break=never cause the action to be executed in a non
> stacked condition?
>
> Call trace:
>
> Dialplan: sofia/external/Unknown at 72.37.252.18 Regex (FAIL)
> [emergency_set_variables] ${caller_id_name}(Unknown) =~ /^Emerg_/
> break=never
> Dialplan: sofia/external/Unknown at 72.37.252.18 Date/TimeMatch (FAIL)
> [emergency_set_variables] break=never
> Dialplan: sofia/external/Unknown at 72.37.252.18 Date/Time Match (PASS)
> [emergency_set_variables] break=never
> Dialplan: sofia/external/Unknown at 72.37.252.18 Action set(open=true) INLINE
> EXECUTE sofia/external/Unknown at 72.37.252.18 set(open=true)
>
> Dialplan:
>
> <condition field="${caller_id_name}" expression="^Emerg_" break="never">
>    <action application="set" data="emergency_call=true" inline="true"/>
>  </condition>
>
>  <condition wday="2-6" time-of-day="22:00-23:59" break="never">
>     <action application="set" data="open=true" inline="true"/>
>  </condition>
>
>  <condition wday="1,7" time-of-day="05:00-23:59" break="never">
>     <action application="set" data="open=true" inline="true"/>
>  </condition>
>
> -------------------------------------------------
>
> I also getting confusing behavior with anti-action and stacked
> condition. I expect the anti-action to be executed if any of the
> stacked conditions evaluates to FAIL. However, in the case below, the
> extension simply breaks if any of the condition evaluates to FAIL.
>
> Call trace:
>
> Dialplan: sofia/external/Unknown at 72.37.252.18 parsing
> [public->emergency_bridge] continue=true
> Dialplan: sofia/external/Unknown at 72.37.252.18 Regex (PASS)
> [emergency_bridge] ${sip_gateway}(1006_7217) =~ /^1006_7217$/
> break=on-false
> Dialplan: sofia/external/Unknown at 72.37.252.18 Regex (FAIL)
> [emergency_bridge] ${emergency_call}() =~ /^true$/ break=on-false
> Dialplan: sofia/external/Unknown at 72.37.252.18 parsing
> [public->public_did] continue=false <-- [[MOVES ON TO ANOTHER
> EXTENSION WITH EXECUTING THE anti-action]]
>
> Dialplan:
>
> <condition field="${sip_gateway}" expression="^${default_provider}$"/>
>    <condition field="${emergency_call}" expression="^true$"/>
>     <condition field="${db(select/emergency/autoanswer)}" expression="^1$">
>       <action application="set" data="call_timeout=60"/>
>      <action application="set"
>
> data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|Auto%1)}"/>
>      <action application="set" data="autoanswered=true"/>
>      <action application="answer" data=""/>
>      <action application="set"
>
> data="group_confirm_file=/usr/local/freeswitch/sounds/en/us/callie/emergency/press_to_accept.wav"/>
>      <action application="set" data="group_confirm_key=1"/>
>      <action application="bridge"
> data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>
>
>       <anti-action application="set"
>
> data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|NotAuto%1)}"/>
>      <anti-action application="set" data="call_timeout=30"/>
>      <anti-action application="set" data="autoanswered=false"/>
>       <anti-action application="set"
>
> data="group_confirm_file=/usr/local/freeswitch/sounds/en/us/callie/emergency/press_to_accept.wav"/>
>      <anti-action application="set" data="group_confirm_key=1"/>
>       <anti-action application="bridge"
> data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>
>    </condition>
>   </extension>
>
>
> SwK suggested that I use a script language, which is probably what
> I'll end up doing. However, I'm very interested in understanding why
> the scenarios above. Are these bugs or are they just counter intuitive
> rules that we must simply memorize?
>
> Thanks for your input.
> Herman Griffin
>
>
>
> On Sat, Jan 14, 2012 at 11:42 AM, Jeff Lenk <jeff at jefflenk.com> wrote:
> > By putting the break=never you are defeating the "and" processing. Remove
> > that.
> >
> > Move the second group into its own extension.
> >
> > --
> > View this message in context:
> http://freeswitch-users.2379917.n2.nabble.com/Stacked-conditions-are-not-acting-like-logical-AND-tp7188082p7188271.html
> > Sent from the freeswitch-users mailing list archive at Nabble.com.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freeswitch.org/pipermail/freeswitch-users/attachments/20120116/cb9ddf6e/attachment-0001.html 


Join us at ClueCon 2011 Aug 9-11, 2011
More information about the FreeSWITCH-users mailing list