
How dialplan processing works
A call is incoming to FreeSWITCH.
It lands in a specific dialplan context based on its technology, network characteristics (profiles), or (if the call is originated by a registered user) based on explicit assignment in the User Directory. Starting from the beginning of the context, the call traverse the context, trying to match each extension, one after another.
Inside an extension, if a condition matches, actions and anti-actions contained in that condition are added to the call's TODO list. Based on the value of the "break" condition parameter, at each condition the call decides to stop, or to proceed to the next condition.
Based on the value of the "continue" extension parameter, at each extension the call decides to stop, or to proceed to the next extension.
After the call finishes traversing the dialplan context (because of "continue" or because there are no more extensions to check) then all (anti-)actions stored in its TODO list will be executed.
So, there are two separate phases: first phase is Dialplan Parsing (also known as ROUTING phase), where the call traverses the dialplan and accumulates actions in the TODO list (without executing them). The second phase is the EXECUTE phase, in which all accumulated actions are batch-executed.
This can be clearly seen from the FreeSWITCH console if we pump up the loglevel, type "fsctl loglevel 7", and then call 1234 again:

As you can see, the call enters the ROUTING phase, where it checks the extensions of a specific dialplan context (in this case the "default" context) looking for matches. Here the first extensions has a condition with an expression that fails to match. So, at first thought we would expect to proceed to check the next extension. But this failed condition has an anti-action inside, so actually we have a match! A negative match still is a match, not only in romantic affairs.
So, after adding the anti-action to the TODO list, the call stops traversing the dialplan context, and go forward to the EXECUTE phase.
If we delete (or comment out) the anti-action from the condition, and reloadxml, when we call again we'll see that all the extensions in the context will be checked.
NB: It is important to remember that if you SETa channel variable in dialplan, and THEN CHECK, it WILL NOT WORK as expected!
<extension name="giovanni_06"> <condition field="destination_number" expression="^4321$"> <action application="answer"/> <action application="set" data="myvariable=abc"/> </condition> <condition field="${myvariable}" expression="abc"> <action application="log" data="WARNING YESSSSS"/> <anti-action application="log" data="WARNING NOOOOOOOOT"/> </condition> </extension>
This is because the "action" of setting the variable will be executed in the EXECUTE phase, while the checking of the variable is done at the previous ROUTING (parsing) phase.
To make it work, you must "inline" the set action, so it will be executed at ROUTING phase. The following extension works:
<extension name="giovanni_07"> <condition field="destination_number" expression="^4321$"> <action application="answer"/> <action application="set" data="myvariable=abc" inline="true"/> </condition> <condition field="${myvariable}" expression="abc"> <action application="log" data="WARNING YESSSSS"/> <anti-action application="log" data="WARNING NOOOOOOOOT"/> </condition> </extension>
Also, the following will never work (you cannot inline the result from play_and_get_digits. Use a script instead):
<extension name="play_and_get_digits with say">
<condition field="destination_number" expression="^(6500)$">
<action application="play_and_get_digits" data="1 1 1 3000 # say:'press one for technical support' silence_stream://250 choice \d+" />
</condition>
<condition field="${choice}" expression="1">
<action application="log" data="TECH SUPPORT!"/>
<anti-action application="log" data="OPERATOR"/>
</condition>
</extension>