Asterisk
Asterisk Asterisk
Contents

Asterisk - The Open Source VoIP PBX

Previous Page Next Page
 
Asterisk: The Future of Telephony
Table of Contents
Copyright
Foreword
Preface
Audience
Organization
Software
Conventions Used in This Book
Using Code Examples
Safari® Enabled
How to Contact Us
Acknowledgments
Chapter 1.  A Telephony Revolution
Section 1.1.  VoIP: Bridging the Gap Between Traditional Telephony and Network Telephony
Section 1.2.  Massive Change Requires Flexible Technology
Section 1.3.  Asterisk: The Hacker's PBX
Section 1.4.  Asterisk: The Professional's PBX
Section 1.5.  The Asterisk Community
Section 1.6.  The Business Case
Section 1.7.  This Book
Chapter 2.  Preparing a System for Asterisk
Section 2.1.  Server Hardware Selection
Section 2.2.  Environment
Section 2.3.  Telephony Hardware
Section 2.4.  Types of Phone
Section 2.5.  Linux Considerations
Section 2.6.  Conclusion
Chapter 3.  Installing Asterisk
Section 3.1.  What Packages Do I Need?
Section 3.2.  Obtaining the Source Code
Section 3.3.  Compiling Zaptel
Section 3.4.  Compiling libpri
Section 3.5.  Compiling Asterisk
Section 3.6.  Installing Additional Prompts
Section 3.7.  Updating Your Source Code
Section 3.8.  Common Compiling Issues
Section 3.9.  Loading Zaptel Modules
Section 3.10.  Loading libpri
Section 3.11.  Loading Asterisk
Section 3.12.  Directories Used by Asterisk
Section 3.13.  Conclusion
Chapter 4.  Initial Configuration of Asterisk
Section 4.1.  What Do I Really Need?
Section 4.2.  Working with Interface Configuration Files
Section 4.3.  FXO and FXS Channels
Section 4.4.  Configuring an FXO Channel
Section 4.5.  Configuring an FXS Channel
Section 4.6.  Configuring SIP
Section 4.7.  Configuring Inbound IAX Connections
Section 4.8.  Configuring Outbound IAX Connections
Section 4.9.  Debugging
Section 4.10.  Conclusion
Chapter 5.  Dialplan Basics
Section 5.1.  Dialplan Syntax
Section 5.2.  A Simple Dialplan
Section 5.3.  Adding Logic to the Dialplan
Section 5.4.  Conclusion
Chapter 6.  More Dialplan Concepts
Section 6.1.  Expressions and Variable Manipulation
Section 6.2.  Dialplan Functions
Section 6.3.  Conditional Branching
Section 6.4.  Voicemail
Section 6.5.  Macros
Section 6.6.  Using the Asterisk Database (AstDB)
Section 6.7.  Handy Asterisk Features
Section 6.8.  Conclusion
Chapter 7.  Understanding Telephony
Section 7.1.  Analog Telephony
Section 7.2.  Digital Telephony
Section 7.3.  The Digital Circuit-Switched Telephone Network
Section 7.4.  Packet-Switched Networks
Section 7.5.  Conclusion
Chapter 8.  Protocols for VoIP
Section 8.1.  The Need for VoIP Protocols
Section 8.2.  VoIP Protocols
Section 8.3.  Codecs
Section 8.4.  Quality of Service
Section 8.5.  Echo
Section 8.6.  Asterisk and VoIP
Section 8.7.  Conclusion
Chapter 9.  The Asterisk Gateway Interface (AGI)
Section 9.1.  Fundamentals of AGI Communication
Section 9.2.  Writing AGI Scripts in Perl
Section 9.3.  Creating AGI Scripts in PHP
Section 9.4.  Writing AGI Scripts in Python
Section 9.5.  Debugging in AGI
Section 9.6.  Conclusion
Chapter 10.  Asterisk for the Über-Geek
Section 10.1.  Festival
Section 10.2.  Call Detail Recording
Section 10.3.  Customizing System Prompts
Section 10.4.  Manager
Section 10.5.  Call Files
Section 10.6.  DUNDi
Section 10.7.  Conclusion
Chapter 11.  Asterisk: The Future of Telephony
Section 11.1.  The Problems with Traditional Telephony
Section 11.2.  Paradigm Shift
Section 11.3.  The Promise of Open Source Telephony
Section 11.4.  The Future of Asterisk
Appendix A.  VoIP Channels
Section A.1.  IAX
Section A.2.  SIP
Appendix B.  Application Reference
AbsoluteTimeout( )
AddQueueMember( )
ADSIProg( )
AgentCallbackLogin( )
AgentLogin( )
AgentMonitorOutgoing( )
AGI( )
AlarmReceiver( )
Answer( )
AppendCDRUserField( )
Authenticate( )
Background( )
BackgroundDetect( )
Busy( )
CallingPres( )
ChangeMonitor( )
ChanIsAvail( )
CheckGroup( )
Congestion( )
ControlPlayback( )
Curl( )
Cut( )
DateTime( )
DBdel( )
DBdeltree( )
DBget( )
DBput( )
DeadAGI( )
Dial( )
DigitTimeout( )
Directory( )
DISA( )
DumpChan( )
DUNDiLookup( )
EAGI( )
Echo( )
EndWhile( )
ENUMLookup( )
Eval( )
Exec( )
ExecIf( )
FastAGI( )
Festival( )
Flash( )
ForkCDR( )
GetCPEID( )
GetGroupCount( )
GetGroupMatchCount( )
Goto( )
GotoIf( )
GotoIfTime( )
Hangup( )
HasNewVoicemail( )
HasVoicemail( )
IAX2Provision( )
ImportVar( )
LookupBlacklist( )
LookupCIDName( )
Macro( )
MailboxExists( )
Math( )
MeetMe( )
MeetMeAdmin( )
MeetMeCount( )
Milliwatt( )
Monitor( )
MP3Player( )
MusicOnHold( )
NBScat( )
NoCDR( )
NoOp( )
Park( )
ParkAndAnnounce( )
ParkedCall( )
PauseQueueMember( )
Playback( )
Playtones( )
Prefix( )
PrivacyManager( )
Progress( )
Queue( )
Random( )
Read( )
RealTime
RealTimeUpdate( )
Record( )
RemoveQueueMember( )
ResetCDR( )
ResponseTimeout( )
RetryDial( )
Ringing( )
SayAlpha( )
SayDigits( )
SayNumber( )
SayPhonetic( )
SayUnixTime( )
SendDTMF( )
SendImage( )
SendText( )
SendURL( )
Set( )
SetAccount( )
SetAMAFlags( )
SetCallerID( )
SetCallerPres( )
SetCDRUserField( )
SetCIDName( )
SetCIDNum( )
SetGlobalVar( )
SetGroup( )
SetLanguage( )
SetMusicOnHold( )
SetRDNIS( )
SetVar( )
SIPAddHeader( )
SIPDtmfMode( )
SIPGetHeader( )
SoftHangup( )
StopMonitor( )
StopPlaytones( )
StripLSD( )
StripMSD( )
SubString( )
Suffix( )
System( )
Transfer( )
TrySystem( )
TXTCIDName( )
UnpauseQueueMember( )
UserEvent( )
Verbose( )
VMAuthenticate( )
VoiceMail( )
VoiceMailMain( )
Wait( )
WaitExten( )
WaitForRing( )
WaitForSilence( )
WaitMusicOnHold( )
While( )
Zapateller( )
ZapBarge( )
ZapRAS( )
ZapScan( )
Appendix C.  AGI Reference
ANSWER
CHANNEL STATUS
DATABASE DEL
DATABASE DELTREE
DATABASE GET
DATABASE PUT
EXEC
GET DATA
GET FULL VARIABLE
GET OPTION
GET VARIABLE
HANGUP
NOOP
RECEIVE CHAR
RECORD FILE
SAY ALPHA
SAY DATE
SAY DATETIME
SAY DIGITS
SAY NUMBER
SAY PHONETIC
SAY TIME
SEND IMAGE
SEND TEXT
SET AUTOHANGUP
SET CALLERID
SET CONTEXT
SET EXTENSION
SET MUSIC ON
SET PRIORITY
SET VARIABLE
STREAM FILE
TDD MODE
VERBOSE
WAIT FOR DIGIT
Appendix D.  Configuration Files
Section D.1.  modules.conf
Section D.2.  adsi.conf
Section D.3.  adtranvofr.conf
Section D.4.  agents.conf
Section D.5.  alarmreceiver.conf
Section D.6.  alsa.conf
Section D.7.  asterisk.conf
Section D.8.  cdr.conf
Section D.9.  cdr_manager.conf
Section D.10.  cdr_odbc.conf
Section D.11.  cdr_pgsql.conf
Section D.12.  cdr_tds.conf
Section D.13.  codecs.conf
Section D.14.  dnsmgr.conf
Section D.15.  dundi.conf
Section D.16.  enum.conf
Section D.17.  extconfig.conf
Section D.18.  extensions.conf
Section D.19.  features.conf
Section D.20.  festival.conf
Section D.21.  iax.conf
Section D.22.  iaxprov.conf
Section D.23.  indications.conf
Section D.24.  logger.conf
Section D.25.  manager.conf
Section D.26.  meetme.conf
Section D.27.  mgcp.conf
Section D.28.  modem.conf
Section D.29.  musiconhold.conf
Section D.30.  osp.conf
Section D.31.  oss.conf
Section D.32.  phone.conf
Section D.33.  privacy.conf
Section D.34.  queues.conf
Section D.35.  res_odbc.conf
Section D.36.  rpt.conf
Section D.37.  rtp.conf
Section D.38.  sip.conf
Section D.39.  sip_notify.conf
Section D.40.  skinny.conf
Section D.41.  voicemail.conf
Section D.42.  vpb.conf
Section D.43.  zapata.conf
Section D.44.  zaptel.conf
Appendix E.  Asterisk Command-Line Interface Reference
!
abort halt
Section E.1.  add
Section E.2.  agi
Section E.3.  database
Section E.4.  iax2
Section E.5.  indication
Section E.6.  logger
Section E.7.  meetme
Section E.8.  pri
Section E.9.  remove
Section E.10.  restart
Section E.11.  set
Section E.12.  show
Section E.13.  sip
Section E.14.  stop
Section E.15.  zap
Colophon
About the Authors
Colophon
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Previous Page
Next Page

5.3. Adding Logic to the Dialplan

The dialplan we just built was staticit always performs the same actions on every call. Now we'll start adding some logic to our dialplan so that it will perform different actions based on input from the user. We'll start by introducing a few more applications.

5.3.1. The Background( ) and Goto( ) Applications

One important key to building interactive Asterisk systems is the Background( ) 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 file 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,Background(hello-world)

Another useful application is Goto( ). As its name implies, it is used to send the call to another context, extension, and priority. The Goto( ) application makes it easy to programmatically move a call between different parts of the dialplan. The syntax for the Goto( ) application calls for us to pass the destination context, extension, and priority as arguments to the application, like this:

    exten => 123,1,Goto(context,extension,priority)

In our next example, we'll use the Background( ) and Goto( )applications to create a slightly more complex dialplan, allowing the caller to interact with the system by pressing digits on the keypad. Let's begin by using Background( ) to accept input from the caller:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)

In this example, we'll play the sample sound file named enter-ext-of-person.gsm. While it's not the perfect fit for an auto-attendant greeting, it will certainly work for this example. Now let's add two extensions that will be triggered by the caller entering either 1 or 2 at the prompt:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 1,1,Playback(digits /1)
    exten => 2,1,Playback(digits/2)

Before going on, let's review what we've done so far. When users call into our dialplan, they will hear a greeting saying, "Please enter the number you wish to call." If they press 1, they will hear the number one, and if they press 2, they will hear the number two. 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:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 1,1,Playback(digits/1)
    exten => 1,2,Goto(incoming,s,1)
    exten => 2,1,Playback(digits/2)
    exten => 2,2,Goto(incoming,s,1)

These two new lines (highlighted in bold) will send the call control back to the s 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, it'll assume it's the destination priority in the current extension. If you pass two, it'll 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.


5.3.2. Handling Invalid Entries and Timeouts

Now that our first voice menu is fairly complete, let's add some additional special extensions. First, we need an extension for invalid entries, so that when a caller presses an invalid entry (e.g., pressing 3 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 Background( ) has finished playing the sound file. Here is what our dialplan will look like after we've added these two extensions:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 1,1,Playback(digits/1)
    exten => 1,2,Goto(incoming,s,1)
    exten => 2,1,Playback(digits/2)
    exten => 2,2,Goto(incoming,s,1)
    exten => i,1,Playback(pbx-invalid)
    exten => i,2,Goto(incoming,s,1)
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,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( ) .

5.3.3. Using the Dial( ) Application

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 standard 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 is made up of a technology (or transport) across which to make the call, a forward slash, and the remote resource (usually a channel name or number). For example, let's assume that we want to call a Zap channel named 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 might have a destination of SIP/1234, and a call to an IAX device might have a destination of IAX/fred. If we want 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)

When this extension is executed, Asterisk will ring the phone connected to channel Zap/1. If that phone is answered, Asterisk will bridge the inbound call with the Zap/1 channel. We can also dial multiple channels at the same time, by concatenating the destinations together with an ampersand (&), like this:

    exten => 123,1,Dial(Zap/1&Zap/2&Zap/3)

The Dial( ) application will bridge the inbound call with whichever destination channel is answered first.

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, Dial( ) goes on to the next priority in the extension. If, however, the destination channel is busy, Dial( ) will go to priority n+101, if it exists (where n is the priority where the Dial( ) application was called). This allows us to handle unanswered calls differently from calls whose destinations were busy.

Let's put what we've learned so far into another example:

    exten => 123,1,Dial(Zap/1,10)
    exten => 123,2,Playback(vm-nobodyavail)
    exten => 123,3,Hangup( )
    exten => 123,102,Playback(tt-allbusy)
    exten => 123,103,Hangup( )

As you can see, this example will play the vm-nobodyavail.gsm sound file if the call goes unanswered, or the tt-allbusy.gsm sound file if the Zap/1 channel is currently busy.

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, the most popular option is the letter r. If you place the letter r as the third argument, the calling party will hear a ringing tone while the destination channel is being notified of an incoming call.

It should be noted that the r option isn't always required to indicate ringing, as Asterisk will automatically generate a ringing tone when it is attempting to establish a channel. However, you can use the r option to force Asterisk to indicate ringing even when no connection is being attempted. To add the r option to our last example, we simply change the first line:

    exten => 123,1,Dial(Zap/1,10,r)
    exten => 123,2,Playback(vm-nobodyavail)
    exten => 123,3,Hangup( )
    exten => 123,102,Playback(tt-allbusy)
    exten => 123,103,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 extensions 101 and 102, which will allow outside callers to reach John and Jane:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 101,1,Dial(Zap/1,10)
    exten => 101,2,Playback(vm-nobodyavail)
    exten => 101,3,Hangup( )
    exten => 101,102,Playback(tt-allbusy)
    exten => 101,103,Hangup( )
    exten => 102,1,Dial(SIP/Jane,10)
    exten => 102,2,Playback(vm-nobodyavail)
    exten => 102,3,Hangup( )
    exten => 102,102,Playback(tt-allbusy)
    exten => 102,103,Hangup( )
    exten => i,1,Playback(pbx-invalid)
    exten => i,2,Goto(incoming,s,1)
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,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.

If you are making outbound calls on an FXO Zap channel, you can use the following syntax to dial a number on that channel:

    exten => 123,1,Dial(Zap/4/5551212)

This example would dial the number 555-1212 on the Zap/4 channel. For other channel types, such as SIP and IAX, simply put the destination as the resource, as shown in these two lines:

    exten => 123,1,Dial(SIP/1234)
    exten => 124,1,Dial(IAX2/john@asteriskdocs.org)

Note that any of these 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 => 123,1,Dial(Zap/1,,r)

5.3.4. Adding a Context for Internal Calls

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

As in previous examples, we've assumed that an FXS Zap 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 [internal] 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. This channel will be used for outbound calling.

We've also assumed you have at least one SIP channel (named SIP/jane) that is configured to originate in the [internal] 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), don't worryyou can change the examples to match your particular system configuration.


Our dialplan now looks like this:

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 101,1,Dial(Zap/1,10)
    exten => 101,2,Playback(vm-nobodyavail)
    exten => 101,3,Hangup( )
    exten => 101,102,Playback(tt-allbusy)
    exten => 101,103,Hangup( )
    exten => 102,1,Dial(SIP/Jane,10)
    exten => 102,2,Playback(vm-nobodyavail)
    exten => 102,3,Hangup( )
    exten => 102,102,Playback(tt-allbusy)
    exten => 102,103,Hangup( )
    exten => i,1,Playback(pbx-invalid)
    exten => i,2,Goto(incoming,s,1)
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,Hangup( )

    [internal]
    exten => 101,1,Dial(Zap/1,,r)
    exten => 102,1,Dial(SIP/jane,,r)

In this example, we have added two new extensions to the [internal] 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 extensionsyou 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 => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 101,1,Dial(Zap/1,10)
    exten => 101,2,Playback(vm-nobodyavail)
    exten => 101,3,Hangup( )
    exten => 101,102,Playback(tt-allbusy)
    exten => 101,103,Hangup( )
    exten => 102,1,Dial(SIP/Jane,10)
    exten => 102,2,Playback(vm-nobodyavail)
    exten => 102,3,Hangup( )
    exten => 102,102,Playback(tt-allbusy)
    exten => 102,103,Hangup( )
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,Hangup( )

    [internal]
    exten => 101,1,Dial(Zap/1,,r)
    exten => john,1,Dial(Zap/1,,r)
    exten => 102,1,Dial(SIP/jane,,r)
    exten => jane,1,Dial(SIP/jane,,r)

It certainly wouldn't hurt to add named extensions if you think your users might be dialed via a VoIP transport that supports names.

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.

5.3.5. Using Variables

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 Zap/1. To assign a value to a variable, simply type the name of the variable, an equals sign, and the value, like this:

    JOHN=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},,r)

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 don't have to be capitalized, but we're doing so in this book for readability's sake.


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.

5.3.5.1. Global variables

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 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 only have to change 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 SetGlobalVar( ) application. Here is how both methods look inside of a dialplan:

    [globals]
    JOHN=Zap/1

    [internal]
    exten => 123,1,SetGlobalVar(JOHN=Zap/1)

5.3.5.2. Channel variables

A channel variable is a variable (such as the Caller*IDnumber) 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 channel participating in that call.

There are many predefined channel variables available for use within the dialplan, which are explained in the README.variables file in the doc subdirectory of the Asterisk source. Channel variables are set via the Set( ) application:

    exten => 123,1,Set(MAGICNUMBER=42)

We'll use several of these channel variables in the next chapter.

5.3.5.3. Environment variables

Environment variables are a way of accessing Unix environment variables from within Asterisk. These are referenced in the form of ${ENV(var)}, where var is the Unix environment variable you wish to reference.

5.3.5.4. Adding variables to our dialplan

Now that we've learned about variables, let's put them to work in our dialplan. We'll add variables for two people, John and Jane:

    [globals]
    JOHN=Zap/1
    JANE=SIP/jane

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 101,1,Dial(${JOHN},10)
    exten => 101,2,Playback(vm-nobodyavail)
    exten => 101,3,Hangup( )
    exten => 101,102,Playback(tt-allbusy)
    exten => 101,103,Hangup( )
    exten => 102,1,Dial(${JANE},10)
    exten => 102,2,Playback(vm-nobodyavail)
    exten => 102,3,Hangup( )
    exten => 102,102,Playback(tt-allbusy)
    exten => 102,103,Hangup( )
    exten => i,1,Playback(pbx-invalid)
    exten => i,2,Goto(incoming,s,1)
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,Hangup( )

    [internal]
    exten => 101,1,Dial(${JOHN},,r)
    exten => 102,1,Dial(${JANE},,r)

5.3.6. Pattern Matching

Often, it would be tedious to add every possible extension to a dialplan. This is especially the case for outbound calls. Can you imagine a dialplan with an extension for every possible number you could dial? Luckily, Asterisk has just the thing for situations like this: pattern matching to allow you to use one section of code for many different extensions.

5.3.6.1. Pattern-matching syntax

When using pattern matching, we use different letters and symbols to represent the possible digits we want to match. Patterns always start with an underscore (_). This tells Asterisk that we're matching on a pattern, and not on an 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.


After the underscore, you can use one or more of the following characters:



X

Matches any digit from 0 to 9.



Z

Matches any digit from 1 to 9.



N

Matches any digit from 2 to 9.



[15-7]

Matches any digit or range of digits specified. In this case, matches a 1, 5, 6, or 7.



. (period)

Wildcard match; matches one or more characters.

If you're not careful, wildcard matches can make your dialplans do things you're not expecting. You should only use the wildcard match in a pattern 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 possible:

    _X.


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 would match any 3-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 3-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. Say you had defined the following two patterns, and a caller dialed 888-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.

5.3.6.2. Pattern-matching examples

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

Got it? This pattern would match any seven-digit number, as long as the first digit was two or higher. According to the North American Numbering Plan, this pattern would match any local number.

The NANP and Toll Fraud

The North American Number Plan (NANP) is a shared telephone numbering scheme used by 19 countries in North America and the Caribbean.

In the United States and Canada, telecom regulations are similar (and sensible) enough that you can place a long-distance call to most numbers in country code 1 and expect to pay a reasonable toll. What many people don't realize, however, is that 19 countries, many of which have very different telecom regulations, share the NANP. (More information can be found at http://www.nanpa.com.)

Many toll-fraud schemes trick naive North Americans into calling shockingly expensive per-minute toll numbers in a Caribbean countrythe callers believe that since they dialed 1-NPA-NXX-XXXX to reach the number, they'll be paying their standard national long-distance rate for the call. Since the country in question may have regulations that allow for this form of extortion, the caller is ultimately held responsible for the call charges.

The only way to prevent this sort of activity is to block calls to certain area codes (809, for example) and remove the restrictions only on an as-needed basis. Please take extra caution to make sure users can't abuse your phone system!


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, you would use this pattern to match any long-distance number.

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

[*] If you find it peculiar that we've chosen patterns that are used to dial outbound numbers in the NANP, you're on to something! We'll be using these patterns in the next section to add outbound dialing capabilities to our dialplan.

5.3.6.3. Using the ${EXTEN} channel variable

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 the number of digits you'd like to remove. 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 read back only the last two digits of the dialed extension.

If x is negative, SayDigits( ) gives you the last x digits of the dialed extension. In this next example, SayDigits( ) will read back only the last digit of the dialed extension:

    exten => _XXX,1,SayDigits(${EXTEN:-1))

5.3.7. Enabling Outbound Dialing

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 who has permission to make outbound calls, and which types of outbound calls they are allowed to make.

First, let's make 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,2,Congestion( ) 
 

    exten => _9NXXXXXX,102,Congestion( )

Note that dialing 9 doesn't actually give you an outside line, unlike with many traditional PBX systems. Once you dial 9 on an FXS 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, even after the caller has dialed the indicated pattern.


Let's review what we've just done. We've added a global variable called OUTBOUNDTRUNK, which will control which channel to use for outbound calls. 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 farther, let's make sure our dialplan allows outbound emergency numbers:

    [outbound-local]
    exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
    exten => _9NXXXXXX,2,Congestion( )
    exten => _9NXXXXXX,102,Congestion( )

    exten => 911,1,Dial(${OUTBOUNDTRUNK}/911)
    exten => 9911,1,Dial(${OUTBOUNDTRUNK}/911)

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,2,Congestion( )
    exten => _91NXXNXXXXXX,102,Congestion( )

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 other contexts.

5.3.8. Includes

Asterisk enables us to use a context within another context via the include directive. This is used to grant access to different sections of the dialplan. We'll use the include functionality to allow users in our [internal] 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 including them. Asterisk will first try to match the extension in the current context. If unsuccessful, it will then try the first included 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 [internal] context to use them. Let's remedy that by including the two outbound contexts in the [internal] context, like this:

    [globals]
    JOHN=Zap/1
    JANE=SIP/jane
    OUTBOUNDTRUNK=Zap/4

    [incoming]
    exten => s,1,Answer( )
    exten => s,2,Background(enter-ext-of-person)
    exten => 101,1,Dial(${JOHN},10)
    exten => 101,2,Playback(vm-nobodyavail)
    exten => 101,3,Hangup( )
    exten => 101,102,Playback(tt-allbusy)
    exten => 101,103,Hangup( )
    exten => 102,1,Dial(${JANE},10)
    exten => 102,2,Playback(vm-nobodyavail)
    exten => 102,3,Hangup( )
    exten => 102,102,Playback(tt-allbusy)
    exten => 102,103,Hangup( )
    exten => i,1,Playback(pbx-invalid)
    exten => i,2,Goto(incoming,s,1)
    exten => t,1,Playback(vm-goodbye)
    exten => t,2,Hangup( )

    [internal]
    include => outbound-local
    include => outbound-long-distance

    exten => 101,1,Dial(${JOHN},,r)
    exten => 102,1,Dial(${JANE},,r)

    [outbound-local]
    exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
    exten => _9NXXXXXX,2,Congestion( )
    exten => _9NXXXXXX,102,Congestion( )

    exten => 911,1,Dial(${OUTBOUNDTRUNK}/911)
    exten => 9911,1,Dial(${OUTBOUNDTRUNK}/911)

    [outbound-long-distance]
    exten => _91NXXNXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
    exten => _91NXXNXXXXXX,2,Congestion( )
    exten => _91NXXNXXXXXX,102,Congestion( )

These two include statements make it possible for callers in the [internal] 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!)


Previous Page
Next Page
Asterisk