The dialplan is the heart of your Asterisk system. It defines how calls flow into and out of the system. A form of scripting language, the dialplan contains instructions that Asterisk follows in response to external triggers. In contrast to traditional phone systems, Asterisk’s dialplan is fully customizable.
This chapter introduces the essential concepts of the dialplan. The information presented here is critical to your understanding of dialplan code and will form the basis of any dialplan you write. The examples have been designed to build upon one another, and we recommend that you do not skip too much of this chapter, since it is so fundamentally important to Asterisk. Please also note that this chapter is by no means an exhaustive survey of all the possible things dialplans can do; our aim is to cover just the essentials. We’ll cover more advanced dialplan topics in later chapters. You are encouraged to experiment.
The Asterisk dialplan is specified in the configuration file named extensions.conf.
The extensions.conf file usually resides in the /etc/asterisk/ directory, but its location may vary depending on how you installed Asterisk. Other common locations for this file include /usr/local/etc/asterisk/ and /opt/etc/asterisk/.
The dialplan is made up of four main concepts: contexts, extensions, priorities, and applications. After explaining the role each of these elements plays in the dialplan, we’ll have you build a basic but functioning dialplan.
Dialplans are broken into sections called contexts. Contexts keep different parts of the dialplan from interacting with one another. An extension that is defined in one context is completely isolated from extensions in any other context, unless interaction is specifically allowed. (We’ll cover how to allow interaction between contexts near the end of the chapter. See Includes for more information.)
As a simple example, let’s imagine
we have two companies sharing an Asterisk server. If we place each
company’s automated attendant in its own context, they will be
completely separated from each other. This allows us to independently
define what happens when, say, extension 0 is dialed: Callers dialing
0
from Company A’s voice menu will
get Company A’s receptionist, while callers dialing 0
at Company B’s voice menu will get Company
B’s receptionist. (This assumes, of course, that we’ve told Asterisk
to transfer the calls to the receptionists when callers press 0
.[54])
Contexts are defined by placing the
name of the context inside square brackets ([]
). The name can be made up of the letters A through Z
(upper- and lowercase), the numbers 0 through 9, and the hyphen and
underscore.[55] A context for incoming calls might look like
this:
[incoming]
All of the instructions placed
after a context definition are part of that context, until the next
context is defined. At the beginning of the dialplan, there are two
special contexts named [general]
and [globals]
. The [general]
section contains a list of general dialplan settings (which you’ll
probably never have to worry about), and we will discuss the [globals]
context in the section Global variables. For now, it’s just
important to know that these two labels are not really contexts. Avoid
the use of [general]
, [default]
, and [globals]
as context names, but otherwise
name your contexts anything you wish.
When you define a channel (which is not done in the extensions.conf file, but rather in files
such as sip.conf, iax.conf, chan_dahdi.conf, etc.), one of the required
parameters in each channel definition is context
.
The context is the point in the dialplan where connections
from that channel will begin. The context setting for the
channel is how you plug the channel into the dialplan. Figure 6-1 illustrates the relationship
between channel configuration files and contexts in the
dialplan.
This is one of the most important concepts to understand when dealing with channels and dialplans. Once you understand the relationship of the context definition in a channel to the matching context in the dialplan, you will find it much easier to troubleshoot the call flow through an Asterisk system.
An important use of contexts (perhaps the most important use) is to provide security. By using contexts correctly, you can give certain callers access to features (such as long-distance calling) that aren’t made available to others. If you do not design your dialplan carefully, you may inadvertently allow others to fraudulently use your system. Please keep this in mind as you build your Asterisk system; there are many bots on the Internet that were specifically written to identify and exploit poorly secured Asterisk systems.
The Asterisk wiki at https://wiki.asterisk.org/wiki/display/AST/Important+Security+Considerations outlines several steps you should take to keep your Asterisk system secure. (Chapter 26 in this book also deals with security.) It is vitally important that you read and understand this page. If you ignore the security precautions outlined there, you may end up allowing anyone and everyone to make long-distance or toll calls at your expense!
If you don’t take the security of your Asterisk system seriously, you may end up paying—literally. Please take the time and effort to secure your system from toll fraud.
In the world of telecommunications, the word extension usually refers to a numeric identifier that, when dialed, will ring a phone (or system resource such as voicemail or a queue). In Asterisk, an extension is far more powerful, as it defines the unique series of steps (each step containing an application) through which Asterisk will take that call.
Within each context, we can define as many (or few) extensions as required. When a particular extension is triggered (by an incoming call or by digits being dialed on a channel), Asterisk will follow the steps defined for that extension. It is the extensions, therefore, that specify what happens to calls as they make their way through the dialplan. Although extensions can, of course, be used to specify phone extensions in the traditional sense (i.e., extension 153 will cause the SIP telephone set on John’s desk to ring), in an Asterisk dialplan, they can be used for much more.
The syntax for an extension is the
word exten
, followed by an arrow
formed by the equals sign and the greater-than sign, like this:
exten =>
This is followed by the name (or number) of the extension. When dealing with traditional telephone systems, we tend to think of extensions as the numbers you would dial to make another phone ring. In Asterisk, you get a whole lot more; for example, extension names can be any combination of numbers and letters. Over the course of this chapter and the next, we’ll use both numeric and alphanumeric extensions.
Assigning names to extensions may seem like a revolutionary concept, but when you realize that many VoIP transports support (or even actively encourage) dialing by name or email address rather than just by number, it makes perfect sense. This is one of the features that makes Asterisk so flexible and powerful.
Each step in an extension is composed of three components:
These three components are separated by commas, like this:
exten =>name
,priority
,application()
Here’s a simple example of what a real extension might look like:
exten => 123,1,Answer()
In this example, the extension name
is 123
, the priority is 1
, and the application is Answer()
.
Each extension can have multiple steps, called priorities. The priorities are numbered sequentially, starting with 1, and each executes one specific application. As an example, the following extension would answer the phone (in priority number 1), and then hang it up (in priority number 2):
exten => 123,1,Answer() exten => 123,2,Hangup()
It’s pretty obvious that this code doesn’t really do anything useful. We’ll get there. The key point to note here is that for a particular extension, Asterisk follows the priorities in order. This style of dialplan syntax is still seen from time to time, although (as you’ll see momentarily) it is not generally used anymore for new code:
exten => 123,1,Answer() exten => 123,2,do something
exten => 123,3,do something else
exten => 123,4,do one last thing
exten => 123,5,Hangup()
In older releases of Asterisk, the numbering of priorities caused a lot of problems. Imagine having an extension that had 15 priorities, and then needing to add something at step 2: all of the subsequent priorities would have to be manually renumbered. Asterisk does not handle missing steps or misnumbered priorities, and debugging these types of errors was pointless and frustrating.
Beginning with version 1.2,
Asterisk addressed this problem: it introduced the use of the
n
priority, which stands for
“next.” Each time Asterisk encounters a priority named n
, it takes the number of the previous
priority and adds 1. This makes it easier to make changes to your
dialplan, as you don’t have to keep renumbering all your steps. For
example, your dialplan might look something like this:
exten => 123,1,Answer() exten => 123,n,do something
exten => 123,n,do something else
exten => 123,n,do one last thing
exten => 123,n,Hangup()
Internally, Asterisk will
calculate the next priority number every time it encounters an
n
.[56] Bear in mind that you must always specify priority
number 1. If you accidentally put an n
instead of 1
for the first priority (a common mistake
even among experienced dialplan coders), you’ll find after reloading
the dialplan that the extension will not exist.
In the never-ending effort to simplify coding effort,
a new construct was created to make extension building and
management even easier. As long as the extension remains the same,
rather than having to type the full extension on each line, you can
simply type same =>
, followed
by the priority and application:
exten => 123,1,Answer() same => n,do something
same => n,do something else
same => n,do one last thing
same => n,Hangup()
The indentation is not required, but it may make for easier reading. This style of dialplan will also make it easier to copy code from one extension to another. We prefer this style ourselves, and highly recommend it.
Priority labels allow you to assign a name to a priority within an extension. This is to ensure that you can refer to a priority by something other than its number (which probably isn’t known, given that dialplans now generally use unnumbered priorities). The reason it is important to be able to address a particular priority in an extension is that you will often want to send calls from other parts of the dialplan to a particular priority in a particular extension. We’ll talk about that more later. To assign a text label to a priority, simply add the label inside parentheses after the priority, like this:
exten => 123,n(label
),application()
Later, we’ll cover how to jump between different priorities based on dialplan logic. You’ll see a lot more of priority labels, and you’ll use them often in your dialplans.
Applications are the workhorses of the dialplan. Each
application performs a specific action on the current channel, such as
playing a sound, accepting touch-tone input, looking something up in a
database, dialing a channel, hanging up the call, and so forth. In the
previous example, you were introduced to two simple applications:
Answer()
and Hangup()
. You’ll learn more about how these work
momentarily.
Some applications, including
Answer()
and Hangup()
, need no other instructions to do
their jobs. Most applications, however, require additional
information. These additional elements, or
arguments, are passed on to the applications to
affect how they perform their actions. To pass arguments to an
application, place them between the parentheses that follow the
application name, separated by commas.
Occasionally, you may also see
the pipe character (|
) being used as a separator between arguments, instead
of a comma. Starting in Asterisk 1.6.0, support for the pipe as a
separator character has been removed.[57]
The Answer()
application is used to answer a channel that is ringing. This does the
initial setup for the channel that receives the incoming call. As we
mentioned earlier, Answer()
takes
no arguments. Answer()
is not
always required (in fact, in some cases it may not be desirable at
all), but it is an effective way to ensure a channel is connected
before performing further actions.
The Playback()
application is used for playing a previously recorded
sound file over a channel. Input from the user is ignored, which means
that you would not use Playback()
in an auto attendant, for example, unless you did not want to accept
input at that point.[58]
Asterisk comes with many professionally recorded sound files, which should be found in the default sounds directory (usually /var/lib/asterisk/sounds/). When you compile Asterisk, you can choose to install various sets of sample sounds that have been recorded in a variety of languages and file formats. We’ll be using these files in many of our examples. Several of the files in our examples come from the Extra Sound Package, so please take the time to install it (see Chapter 3). You can also have your own sound prompts recorded in the same voices as the stock prompts by visiting http://www.theivrvoice.com/. Later in the book we’ll talk more about how you can use a telephone and the dialplan to create and manage your own system recordings.
To use Playback()
, specify a filename (without a
file extension) as the argument. For example, Playback(filename)
would play the sound file
called filename.wav, assuming it
was located in the default sounds directory. Note that you can include
the full path to the file if you want, like this:
Playback(/home/john/sounds/filename)
The previous example would play filename.wav from the /home/john/sounds/ directory. You can also use relative paths from the Asterisk sounds directory, as follows:
Playback(custom/filename)
This example would play filename.wav from the custom/ subdirectory of the default sounds directory (probably /var/lib/asterisk/sounds/custom/filename.wav). Note that if the specified directory contains more than one file with that filename but with different file extensions, Asterisk automatically plays the best file.[59]
The Hangup()
application does exactly as its name implies: it hangs
up the active channel. You should use this application at the end of a
context when you want to end the current call, to ensure that callers
don’t continue on in the dialplan in a way you might not have
anticipated. The Hangup()
application does not require any arguments, but you can pass an ISDN
cause code if you want (e.g., Hangup(16)
).
As we work through the book, we will be introducing you to many more Asterisk applications.
OK, enough theory. Open up the file /etc/asterisk/extensions.conf, and let’s take a look at your first dialplan (which was created in Chapter 5). We’re going to add to that.
As is typical in many technology books (especially computer programming books), our first example is called “Hello World!”
In the first priority of our extension, we answer the call. In the second, we play a sound file named hello-world, and in the third we hang up the call. The code we are interested in for this example looks like this:
exten => 200,1,Answer() same => n,Playback(hello-world) same => n,Hangup()
If you followed along in Chapter 5, you’ll already have a channel or two configured, as well as the sample dialplan that contains this code. If not, what you need is an extensions.conf file in your /etc/asterisk/ directory that contains the following code:
[LocalSets] ; this is the context name exten => 100,1,Dial(SIP/0000FFFF0001) ; Replace 0000FFFF0001 with your device name exten => 101,1,Dial(SIP/0000FFFF0002) ; Replace 0000FFFF0002 with your device name exten => 200,1,Answer() same => n,Playback(hello-world) same => n,Hangup()
If you don’t have any channels configured, now is the time to do so. There is real satisfaction that comes from passing your first call into an Asterisk dialplan on a system that you’ve built from scratch. People get this funny grin on their faces as they realize that they have just created a telephone system. This pleasure can be yours as well, so please, don’t go any further until you have made this little bit of dialplan work. If you have any problems, get back to Chapter 5 and work through the examples there.
If you don’t have this dialplan code built yet, you’ll need to add it and reload the dialplan with this CLI command:
*CLI>
dialplan reload
$
sudo /usr/sbin/asterisk -rx "dialplan reload"
Calling extension 200 from either of your configured phones should reward you with the voice of Allison Smith saying “Hello World.”
If it doesn’t work, check the
Asterisk console for error messages, and make sure your channels are
assigned to the LocalSets
context.
We do not recommend that you move forward in this book until you have verified the following:
Even though this example is very short and simple, it emphasizes the core concepts of contexts, extensions, priorities, and applications. You now have the fundamental knowledge on which all dialplans are built.
The dialplan we just built was static; it will always perform the same actions on every call. Many dialplans will also need logic to perform different actions based on input from the user, so let’s take a look at that now.
As its name implies, the Goto()
application is used to send a 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:
same => n,Goto(context
,extension
,priority
)
We’re going to create a new context
called TestMenu
, and create an
extension in our LocalSets
context
that will pass calls to that context using Goto():
exten => 201,1,Goto(TestMenu,start,1) ; add this to the end of the ; [LocalSets] context [TestMenu] exten => start,1,Answer()
Now, whenever a device enters the LocalSets
context and dials 201
, the call will be passed to the start
extension in the TestMenu
context (which currently won’t do
anything interesting because we still have more code to write).
We used the extension start
in this example, but we could have
used anything we wanted as an extension name, either numeric or
alpha. We prefer to use alpha characters for extensions that are
not directly dialable, as this makes the dialplan easier to read.
Point being, we could have used 123
or xyz123
, or 99luftballons
, or whatever we wanted
instead of start
. The word
“start” doesn’t actually mean anything to the dialplan; it’s just
another extension.
One of the most useful applications
in an interactive Asterisk dialplan is the Background()
[60] 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 passes the call 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
(assuming there is an
extension 5
to send the call
to).
The most common use of the Background()
application is to create voice
menus (often called auto attendants[61] 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()
:
[TestMenu] exten => start,1,Answer() same => n,Background(main-menu)
If you want Asterisk to wait for
input from the caller after the sound prompt has finished playing, you
can use WaitExten()
. The WaitExten()
application waits for the caller to enter DTMF digits and is used
directly following the Background()
application, like this:
[TestMenu] exten => start,1,Answer() same => n,Background(main-menu) same => 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[62]), simply pass the number of seconds as the first
argument to WaitExten()
, like
this:
same => n,WaitExten(5) ; We recommend always passing a time argument to WaitExten()
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 a match, it will send the call to that extension. Let’s
demonstrate by adding a few lines to our dialplan example:
[TestMenu] exten => start,1,Answer() same => n,Background(main-menu) same => n,WaitExten(5) exten => 1,1,Playback(digits/1) exten => 2,1,Playback(digits/2)
After making these changes, save and reload your dialplan:
*CLI> dialplan reload
If you call into extension 201
, you should hear a sound prompt that
says “main menu.” The system will then wait 5 seconds for you to enter
a digit. If the digit you press is either 1
or 2
,
Asterisk will match the relevant extension, and read that digit back
to you. Since we didn’t provide any further instructions, your call
will then end. You’ll also find that if you enter a different digit
(such as 3
), the dialplan will be
unable to proceed.
Let’s embellish things a little.
We’re going to use the Goto()
application to have the dialplan repeat the greeting after playing
back the number:
[TestMenu] exten => start,1,Answer() same => n,Background(main-menu) same => n,WaitExten(5) exten => 1,1,Playback(digits/1) same => n,Goto(TestMenu,start,1) exten => 2,1,Playback(digits/2) same => n,Goto(TestMenu,start,1)
These new lines will send control
of the call back to the start
extension after playing back the selected number. This is generally
considered friendlier than just hanging up.
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 the
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, since the destination context is the same as the source context.
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. In
Asterisk, when a context receives a request for an extension that is
not valid within that context (e.g., pressing 9
in the preceding example), the call is
sent to the i
extension. We also
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:
[TestMenu]
exten => start,1,Answer()
same => n,Background(main-menu)
same => n,WaitExten(5)
exten => 1,1,Playback(digits/1)
same => n,Goto(TestMenu,start,1)
exten => 2,1,Playback(digits/2)
same => n,Goto(TestMenu,start,1)
exten => i,1,Playback(pbx-invalid)
same => n,Goto(TestMenu,start,1)
exten => t,1,Playback(vm-goodbye)
same => n,Hangup()
Using the i
and t
extensions makes our menu a little more robust and user-friendly. That
being said, it is still quite limited, because outside callers still
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 much 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 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, which we’ll look at next.
The first argument 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 address of the remote endpoint or resource. Common technology types include DAHDI (for analog and T1/E1/J1 channels), SIP, and IAX2.
For example, let’s assume that
we want to call a DAHDI endpoint identified by DAHDI/1
, which is an FXS channel with an
analog phone plugged into it. The technology is DAHDI
, and the resource (or channel
identifier) is 1
. Similarly, a
call to a SIP device (as defined in sip.conf) might have a destination of
SIP/0004F2001122
, and a call to
an IAX device (defined in iax.conf) might have a destination of
IAX2/Softphone
.[63] If we wanted Asterisk to ring the DAHDI/1
channel when extension 105
is reached in the dialplan, we’d add
the following extension:
exten => 105,1,Dial(DAHDI/1)
We can also dial multiple
channels at the same time, by concatenating the destinations with an
ampersand (&
), like
this:
exten => 105,1,Dial(DAHDI/1&SIP/0004F2001122&IAX2/Softphone)
The Dial()
application will ring all of the
specified destinations simultaneously, and bridge the inbound call
with whichever destination channel answers first (the other channels
will immediately stop ringing). 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.[64]
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 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/[email protected]/s)
The full syntax for the Dial()
application is slightly different
for DAHDI channels:
Dial(DAHDI/[gGrR]
channel_or_group
[/remote_extension]
)
For example, here is how you
would dial 1-800-555-1212
on
DAHDI channel number
4[65]:
exten => 501,1,Dial(DAHDI/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 specified
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 => 201,1,Dial(DAHDI/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 => 201,1,Dial(DAHDI/1,10)
same => n,Playback(vm-nobodyavail)
same => 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
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 => 201,1,Dial(DAHDI/1,10,m)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
The fourth and final argument to the Dial()
application is a URI. If the
destination channel supports receiving a URI at the time of the
call, the specified URI will be sent (for example, if you have an IP
telephone that supports receiving a URI, it will appear on the
phone’s display; likewise, if you’re using a softphone, the URI
might pop up on your computer screen). This argument is very rarely
used.
Few (if any) phones support URI information being passed to them. If you’re looking for something like a screen pop, you might want to check out Chapter 18, and more specifically the section on Jabber in Using XMPP (Jabber) with Asterisk.
Let’s modify extensions 1
and 2
in our menu to use the Dial()
application:
[TestMenu] exten => start,1,Answer() same => n,Background(main-menu) same => n,WaitExten(5) exten => 1,1,Dial(SIP/0000FFFF0001,10) ; Replace 0000FFFF0001 with your device name same => n,Playback(vm-nobodyavail) same => n,Hangup() exten => 2,1,Dial(SIP/0000FFFF0002,10) ; Replace 0000FFFF0002 with your device name same => n,Playback(vm-nobodyavail) same => n,Hangup() exten => i,1,Playback(pbx-invalid) same => n,Goto(TestMenu,start,1) exten => t,1,Playback(vm-goodbye) same => n,Hangup()
Variables can be used in an Asterisk dialplan to help reduce typing, improve clarity, or add logic. If you have some computer programming experience, you already understand what a variable is. If not, we’ll briefly explain what variables are and how they are used. They are a vitally important Asterisk dialplan concept (and something you will not find in the dialplan of any proprietary PBX).
A variable is
a named container that can hold a value. The advantage of a variable
is that its contents may change, but its name does not, which means
you can write code that references the variable name and not worry
about what the value will be. So, for example, we might create a
variable called JOHN
and assign it
the value of DAHDI/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
DAHDI/1
. If at some point we change
John’s channel to something else, we don’t have to change any of our
code that references the JOHN
variable; we only have to change the value assigned to the
variable.
There are two ways to reference
a variable. To reference the variable’s name, simply
type the name of the variable, such as LEIF
. If, on the other hand, you want to
reference the contents of the value, you must type a dollar sign, an
opening curly brace, the name of the variable, and a closing curly
brace (in the case of LEIF
, we
would reference the value of the variable with ${LEIF}
). Here’s how we might use a variable
inside the Dial()
application:
exten => 301,1,Set(LEIF=SIP/0000FFFF0001) same => n,Dial(${LEIF})
In our dialplan, whenever we refer
to ${LEIF}
, Asterisk will
automatically replace it with whatever value has been assigned to the
variable named LEIF
.
Note that variable names are case-sensitive. A variable named
LEIF
is different than a variable
named Leif
. For readability’s
sake, all our variable names in the examples will be written in
uppercase. You should also be aware that any variables set by
Asterisk will be uppercase. Some variables, such as CHANNEL
and EXTEN
, are reserved by Asterisk. You
should not attempt to set these variables. It is popular to write
global variables in uppercase and channel variables in Pascal/Camel
case.
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 are visible to all channels at all times. 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
SIP/0000FFFF0001
channel. Now
imagine you had to go through your dialplan and change all of those
references to SIP/0000FFFF0002
.
It would be a long and error-prone process, to say the least.
On the other hand, if you had
defined a global variable that contained the value SIP/0000FFFF0001
at the beginning of your
dialplan and then referenced that instead, you would have to change
only one line of code to affect all places in the dialplan where
that channel was used.
Global variables should be
declared in the [globals]
context
at the beginning of the extensions.conf file. As an example, we
will create a global variable named LEIF
with a value of SIP/0000FFFF0001
. This variable is set at
the time Asterisk parses the dialplan:
[globals] LEIF=SIP/0000FFFF0001
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 Asterisk wiki at https://wiki.asterisk.org/wiki/display/AST/Channel+Variables.
Channel variables are set via the Set()
application:
exten => 202,1,Set(MagicNumber=42) same => n,SayNumber(${MagicNumber})
You’re going to be seeing a lot more channel variables. Read on.
Environment
variables are a way of accessing Unix environment
variables from within Asterisk. These are referenced using the
ENV()
dialplan function.[66] 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’re going to add three global variables that will associate a variable name to a channel name:
[globals] LEIF=SIP/0000FFFF0001 JIM=SIP/0000FFFF0002 RUSSELL=SIP/0000FFFF0003 [LocalSets] exten => 100,1,Dial(${LEIF}) exten => leif,1,Dial(${LEIF}) exten => 101,1,Dial(${JIM}) exten => jim,1,Dial(${JIM}) exten => 102,1,Dial(${RUSSELL}) exten => russell,1,Dial(${RUSSELL}) [TestMenu] exten => 201,1,Answer() same => n,Background(enter-ext-of-person) same => n,WaitExten() exten => 1,1,Dial(DAHDI/1,10) same => n,Playback(vm-nobodyavail) same => n,Hangup() exten => 2,1,Dial(SIP/Jane,10) same => n,Playback(vm-nobodyavail) same => n,Hangup() exten => i,1,Playback(pbx-invalid) same => n,Goto(incoming,123,1) exten => t,1,Playback(vm-goodbye) same => n,Hangup()
You’ll notice we’ve added
pseudonym extension names for our extension numbers. In Extensions, we explained that Asterisk
does not care which naming scheme you use to identify an extension.
We’ve simply added both numeric and named extension identifiers for
reaching the same endpoint; extensions 100
and leif
both reach the device located at
SIP/0000FFFF0001
, extensions
101
and jim
both reach the device located at
SIP/0000FFFF0002
, and both
102
and russell
reach the device located at
SIP/0000FFFF0003
. The devices
are identified with the global variables ${LEIF}
, ${JIM}
, and ${RUSSELL}
, respectively, and we’re
dialing those locations using the Dial()
application.
In our test menu we’ve simply
picked a couple of random endpoints to dial, such as DAHDI/1
and SIP/Jane
. These could be replaced with any
available endpoints that you wish. Our TestMenu
context has been built to start
giving you an idea as to what an Asterisk dialplan looks
like.
If we want to be able to allow people to dial through Asterisk and have Asterisk connect them to outside resources, we need a way to match on any possible phone number that the caller might dial. For situations like this, Asterisk offers pattern matching. Pattern matching allows you to create one extension in your dialplan that matches many different numbers. This is enormously useful.
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.
If you forget the underscore at the beginning 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 character from the range of digits specified. In this case, the pattern matches a single 1, as well as any number in the range 5, 6, 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, if you really need a catch-all pattern match, use this one to match all strings that start with a digit:
_X.
Or this one, to match any alphanumeric string:
_[0-9a-zA-Z].
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(silence/1&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(silence/1&digits/1) exten => _55512XX,1,Playback(silence/1&digits/2)
In this case the second extension would be selected, because it is more specific.
This pattern matches any seven-digit number, as long as the first digit is 2 or higher:
_NXXXXXX
The preceding 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.
_1NXXNXXXXXX
This one will match the number 1, followed by an area code between 200 and 999, then any seven-digit number. In the NANP calling area, you would use this pattern to match any long-distance number.[67]
_011.
Note 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.)
So what happens if you want to use pattern matching
but need to know which digits were actually dialed? Enter the
${EXTEN}
channel variable.
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 this out:
exten => _XXX,1,Answer() same => n,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 try another example:
exten => _XXX,1,Answer() same => n,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.
Asterisk has an important feature that allows extensions
from one context to be available from within another context. This is
accomplished through use of the include
directive. The include
directive allows us to control
access to different sections of the dialplan.
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
Including one context within another context allows extensions within the included context to be dialable.
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.
We will discuss the include
directive more in Chapter 7.
And there you have it—a basic but functional dialplan. There is still much we have not covered, but you’ve got all of the fundamentals. In the following chapters, we’ll continue to build on this foundation.
If parts of this dialplan don’t make sense, you may want to go back and reread a section or two before continuing on to the next chapter. It’s imperative that you understand these principles and how to apply them, as the next chapters build on this information.
[54] This is a very important consideration. With traditional PBXs, there are generally a set of defaults for things like reception, which means that if you forget to define them, they will probably work anyway. In Asterisk, the opposite is true. If you do not tell Asterisk how to handle every situation, and it comes across something it cannot handle, the call will typically be disconnected. We’ll cover some best practices later that will help ensure this does not happen. See Handling Invalid Entries and Timeouts for more information.
[55] Please note that the space is conspicuously absent from the list of allowed characters. Don’t use spaces in your context names—you won’t like the result!
[56] Asterisk permits simple arithmetic within the priority,
such as n+200
, and the
priority s
(for same), but
their usage is somewhat deprecated due to the existence of
priority labels. Please note that extension
s
and
priority s
are two distinct concepts.
[57] Except in some parts of voicemail.conf.
[58] There is another application called Background()
that is very similar to
Playback()
, except that it does
allow input from the caller. You can read more about this
application in Chapter 15 and Chapter 17.
[59] Asterisk selects the best file based on translation cost—that is, it selects the file that is the least CPU-intensive to convert to its native audio format. When you start Asterisk, it calculates the translation costs between the different audio formats (they often vary from system to system). You can see these translation costs by typing show translation at the Asterisk command-line interface. The numbers shown represent how many milliseconds it takes Asterisk to transcode one second of audio. We’ll talk more about the different audio formats (known as codecs) in Codecs.
[60] It should be noted that some people expect that Background()
, due to its name, will
continue onward through the next steps in the dialplan while the
sound is being played. In reality, its name refers to the fact
that it is playing a sound in the background, while waiting for
DTMF in the foreground.
[61] More information about auto attendants can be found in Chapter 15.
[62] See the dialplan function TIMEOUT()
for information on how to
change the default timeouts. See Chapter 10 for information on what dialplan
functions are.
[63] If this were a production environment, this would not actually be a good name for this device. If you have more than one softphone on your system (or add another in the future), how will you tell them apart?
[64] We’ll cover variables in the upcoming section Using Variables. In future chapters
we’ll discuss how to have your dialplan make decisions based on
the value of DIALSTATUS
.
[65] Bear in mind that this assumes that this channel connects to something that knows how to reach external numbers.
[66] We’ll get into dialplan functions later. Don’t worry too much about environment variables right now. They are not important to understanding the dialplan.
[67] 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 the international country code for NANP. Keep this in mind if you send your phone number to someone in another country. The recipient may not know your country code, and thus be unable to call you with just your area code and phone number. Your full phone number with country code is +1 NPA NXX XXXX (where NPA is your area code)―e.g., +1 416 555 1212.