In the previous article, you learned how to configure the PJSIP channel driver to connect a simple softphone client with your Asterisk installation. However, your phones still can’t call each other, and you haven’t given them numerical "extensions" yet. Connecting channels together in Asterisk is the work of the dialplan. In this article, you’ll learn the basics of the dialplan: What it is, how it’s configured, and how to use it to connect phones together.
As a reminder, this is the setup we're configuring:
The Asterisk dialplan is responsible for routing calls, so it is often referred to as the heart of an Asterisk system. The dialplan is written in a special scripting language, and it is extremely powerful. You might think of phone systems as simply accepting and connecting calls, but Asterisk is capable of much more. With the dialplan, you can design rich, voice-driven applications. For example, you could create the following call flow for a small business:
- An external call comes into Asterisk from a standard telephone number.
- An Interactive Voice Response (IVR) system might ask the user to enter basic information, such as their account number.
- Asterisk accepts the user’s input. The IVR looks up their account and presents them with information (e.g., information about outstanding invoices).
- Optionally, the user can be routed to a queue of available customer service representatives. When the employee receives the customer’s call, the system provides them with all of the customer’s details and saves the caller some time.
While there are other programming interfaces for interacting with Asterisk, the dialplan is the most basic, and understanding it is fundamental to understanding how Asterisk handles calls. According to Asterisk the Definitive Guide, there are four fundamental components to the Asterisk dialplan:
- Contexts: A context is a logical section in the dialplan. Contexts contain one or more extensions.
- Extensions: An extension is simply a grouping of steps used to handle a particular call. Unlike many traditional phone systems, extensions don’t have to be numerical and they aren’t tied to a single device. You could have an extension called "mainIVR" if you wanted.
- Priorities: A priority is a step in an extension. Priorities handle ordering, and they can also have labels attached to them so that a call can jump between priorities as needed.
- Applications: Applications are a lot like functions in traditional programming languages. They tell Asterisk what to do with a call. For example, you might have an internal extension of *86. When *86 is dialed, you might have Asterisk play a message of the day using the Playback application.
If you’re new to Asterisk, this breakdown probably sounds complicated. While Asterisk dialplans certainly can be complex, a simple phone system only requires a simple dialplan. Let’s take a look at the dialplan needed to support your intra-office calling scenario. The dialplan is configured in
[office-phones] exten => 1001,1,Dial(PJSIP/alice-softphone) exten => 1002,1,Dial(PJSIP/bob-softphone)
The snippet above is all that is necessary to allow your two phones to call each other. Let’s step through each part of this dialplan:
office-phonesis the context. This context contains two extensions.
1002are the extensions. Notice how this setup decouples the numbers from the phones themselves. While these numbers are currently hardcoded to dial Alice’s and Bob’s phones, they could just as easily be used for more complex routing (e.g., automatically roll over to an overnight line during certain hours).
1after the extension is the priority. Remember, a priority is just a step in extension handling. The first priority is always
1. In this example, each extension only has a single priority.
Dialis the application. The Dial application is used to ring a remote device. Dialing occurs via SIP or other signaling protocols (if you need a refresher on VoIP protocols, head over to our [first article]). [Note: Don’t forget to add the link.]
To recap: When a call comes into the
office-phones context, Asterisk tries matching that call to an extension. When extension 1001 is dialed, the first step (priority) tells Asterisk to dial the PJSIP endpoint for Alice’s phone. When extension 1002 is dialed, the same thing happens for Bob’s phone.
This is great so far, but how exactly does a call make its way into the dialplan? The answer lies in the PJSIP endpoint configuration from the previous article:
[alice-softphone] type=endpoint context=office-phones disallow=all allow=ulaw auth=alice-auth aors=alice-softphone
Notice that the context for each phone is set to
office-phones. This setting tells Asterisk that any calls coming from the
bob-softphone endpoints should enter the dialplan in the
office-phones context. When Bob dials a number (say, 9000) from his softphone, Asterisk looks in the
office-phones context for the matching extension 9000. In the sample dialplan above, this call will fail because there is no matching extension.
You don’t have to configure all of your phones to enter the dialplan in the same context. In fact, you’ll likely find good reasons to specifically put phones in other contexts. Consider a business that wants to only allow certain people to make international calls, while everyone else is restricted to local calls. You might have two extensions: One to allow unrestricted calling, and one that only allows calls to numbers that start with the local area code. Those with international calling privileges would be placed in the
international context, while everyone else would be placed in the
That was a lot of theory. Let’s get back to the command line and test out the changes that we made to the dialplan. First, you must non-disruptively
reload the dialplan to enact the changes you made in the config file:
asterisk-1*CLI> dialplan reload Dialplan reloaded.
Next, you can inspect the dialplan directly from the Asterisk CLI to ensure that your changes are present:
asterisk-1*CLI> dialplan show office-phones [ Context 'office-phones' created by 'pbx_config' ] '1001' => 1. Dial(PJSIP/alice-softphone) [extensions.conf:3] '1002' => 1. Dial(PJSIP/bob-softphone) [extensions.conf:5] -= 2 extensions (2 priorities) in 1 context. =-
Notice that Asterisk includes the exact file name and line number where an extension and its priority can be found. This information is useful when troubleshooting behavior in your phone system.
With the dialplan reloaded and your changes clearly in place, you should be able to place a test call from Linphone (or whatever SIP endpoint you’re using). First, launch the Asterisk CLI with extra verbosity using
[root@asterisk-1 asterisk]# asterisk -rvvv Asterisk 16.6.1, Copyright (C) 1999 - 2018, Digium, Inc. and others. Created by Mark Spencer <email@example.com> Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details. This is free software, with components licensed under the GNU General Public License version 2 and other licenses; you are welcome to redistribute it under certain conditions. Type 'core show license' for details. ========================================================================= Connected to Asterisk 16.6.1 currently running on asterisk-1 (pid = 4138)
Next, place a call from Alice’s phone to extension 1002. Assuming that you registered an additional softphone (or physical phone) for Bob, the extension should show as
The Asterisk CLI also prints informational messages about the call’s progression since it was set to verbose mode. You can see the inbound call being handled by the dialplan and handed off to the PJSIP channel driver to dial Bob’s softphone. Eventually, once Bob answers, Asterisk bridges the audio for the call together so that both parties can hear each other:
== Setting global variable 'SIPDOMAIN' to 'asterisk-1.acritelli.com' -- Executing [1002@office-phones:1] Dial("PJSIP/alice-softphone-00000008", "PJSIP/bob-softphone") in new stack -- Called PJSIP/bob-softphone -- PJSIP/bob-softphone-00000009 is ringing -- PJSIP/bob-softphone-00000009 is ringing -- PJSIP/bob-softphone-00000009 answered PJSIP/alice-softphone-00000008 -- Channel PJSIP/bob-softphone-00000009 joined 'simple_bridge' basic-bridge <edd9402c-6df0-4fff-a81e-57826dadc652> -- Channel PJSIP/alice-softphone-00000008 joined 'simple_bridge' basic-bridge <edd9402c-6df0-4fff-a81e-57826dadc652> -- Channel PJSIP/bob-softphone-00000009 left 'native_rtp' basic-bridge <edd9402c-6df0-4fff-a81e-57826dadc652> -- Channel PJSIP/alice-softphone-00000008 left 'native_rtp' basic-bridge <edd9402c-6df0-4fff-a81e-57826dadc652> == Spawn extension (office-phones, 1002, 1) exited non-zero on 'PJSIP/alice-softphone-00000008' asterisk-1*CLI>
You have now created enough Asterisk configuration to allow both of your phones to call each other. Congratulations!
Adding another extension
You’ve now seen basic dialplan configuration that allows two phones to call each other. I also mentioned a few times that Asterisk decouples the concept of a physical phone from an extension because an extension is simply a set of instructions in the dialplan. Let’s add another simple extension to the dialplan to see exactly what I mean:
[office-phones] exten => 1001,1,Dial(PJSIP/alice-softphone) exten => 1002,1,Dial(PJSIP/bob-softphone) exten => 9000,1,Answer() same => n,Playback(hello-world) same => n,Hangup()
The above configuration adds an additional extension (9000) to the dialplan. When this extension is dialed, Asterisk:
- Answers the call.
- Plays a
hello-worldfile. This is a sound file included with Asterisk. By default, Asterisk searches for sounds in
- Hangs up the call.
Notice the use of the
same => n syntax. This is a common and helpful bit of syntactic sugar in the dialplan. Remember that each extension has one or more priorities, or steps, associated with it. The
same => n syntax saves you some typing and tells Asterisk that this step is just the next priority for the same extension. The above configuration could also be written as:
exten => 9000,1,Answer() exten => 9000,2,Playback(hello-world) exten => 9000,3,Hangup()
With your new configuration in place, reload the dialplan and try dialing extension 9000 to see what happens. Again, the key concept to understand is that you have created an extension that has no physical device associated with it. Asterisk fully decouples the concept of devices and extensions.
In this article, you learned about the Asterisk dialplan and wrote enough dialplan configuration to enable two phones to call each other. The Asterisk dialplan is extremely powerful, allowing you to build rich communications applications. I strongly recommend that you check out the official Asterisk dialplan documentation and the fifth edition of Asterisk: The Definitive Guide to help you better understand everything that the dialplan has to offer.
In the [next article], you’ll work on connecting your phone system to an external provider to enable inbound and outbound calling. [Note: Don’t forget to add the link.]