The dialplan we just built was static; it will always perform the same actions on every call. We are going to start adding some logic to our dialplan so that it will perform different actions based on input from the user. To do this, we’re going to need to introduce a few more applications.
One of the most important keys to building interactive Asterisk
dialplans is the Background()
[75] application. Like Playback()
, it plays a recorded sound
file. Unlike Playback()
, however, when the caller
presses a key (or series of keys) on her telephone keypad, it interrupts
the playback and goes to the extension that corresponds with the pressed
digit(s). If a caller presses 5, for example, Asterisk will stop playing
the sound prompt and send control of the call to the first priority of
extension 5.
The most common use of the Background()
application is to create voice menus (often called auto-attendants or phone
trees). Many companies use voice menus to direct callers to
the proper extensions, thus relieving their receptionists from having to
answer every single call.
Background()
has the same
syntax as Playback()
:
exten => 123,1,Answer() exten => 123,n,Background(main-menu)
In earlier versions of Asterisk, if the Background()
application finished playing the
sound prompt and there were no more priorities in the current extension,
Asterisk would sit and wait for input from the caller. Asterisk no
longer does this by default. If you want Asterisk to wait for input from
the caller after the sound prompt has finished playing, you can call the
WaitExten()
application. The WaitExten()
application waits for the caller
to enter DTMF digits, and is frequently called directly after the
Background()
application, like
this:
exten => 123,1,Answer() exten => 123,n,Background(main-menu) exten => 123,n,WaitExten()
If you’d like the WaitExten()
application to wait a specific number of seconds for a response (instead
of using the default timeout), simply pass the number of seconds as the
first argument to WaitExten()
, like
this:
exten => 123,n,WaitExten(5)
Both Background()
and WaitExten()
allow the caller to enter DTMF
digits. Asterisk then attempts to find an extension in the current
context that matches the digits that the caller entered. If Asterisk
finds an unambiguous match, it will send the call to that extension.
Let’s demonstrate by adding a few lines to our example:
exten => 123,1,Answer() exten => 123,n,Background(main-menu) exten => 123,n,WaitExten() exten => 2,1,Playback(digits/2) exten => 3,1,Playback(digits/3) exten => 4,1,Playback(digits/4)
If you call into extension 123 in the example above, it will play
a sound prompt that says “main menu.” It will then wait for you to enter
either 2
, 3
, or 4
. If
you press one of those digits, Asterisk will read that digit back to
you. You’ll also find that if you enter a different digit (such as
5
), it won’t give you what you
expected.
It is also possible that Asterisk will find an ambiguous match.
This can be easily explained if we add an extension named 1
to the previous example:
exten => 123,1,Answer() exten => 123,n,Background(main-menu) exten => 123,n,WaitExten() exten => 1,1,Playback(digits/1) exten => 2,1,Playback(digits/2) exten => 3,1,Playback(digits/3) exten => 4,1,Playback(digits/4)
Dial extension 123, and then at the main menu prompt dial 1
. Why doesn’t Asterisk immediately read back
the number one to you? It’s because the digit 1
is ambiguous; Asterisk doesn’t know whether
you’re trying to go to extension 1 or extension 123. It waits a few
seconds to see if you’re going to dial another digit (such as the
2
in extension 123). If you don’t
dial any more digits, Asterisk will eventually time out and send the
call to extension 1. (We’ll learn how to choose our own timeout values
in Chapter 6, More Dialplan Concepts.)
Before going on, let’s review what we’ve done so far. When users
call into our dialplan, they will hear a greeting. If they press
1
, they will hear the number one, and
if they press 2
, they will hear the
number two, and so on. While that’s a good start, let’s embellish it a
little. We’ll use the Goto()
application to make the dialplan repeat the greeting after playing back
the number.
As its name implies, the Goto()
application is used to send the call to another part of the dialplan.
The syntax for the Goto()
application
requires us to pass the destination context, extension, and priority on
as arguments to the application, like this:
exten => 123,n,Goto(context
,extension
,priority
)
Now, let’s use the Goto()
application in our dialplan:
[incoming] exten => 123,1,Answer() exten => 123,n,Background(main-menu) exten => 1,1,Playback(digits/1) exten => 1,n,Goto(incoming,123,1) exten => 2,1,Playback(digits/2) exten => 2,n,Goto(incoming,123,1)
These two new lines (highlighted in bold) will send control of the
call back to the 123
extension after
playing back the selected number.
If you look up the details of the Goto()
application, you’ll find that you can
actually pass either one, two, or three arguments to the application.
If you pass a single argument, Asterisk will assume it’s the
destination priority in the current extension. If you pass two
arguments, Asterisk will treat them as the extension and priority to
go to in the current context.
In this example, we’ve passed all three arguments for the sake of clarity, but passing just the extension and priority would have had the same effect.
Now that our first voice menu is starting to come together, let’s
add some additional special extensions. First, we need an extension for
invalid entries; when a caller presses an invalid entry (e.g., pressing
9 in the above example), the call is sent to the i
extension. Second, we need an extension to
handle situations when the caller doesn’t give input in time (the
default timeout is 10 seconds). Calls will be sent to the t
extension if the caller takes too long to
press a digit after WaitExten()
has
been called. Here is what our dialplan will look like after we’ve added
these two extensions:
[incoming]
exten => 123,1,Answer()
exten => 123,n,Background(enter-ext-of-person)
exten => 123,n,WaitExten()
exten => 1,1,Playback(digits/1)
exten => 1,n,Goto(incoming,123,1)
exten => 2,1,Playback(digits/2)
exten => 2,n,Goto(incoming,123,1)
exten => 3,1,Playback(digits/3)
exten => 3,n,Goto(incoming,123,1)
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(incoming,123,1)
exten => t,1,Playback(vm-goodbye)
exten => t,n,Hangup()
Using the i
and t
extensions makes our dialplan a little more
robust and user-friendly. That being said, it is still quite limited,
because outside callers have no way of connecting to a live person. To
do that, we’ll need to learn about another application, called Dial()
.
One of Asterisk’s most valuable features is its ability to connect
different callers to each other. This is especially useful when callers
are using different methods of communication. For example, caller A
might be communicating over the traditional analog telephone network,
while user B might be sitting in a café halfway around the world and
speaking on an IP telephone. Luckily, Asterisk takes most of the hard
work out of connecting and translating between disparate networks. All
you have to do is learn how to use the Dial()
application.
The syntax of the Dial()
application is a little more complex than that of the other applications
we’ve used so far, but don’t let that scare you off. Dial()
takes up to four arguments. The first
is the destination you’re attempting to call, which (in its simplest form) is made up of a technology
(or transport) across which to make the call, a forward slash, and the
remote endpoint or resource. Common technology types include Zap (for
analog and T1/E1/J1 channels), SIP, and IAX2. For example, let’s assume
that we want to call a Zap endpoint identified by Zap/1
, which is an FXS channel with an analog
phone plugged into it. The technology is Zap
, and the
resource is 1
. Similarly, a call to a SIP device (as
defined in sip.conf) might have a destination of
SIP/Jane
, and a call to an IAX device
(defined in iax.conf) might have a destination of
IAX2/Fred
. If we wanted Asterisk to
ring the Zap/1
channel when extension
123 is reached in the dialplan, we’d add the following extension:
exten => 123,1,Dial(Zap/1)
We can also dial multiple channels at the same time, by
concatenating the destinations with an ampersand (&
),
like this:
exten => 123,1,Dial(Zap/1&Zap/2&SIP/Jane)
The Dial()
application will
ring the specified destinations simultaneously, and bridge the inbound
call with whichever destination channel answers the call first. If the
Dial()
application can’t contact any
of the destinations, Asterisk will set a variable called DIALSTATUS
with the reason that it couldn’t dial the destinations, and
continue on with the next priority in the extension.[76]
The Dial()
application also
allows you to connect to a remote VoIP endpoint not previously defined
in one of the channel configuration files. The full syntax for this type
of connection is:
Dial(technology/user
[:password]
@remote_host
[:port]
[/remote_extension]
)
As an example, you can dial into a demonstration server at Digium using the IAX2 protocol by using the following extension:
exten => 500,1,Dial(IAX2/guest@misery.digium.com/s)
The full syntax for the Dial()
application is slightly different when dealing with Zap channels, as
shown:
Dial(Zap/[gGrR]
channel_or_group
[/remote_extension]
)
For example, here is how you would dial 1-800-555-1212
on Zap channel number 4.
exten => 501,1,Dial(Zap/4/18005551212)
The second argument to the Dial()
application is a timeout, specified in
seconds. If a timeout is given, Dial()
will attempt to call the destination(s)
for that number of seconds before giving up and moving on to the next
priority in the extension. If no timeout is specified, Dial()
will continue to dial the called
channel(s) until someone answers or the caller hangs up. Let’s add a
timeout of 10 seconds to our extension:
exten => 123,1,Dial(Zap/1,10)
If the call is answered before the timeout, the channels are
bridged and the dialplan is done. If the destination simply does not
answer, is busy, or is otherwise unavailable, Asterisk will set a
variable called DIALSTATUS
and then
continue on with the next priority in the extension.
Let’s put what we’ve learned so far into another example:
exten => 123,1,Dial(Zap/1,10)
exten => 123,n,Playback(vm-nobodyavail)
exten => 123,n,Hangup()
As you can see, this example will play the vm-nobodyavail.gsm sound file if the call goes unanswered.
The third argument to Dial()
is
an option string. It may contain one or more characters that modify the
behavior of the Dial()
application.
While the list of possible options is too long to cover here, one of the
most popular options is the m
option.
If you place the letter m
as the
third argument, the calling party will hear hold music instead of
ringing while the destination channel is being called (assuming, of
course, that music on hold has been configured correctly). To add the
m
option to our last example, we
simply change the first line:
exten => 123,1,Dial(Zap/1,10,m)
exten => 123,n,Playback(vm-nobodyavail)
exten => 123,n,Hangup()
Since the extensions numbered 1 and 2 in our dialplan are somewhat
useless now that we know how to use the Dial()
application, let’s replace them with
new extensions that will allow outside callers to reach John and
Jane:
[incoming]
exten => 123,1,Answer()
exten => 123,n,Background(enter-ext-of-person)
exten => 123,n,WaitExten()
exten => 1,1,Dial(Zap/1,10)
exten => 1,n,Playback(vm-nobodyavail)
exten => 1,n,Hangup()
exten => 2,1,Dial(SIP/Jane,10)
exten => 2,n,Playback(vm-nobodyavail)
exten => 2,n,Hangup()
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(incoming,123,1)
exten => t,1,Playback(vm-goodbye)
exten => t,n,Hangup()
The fourth and final argument to the Dial()
application is a URL. If the
destination channel supports receiving a URL at the time of the call,
the specified URL will be sent (for example, if you have an IP telephone
that supports receiving a URL, it will appear on the phone’s display;
likewise, if you’re using a soft phone, the URL might pop up on your
computer screen). This argument is very rarely used.
Note that the second, third, and fourth arguments may be left blank. For example, if you want to specify an option but not a timeout, simply leave the timeout argument blank, like this:
exten => 1,1,Dial(Zap/1,,m)
In our examples thus far, we have limited ourselves to a single context,
but it is probably fair to assume that almost all Asterisk installations
will have more than one context in their dialplans. As we mentioned at
the beginning of this chapter, one important function of contexts is to
separate privileges (such as making long-distance calls or calling
certain extensions) for different classes of callers. In our next
example, we’ll add to our dialplan by creating two internal phone
extensions, and we’ll set up the ability for these two extensions to
call each other. To accomplish this, we’ll create a new context called
[employees]
.
As in previous examples, we’ve assumed that an FXS analog
channel (Zap/1
, in this case) has
already been configured, and that your
zapata.conf file is configured so that any calls
originated by Zap/1
begin in the
[employees]
context. For a few
examples at the end of the chapter, we’ll also assume that an FXO Zap
channel has been configured as Zap/4
, with calls coming in on this channel
being sent to the [incoming]
context.
We’ve also assumed you have at least one SIP channel (named
SIP/Jane
) that is configured to
originate in the [employees]
context. We’ve done this to introduce you to using other types of
channels.
If you don’t have hardware for the channels listed above (such
as Zap/4
), or if you’re using
hardware with different channel names (e.g., not SIP/Jane
), just change the examples to match
your particular system configuration.
Our dialplan now looks like this:
[incoming]
exten => 123,1,Answer()
exten => 123,n,Background(enter-ext-of-person)
exten => 123,n,WaitExten()
exten => 1,1,Dial(Zap/1,10)
exten => 1,n,Playback(vm-nobodyavail)
exten => 1,n,Hangup()
exten => 2,1,Dial(SIP/Jane,10)
exten => 2,n,Playback(vm-nobodyavail)
exten => 2,n,Hangup()
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(incoming,123,1)
exten => t,1,Playback(vm-goodbye)
exten => t,n,Hangup()
[employees]
exten => 101,1,Dial(Zap/1)
exten => 102,1,Dial(SIP/Jane)
In this example, we have added two new extensions to the [employees]
context. This way, the person
using channel Zap/1
can pick up the
phone and dial the person at channel SIP/Jane
by dialing 102. By that same token,
the phone registered as SIP/Jane
can
dial Zap/1
by dialing 101.
We’ve arbitrarily decided to use extensions 101 and 102 for our examples, but feel free to use whatever numbering convention you wish for your extensions. You should also be aware that you’re not limited to three-digit extensions; you can use as few or as many digits as you like. (Well, almost. Extensions must be shorter than 80 characters long, and you shouldn’t use single-character extensions for your own use, as they’re reserved.) Don’t forget that you can use names as well, like so:
[incoming] exten => 123,1,Answer() exten => 123,n,Background(enter-ext-of-person) exten => 123,n,WaitExten() exten => 1,1,Dial(Zap/1,10) exten => 1,n,Playback(vm-nobodyavail) exten => 1,n,Hangup() exten => 2,1,Dial(SIP/Jane,10) exten => 2,n,Playback(vm-nobodyavail) exten => 2,n,Hangup() exten => i,1,Playback(pbx-invalid) exten => i,n,Goto(incoming,123,1) exten => t,1,Playback(vm-goodbye) exten => t,n,Hangup() [employees] exten => 101,1,Dial(Zap/1) exten => john,1,Dial(Zap/1) exten => 102,1,Dial(SIP/Jane) exten => jane,1,Dial(SIP/Jane)
It certainly wouldn’t hurt to add named extensions if you think
your users might be dialed via a VoIP protocol such as SIP that supports
dialing by name. You can also see that it is possible to have different
extensions in the dialplan ring the same endpoint. For example, you
could have extension 200 ring SIP/George
, and then
have extension 201 play a prompt of some kind and
then ring SIP/George
.
Now that our internal callers can call each other, we’re well on our way toward having a complete dialplan. Next, we’ll see how we can make our dialplan more scalable and easier to modify in the future.
Variables can be used in an Asterisk dialplan to help reduce typing, add clarity, or add additional logic to a dialplan. If you have some computer programming experience, you probably already understand what a variable is. If not, don’t worry; we’ll explain what variables are and how they are used.
You can think of a variable as a container that can hold one value
at a time. So, for example, we might create a variable called JOHN
and assign it the value of Zap/1
. This way, when we’re writing our
dialplan, we can refer to John’s channel by name, instead of remembering
that John is using the channel named Zap/1
.
There are two ways to reference a variable. To reference the
variable’s name, simply type the name of the variable, such as JOHN
. If, on the other hand, you want to
reference its value, you must type a dollar sign, an opening curly
brace, the name of the variable, and a closing curly brace. Here’s how we’d reference the
variable inside the Dial()
application:
exten => 555,1,Dial(${JOHN})
In our dialplan, whenever we write ${JOHN}
, Asterisk will automatically replace
it with whatever value has been assigned to the variable named JOHN
.
Note that variable names are case-sensitive. A variable named
JOHN
is different than a variable named
John
. For readability’s sake, all the variable
names in the examples will be written in uppercase. You should also be
aware that any variables set by Asterisk will be uppercase as well.
Some variables, such as CHANNEL
or
EXTEN
are reserved by Asterisk. You should not
attempt to set these variables.
There are three types of variables we can use in our dialplan: global variables, channel variables, and environment variables. Let’s take a moment to look at each type.
As their name implies, global
variables apply to all extensions in all contexts. Global
variables are useful in that they can be used anywhere within a
dialplan to increase readability and manageability. Suppose for a
moment that you had a large dialplan and several hundred references to
the Zap/1
channel. Now imagine you
had to go through your dialplan and change all of those references to
Zap/2
. It would be a long and
error-prone process, to say the least.
On the other hand, if you had defined a global variable with the
value Zap/1
at the beginning of
your dialplan and then referenced that instead, you would have to
change only one line.
Global variables should be declared in the [globals]
context at the beginning of the
extensions.conf file. They can also be defined
programmatically, using the GLOBAL()
dialplan function.[77] Here is an example of how both methods look inside of a
dialplan. The first shows the setting of a global variable named
JOHN
with a value of Zap/1
. This variable is set at the time
Asterisk parses the dialplan. The second example shows how a global
variable can be set in the dialplan. In this case, the variable named
George
is being assigned the value
of SIP/George
when extension 124 is
dialed in the [employees]
context:
[globals] JOHN=Zap/1 [employees] exten => 124,1,Set(GLOBAL(GEORGE)=SIP/George)
A channel variable is a variable that is associated only with a particular call. Unlike global variables, channel variables are defined only for the duration of the current call and are available only to the channels participating in that call.
There are many predefined channel variables available for use
within the dialplan, which are explained in the
channelvariables.txt file in the
doc subdirectory of the Asterisk source. Channel
variables are set via the Set()
application:
exten => 125,1,Set(MAGICNUMBER=42)
We’ll cover many uses for channel variables in Chapter 6, More Dialplan Concepts.
Environment variables are a way of accessing Unix environment variables from within
Asterisk. These are referenced using the ENV()
dialplan function. The syntax looks like ${ENV(
var
)}
, where var
is
the Unix environment variable you wish to reference. Environment
variables aren’t commonly used in Asterisk dialplans, but they are
available should you need them.
Now that we’ve learned about variables, let’s put them to work in our dialplan. We’ll add global variables for two people, John and Jane:
[globals] JOHN=Zap/1 JANE=SIP/Jane [incoming] exten => 123,1,Answer() exten => 123,n,Background(enter-ext-of-person) exten => 123,n,WaitExten() exten => 1,1,Dial(${JOHN},10) exten => 1,n,Playback(vm-nobodyavail) exten => 1,n,Hangup() exten => 2,1,Dial(${JANE},10) exten => 2,n,Playback(vm-nobodyavail) exten => 2,n,Hangup() exten => i,1,Playback(pbx-invalid) exten => i,n,Goto(incoming,123,1) exten => t,1,Playback(vm-goodbye) exten => t,n,Hangup() [employees] exten => 101,1,Dial(${JOHN}) exten => john,1,Dial(${JOHN}) exten => 102,1,Dial(${JANE}) exten => jane,1,Dial(${JANE})
If we want to be able to allow people to dial through Asterisk and have Asterisk connect the caller to an outside resource, we need a way to match on any possible phone number that the caller might dial. Can you imagine how tedious it would be to manually write a dialplan with an extension for every possible number you could dial? Luckily, Asterisk has just the thing for situations like this: pattern matching. Pattern matching allows you to create one extension in your dialplan that matches many different numbers.
When using pattern matching, certain letters and symbols represent what we are trying to
match. Patterns always start with an underscore (_
). This
tells Asterisk that we’re matching on a pattern, and not on an
explicit extension name. (This means, of course, that you should never
start your extension names with an underscore.)
If you forget the underscore on the front of your pattern, Asterisk will think it’s just a named extension and won’t do any pattern matching. This is one of the most common mistakes people make when starting to learn Asterisk.
After the underscore, you can use one or more of the following characters.
X
Z
N
[15-7]
Matches a single digit from the range of digits specified. In this case, the pattern matches a single 1, 5, 6, or 7.
.
(period)Wildcard match; matches one or more characters, no matter what they are.
If you’re not careful, wildcard matches can make your
dialplans do things you’re not expecting (like matching
built-in extensions such as i
or
h
). You should use the wildcard match in a
pattern only after you’ve matched as many other digits as
possible. For example, the following pattern match should
probably never be used:
_.
In fact, Asterisk will warn you if you try to use it. Instead, use this one, if at all possible:
_X.
Wildcard match; matches zero or more characters, no matter what they are.
To use pattern matching in your dialplan, simply put the pattern in the place of the extension name (or number):
exten => _NXX,1,Playback(auth-thankyou)
In this example, the pattern matches any three-digit extension
from 200 through 999 (the N
matches
any digit between 2 and 9, and each X
matches a digit between 0 and 9). That is
to say, if a caller dialed any three-digit extension between 200 and
999 in this context, he would hear the sound file
auth-thankyou.gsm.
One other important thing to know about pattern matching is that
if Asterisk finds more than one pattern that matches the dialed
extension, it will use the most specific one
(going from left to right). Say you had defined the following two
patterns, and a caller dialed 555-1212
:
exten => _555XXXX,1,Playback(digits/1) exten => _55512XX,1,Playback(digits/2)
In this case the second extension would be selected, because it is more specific.
Before we go on, let’s look at a few more pattern-matching examples. In each one, see if you can tell what the pattern would match before reading the explanation. We’ll start with an easy one:
_NXXXXXX
This pattern would match any seven-digit number, as long as the first digit was two or higher. This pattern would be compatible with any North American Numbering Plan local seven-digit number. In areas with 10-digit dialing, that pattern would look like this:
_NXXNXXXXXX
Note that neither of these two patterns would handle long distance calls. We’ll cover those shortly.
Let’s try another:
_1NXXNXXXXXX
This one is slightly more difficult. This would match the number 1, followed by an area code between 200 and 999, then any 7-digit number. In the NANP calling area, you would use this pattern to match any long-distance number.[78]
Now for an even trickier example:
_011.
If that one left you scratching your head, look at it again. Did you notice the period on the end? This pattern matches any number that starts with 011 and has at least one more digit. In the NANP, this indicates an international phone number. (We’ll be using these patterns in the next section to add outbound dialing capabilities to our dialplan.)
We know what you’re thinking… You’re sitting there asking yourself, “So what happens if I want to use
pattern matching, but I need to know which digits were actually
dialed?” Luckily, Asterisk has just the answer. Whenever you dial an
extension, Asterisk sets the ${EXTEN}
channel variable to the digits that
were dialed. We can use an application called SayDigits()
to test it out:
exten => _XXX,1,SayDigits(${EXTEN})
In this example, the SayDigits()
application will read back to you the three-digit extension you
dialed.
Often, it’s useful to manipulate the ${EXTEN}
by stripping a certain number of
digits off the front of the extension. This is accomplished by using
the syntax ${EXTEN:
x
}
, where x
is
where you want the returned string to start, from left to right. For
example, if the value of EXTEN
is
95551212, ${EXTEN:1}
equals
5551212. Let’s take a look at another example:
exten => _XXX,1,SayDigits(${EXTEN:1})
In this example, the SayDigits()
application would start at the
second digit, and thus read back only the last two digits of the
dialed extension.
Now that we’ve introduced pattern matching, we can go about the process of allowing users to make
outbound calls. The first thing we’ll do is add a variable to the
[globals]
context to define
which channel will be used for outbound calls:
[globals]
JOHN=Zap/1
JANE=SIP/Jane
OUTBOUNDTRUNK=Zap/4
Next, we will add contexts to our dialplan for outbound dialing.
You may be asking yourself at this point, “Why do we need separate contexts for outbound calls?” This is so that we can regulate and control which callers have permission to make outbound calls, and which types of outbound calls they are allowed to make.
To begin, let’s create a context for local calls. To be consistent
with most traditional phone switches, we’ll put a 9
on the front of our patterns, so that users
have to dial 9 before calling an outside number:
[outbound-local] exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1}) exten => _9NXXXXXX,n,Congestion() exten => _9NXXXXXX,n,Hangup()
Note that dialing 9 doesn’t actually give you an outside line, unlike with many traditional PBX systems. Once you dial 9 on an analog line, the dial tone will stop. If you’d like the dial tone to continue even after dialing 9, add the following line (right after your context definition):
ignorepat => 9
This directive tells Asterisk to continue to provide a dial tone on an analog line, even after the caller has dialed the indicated pattern. This will not work with VoIP telephones, as they usually don’t send digits to the system as they are input; they are sent to Asterisk all at once. Luckily, most of the popular VoIP telephones can be configured to emulate the same functionality.
Let’s review what we’ve just done. We’ve added a global variable
called OUTBOUNDTRUNK
, which simply
defines the channel we are using for outbound calls.[79] We’ve also added a context for local outbound calls. In
priority 1, we take the dialed extension, strip off the 9 with the
${EXTEN:1}
syntax, and then attempt
to dial that number on the channel signified by the variable OUTBOUNDTRUNK
. If the call is successful, the
caller is bridged with the outbound channel. If the call is unsuccessful
(because either the channel is busy or the number can’t be dialed for
some reason), the Congestion()
application is called, which plays a “fast busy signal” (congestion
tone) to let the caller know that the call was unsuccessful.
Before we go any further, let’s make sure our dialplan allows outbound emergency numbers:
[outbound-local]
exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
exten => _9NXXXXXX,n,Congestion()
exten => _9NXXXXXX,n,Hangup()
exten => 911,1,Dial(${OUTBOUNDTRUNK}/911)
exten => 9911,1,Dial(${OUTBOUNDTRUNK}/911) ; So that folks who dial “9”
; first will also get through
Again, we’re assuming for the sake of these examples that we’re inside the United States or Canada. If you’re outside of this area, please replace 911 with the emergency services number in your particular location. This is something you never want to forget to put in your dialplan!
Next, let’s add a context for long-distance calls:
[outbound-long-distance] exten => _91NXXNXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1}) exten => _91NXXNXXXXXX,n,Playtones(congestion) exten => _91NXXNXXXXXX,n,Hangup()
Now that we have these two new contexts, how do we allow internal users to take advantage of them? We need a way for contexts to be able to use the functionality contained in other contexts.
Asterisk has a feature that enables us to use the extensions from
one context within another context via the include
directive. This is used to control
access to different sections of the dialplan. We’ll use the include
functionality to allow users in our [employees]
context the ability to make
outbound phone calls. But first, let’s cover the syntax.
The include
statement takes the
following form, where context
is the name of
the remote context we want to include in the current context:
include => context
When we include other contexts within our current context, we have to be mindful of the order in which we are including them. Asterisk will first try to match the dialed extension in the current context. If unsuccessful, it will then try the first included context (including any contexts included in that context), and then continue to the other included contexts in the order in which they were included.
As it sits, our current dialplan has two contexts for outbound
calls, but there’s no way for people in the [employees]
context to use them. Let’s remedy
that by including the two outbound contexts in the [employees]
context, like this:
[globals]
JOHN=Zap/1
JANE=SIP/Jane
OUTBOUNDTRUNK=Zap/4
[incoming]
exten => 123,1,Answer()
exten => 123,n,Background(enter-ext-of-person)
exten => 123,n,WaitExten()
exten => 1,1,Dial(${JOHN},10)
exten => 1,n,Playback(vm-nobodyavail)
exten => 1,n,Hangup()
exten => 2,1,Dial(${JANE},10)
exten => 2,n,Playback(vm-nobodyavail)
exten => 2,n,Hangup()
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(incoming,123,1)
exten => t,1,Playback(vm-goodbye)
exten => t,n,Hangup()
[employees]
include => outbound-local
include => outbound-long-distance
exten => 101,1,Dial(${JOHN})
exten => john,1,Dial(${JOHN})
exten => 102,1,Dial(${JANE})
exten => jane,1,Dial(${JANE})
[outbound-local]
exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
exten => _9NXXXXXX,n,Congestion()
exten => _9NXXXXXX,n,Hangup()
exten => 911,1,Dial(${OUTBOUNDTRUNK}/911)
exten => 9911,1,Dial(${OUTBOUNDTRUNK}/911)
[outbound-long-distance]
exten => _91NXXNXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
exten => _91NXXNXXXXXX,n,Playtones(congestion)
exten => _91NXXNXXXXXX,n,Hangup()
These two include
statements
make it possible for callers in the [employees]
context to make outbound calls. We
should also note that for security’s sake you should always make sure
that your [inbound]
context never
allows outbound dialing. (If by chance it did, people could dial into
your system and then make outbound toll calls that would be charged to
you!)
[75] It should be noted that some people expect that Background()
, due to its name, would
continue in the dialplan while the sound is being played, but its
name refers to the fact that it is playing a sound in the
background, while waiting for DTMF in the foreground.
[76] Don’t worry, we’ll cover variables (in the section called “Using Variables””) and show you how to have your
dialplan make decisions based on the value of this DIALSTATUS
variable.
[77] Don’t worry! We’ll cover dialplan functions in the the section called “Dialplan Functions”” section.
[78] If you grew up in North America, you may believe that the 1 you dial before a long distance call is “the long distance code.” This is incorrect. The number 1 is in fact the international country code for all countries in NANP. Keep this in mind if you ever send your phone number to someone in another country. They may not know what your country code is, and thus be unable to call you with just your area code and phone number. Your full phone number with country code should be printed as +1 NPA NXX XXXX (where NPA is your area code)―e.g., +1 416 555 1212.
[79] The advantage of this is that if one day we decide to send all
of our calls through some other channel, we have to edit the channel
name assigned to the variable OUTBOUNDTRUNK
only in the [globals]
context, instead of having to
manually edit every reference to the channel in our dialplan.