6.3. Conditional Branching
Now that you've learned a bit about expressions
and functions, it's time to put them to use. By using expressions
and functions, you can add even more advanced logic to your
dialplan. To allow your dialplan to make decisions, you'll use
conditional branching . Let's take a
closer look.
6.3.1. The GotoIf( ) Application
The key to conditional branching is the
GotoIf( ) application. GotoIf( ) evaluates an
expression and sends the caller to a specific destination based on
whether the expression evaluates to true or false.
GotoIf( ) uses a special syntax, often
called the conditional syntax:
GotoIf(expression?destination1:destination2)
If the expression evaluates to true, the caller
is sent to the first destination. If the expression evaluates to
false, the caller is sent to the second destination. So, what is
true and what is false? An empty string and the number 0 evaluate
as false. Anything else evaluates as true.
The destinations can each be one of the
following:
-
A priority within the same extension, such as
10
-
An extension and a priority within the same
context, such as 123,10
-
A context, extension, and priority, such as
incoming,123,10
-
A named priority within the same extension, such
as passed
Either of the destinations may be omitted, but
not both. If the omitted destination is to be followed, Asterisk
simply goes on to the next priority in the current extension.
Let's use GotoIf( ) in an example:
exten => 345,1,Set(TEST=1)
exten => 345,2,GotoIf($[{$TEST} = 1]?10:20)
exten => 345,10,Playback(weasels-eaten-phonesys)
exten => 345,20,Playback(office-iguanas)
By changing the value assigned to TEST
in the first line, you should be able to have your Asterisk server
play a different greeting.
Let's look at another example of conditional
branching. This time, we'll use both Goto( ) and
GotoIf( ) to count down from 10 and then hang up:
exten => 123,1,Set(COUNT=10)
exten => 123,2,GotoIf($[${COUNT} > 0]?:10)
exten => 123,3,SayNumber(${COUNT})
exten => 123,4,Set(COUNT=$[${COUNT} - 1])
exten => 123,5,Goto(2)
exten => 123,10,Hangup( )
Let's analyze this example. In the first
priority, we set the variable COUNT to 10. Next,
we check to see if COUNT is greater than 0. If it
is, we move on to the next priority. (Don't forget that if we omit
a destination in the GotoIf( ) application, control goes
to the next priority.) From there we speak the number, subtract
1 from COUNT, and go back to priority two. If
COUNT is less than or equal to 0, control goes to
priority 10, and the call is hung up.
The classic example of conditional branching is
affectionately known as the anti-girlfriend logic. If the Caller ID
number of the incoming call matches the phone number of the
recipient's ex-girlfriend, Asterisk gives a different message than
it ordinarily would to any other caller. While somewhat simple and
primitive, it's a good example for learning about conditional
branching within the Asterisk dialplan.
This example uses a channel variable called
CALLERIDNUM , which is
automatically set by Asterisk to the Caller ID number of the
inbound call. Let's assume for the sake of this example that the
victim's phone number is 885-555-1212:
exten => 123,1,GotoIf($[${CALLERIDNUM} = 8885551212]?20:10)
exten => 123,10,Dial(Zap/4)
exten => 123,20,Playback(abandon-all-hope)
exten => 123,21,Hangup( )
In priority one, we call the GotoIf( )
application. It tells Asterisk to go to priority 20 if the Caller
ID number matches 8885551212, and otherwise to go to
priority 10. If the Caller ID number matches, control of the call
goes to priority 20, which plays back an uninspiring message to the
undesired caller. Otherwise, the call attempts to dial the
recipient on channel Zap/4.
6.3.2. Time-Based Conditional
Branching with GotoIfTime( )
Another way to use conditional branches in your
dialplan is with the GotoIfTime( ) application. Whereas
GotoIf( ) evaluates an expression to decide what to do,
GotoIfTime( ) looks at the current system time and uses
that to decide whether or not to follow a different branch in the
dialplan.
The most obvious use of this application is to
give your callers a different greeting before and after normal
business hours.
The syntax for the GotoIfTime( )
application looks like this:
GotoIfTime(times,days_of_week,days_of_month,months?label)
In short, GotoIfTime( ) sends the call
to the specified label if the current date and time
match the criteria specified by times,
days_of_week, days_of_month, and
months. Let's look at each argument in more
detail:
times
-
This is a list of one or more time ranges, in
24-hour format. As an example, 9:00 a.m. through 5:00 p.m. would be
specified as 09:00-17:00. The day starts at 0:00 and ends
at 23:59.
days_of_week
-
This is a list of one or more days of the week.
The days should be specified as mon, tue,
wed, thu, fri, sat, and/or
sun. Monday through Friday would be expressed as
mon-fri. Tuesday and Thursday would be expressed as
tue,thu.
days_of_month
-
This is a list of the numerical days of the
month. Days are specified by the numbers 1 tHRough
31. The 7th through the 12th would
be expressed as 7-12, and the 15th and
30th of the month would be written as
15,30.
months
-
This is a list of one or more months of the
year. The months should be written as jan, feb,
mar, apr, and so on.
If you wish to match on all possible values for
any of these arguments, simply put an * in for that
argument.
The label argument can be any of
the following:
-
A priority within the same extension, such as
10
-
An extension and a priority within the same
context, such as 123,10
-
A context, extension, and priority, such as
incoming,123,10
-
A named priority within the same extension, such
as passed
Now that we've covered the syntax, let's look at
a couple of examples. The following example would match from
9:00 a.m. to 5:59 p.m., on
Monday through Friday, on
any day of the month, in
any month of the year:
exten => s,1,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)
If the caller calls during these hours, the call
will be sent to the first priority of the s extension in
the context named open. If the call is made outside of the
specified times, it will be sent to the next priority of the
current extension. This allows you to easily branch on multiple
times, as shown in the next example (note that you should always
put your most specific time matches before the least specific
ones):
; If it's any hour of the day, on any day of the week,
; during the fourth day of the month, in the month of of July,
; we're closed
exten => s,1,GotoIfTime(*,*,4,jul?open,s,1)
; During business hours, send calls to the open context
exten => s,2,GotoIfTime(09:00-17:59|mon-fri|*|*?open,s,1)
exten => s,3,GotoIfTime(09:00-11:59|sat|*|*?open,s,1)
; Otherwise, we're closed
exten => s,4,Goto(closed,s,1)
|