Skip to main content

How to configure an Asterisk dialplan for intra-office calling

Learn how to configure Asterisk to let two softphones call each other.

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:

Image
Two phones connected to an Asterisk server.
Network diagram credit: https://extensions.libreoffice.org/extensions/vrt-network-equipment

Dialplan fundamentals

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:

  1. An external call comes into Asterisk from a standard telephone number.
  2. An Interactive Voice Response (IVR) system might ask the user to enter basic information, such as their account number.
  3. Asterisk accepts the user’s input. The IVR looks up their account and presents them with information (e.g., information about outstanding invoices).
  4. 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 /etc/asterisk/extensions.conf:

[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-phones is the context. This context contains two extensions.
  • 1001 and 1002 are 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).
  • The 1 after 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.
  • Dial is 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 alice-softphone or 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 local-only context.

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 asterisk -rvvv:

[root@asterisk-1 asterisk]# asterisk -rvvv
Asterisk 16.6.1, Copyright (C) 1999 - 2018, Digium, Inc. and others.
Created by Mark Spencer <markster@digium.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 ringing:

Image
Asterisk call in progress.

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:

  1. Answers the call.
  2. Plays a hello-world file. This is a sound file included with Asterisk. By default, Asterisk searches for sounds in /usr/lib/asterisk/sounds/.
  3. 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.

Wrapping up

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.]

Topics:   Networking   VOIP  
Author’s photo

Anthony Critelli

Anthony Critelli is a Linux systems engineer with interests in automation, containerization, tracing, and performance. He started his professional career as a network engineer and eventually made the switch to the Linux systems side of IT. He holds a B.S. and an M.S. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.