Asterisk™: The Definitive Guide

Leif Madsen

Jim Van Meggelen

Russell Bryant

Printed in the United States of America.


Table of Contents

Foreword
Preface
Audience
Organization
Software
Conventions Used in This Book
Using Code Examples
Safari Books Online
How to Contact Us
Acknowledgments
Leif Madsen
Jim Van Meggelen
Russell Bryant
1. A Telephony Revolution
Asterisk and VoIP: Bridging the Gap Between Traditional and Network Telephony
The Zapata Telephony Project
Massive Change Requires Flexible Technology
Asterisk: The Hacker’s PBX
Asterisk: The Professional’s PBX
The Asterisk Community
The Asterisk Mailing Lists
Asterisk Wiki Sites
The IRC Channels
Asterisk User Groups
The Asterisk Documentation Project
The Business Case
Conclusion
2. Asterisk Architecture
Modules
Applications
Bridging Modules
Call Detail Recording Modules
Channel Event Logging Modules
Channel Drivers
Codec Translators
Format Interpreters
Dialplan Functions
PBX Modules
Resource Modules
Addon Modules
Test Modules
File Structure
Configuration Files
Modules
The Resource Library
The Spool
Logging
The Dialplan
Hardware
Asterisk Versioning
Previous Release Methodologies
The New Release Methodology
Conclusion
3. Installing Asterisk
Installation Cheat Sheet
Distribution Installation
CentOS Server
Base system installation
Base system update
Enabling NTP for accurate system time
Adding a system user
Ubuntu Server
Base system installation
Base system update
Enable NTP for accurate system time
Software Dependencies
Downloading What You Need
Getting the Source via Subversion
Getting the Source via wget
How to Install It
LibPRI
DAHDI
Asterisk
Setting File Permissions
Base Configuration
Disable SELinux
Initial Configuration
indications.conf and asterisk.conf
modules.conf
musiconhold.conf
make menuselect
Uses for menuselect
menuselect interfaces
Using menuselect
Scripting menuselect
Updating Asterisk
Common Issues
-bash: wget: command not found
configure: error: no acceptable C compiler found in $PATH
make: gcc: command not found
configure: error: C++ preprocessor “/lib/cpp” fails sanity check
configure: error: *** Please install GNU make. It is required to build Asterisk!
configure: *** XML documentation will not be available because the ‘libxml2’ development package is missing.
configure: error: *** termcap support not found
You do not appear to have the sources for the 2.6.18-164.6.1.el5 kernel installed.
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?
Upgrading Asterisk
Conclusion
4. Initial Configuration Tasks
asterisk.conf
The [directories] Section
The [options] Section
The [files] Section
The [compat] Section
modules.conf
The [modules] Section
indications.conf
musiconhold.conf
Converting Music to a Format That Works Best with Asterisk
CentOS
Ubuntu
Completing file conversion
Conclusion
5. User Device Configuration
Telephone Naming Concepts
Hardphones, Softphones, and ATAs
Configuring Asterisk
How Channel Configuration Files Work with the Dialplan
sip.conf
iax.conf
Modifying Your Channel Configuration Files for Your Environment
Loading Your New Channel Configurations
The Asterisk CLI
Testing to Ensure Your Devices Have Registered
Analog Phones
A Basic Dialplan to Test Your Devices
Under the Hood: Your First Call
Conclusion
6. Dialplan Basics
Dialplan Syntax
Contexts
Extensions
Priorities
Unnumbered priorities
The 'same =>' operator
Priority labels
Applications
The Answer(), Playback(), and Hangup() Applications
A Simple Dialplan
Hello World
Building an Interactive Dialplan
The Goto(), Background(), and WaitExten() Applications
Handling Invalid Entries and Timeouts
Using the Dial() Application
Argument 1: Destination
Argument 2: Timeout
Argument 3: Option
Argument 4: URI
Updating the dialplan
Blank arguments
Using Variables
Global variables
Channel variables
Environment variables
Adding variables to our dialplan
Pattern Matching
Pattern-matching syntax
Pattern-matching examples
Using the ${EXTEN} channel variable
Includes
Conclusion
7. Outside Connectivity
The Basics of Trunking
Fundamental Dialplan for Outside Connectivity
PSTN Circuits
Traditional PSTN Trunks
Analog telephony
Digital telephony
Installing PSTN Trunks
Downloading and installing DAHDI
Configuring digital circuits
Configuring analog circuits
VoIP
PSTN Termination
PSTN Origination
VoIP to VoIP
Configuring VoIP Trunks
Configuring SIP trunks between Asterisk systems
Configuring IAX trunks between Asterisk systems
Emergency Dialing
Conclusion
8. Voicemail
Comedian Mail
The [general] Section
The [zonemessages] Section
The Contexts Section
An Initial voicemail.conf File
Dialplan Integration
The VoiceMail() Dialplan Application
The VoiceMailMain() Dialplan Application
Creating a Dial-by-Name Directory
Using a Jitterbuffer
Storage Backends
Linux Filesystem
ODBC
IMAP
Using Asterisk As a Standalone Voicemail Server
Integrating Asterisk into a SIP Environment As a Standalone Voicemail Server
Dialplan requirements
sip.conf requirements
SMDI (Simplified Message Desk Interface)
Conclusion
9. Internationalization
Devices External to the Asterisk Server
PSTN Connectivity, DAHDI, Digium Cards, and Analog Phones
DAHDI Drivers
Asterisk
Caller ID
Language and/or Accent of Prompts
Time/Date Stamps and Pronunciation
Conclusion—Easy Reference Cheat Sheet
10. Deeper into the Dialplan
Expressions and Variable Manipulation
Basic Expressions
Operators
Dialplan Functions
Syntax
Examples of Dialplan Functions
Conditional Branching
The GotoIf() Application
Time-Based Conditional Branching with GotoIfTime()
Macros
Defining Macros
Calling Macros from the Dialplan
Using Arguments in Macros
GoSub()
Defining Subroutines
Calling Subroutines from the Dialplan
Using Arguments in Subroutines
Returning from a Subroutine
Local Channels
Using the Asterisk Database (AstDB)
Storing Data in the AstDB
Retrieving Data from the AstDB
Deleting Data from the AstDB
Using the AstDB in the Dialplan
Handy Asterisk Features
Zapateller()
Call Parking
Conferencing with MeetMe()
Conclusion
11. Parking and Paging
features.conf
The [general] section
The [featuremap] Section
The [applicationmap] Section
Application Map Grouping
Parking Lots
Overhead and “Underchin” Paging (a.k.a. Public Address)
Places to Send Your Pages
External paging
Set paging
Multicast paging via the MulticastRTP channel
VoIP paging adaptors
Combination paging
Bringing it all together
Zone Paging
Conclusion
12. Internet Call Routing
DNS and SIP URIs
The SIP URI
SRV Records
Accepting Calls to Your System
Modifying sip.conf
Standard dialplan
File parsing
Database lookup
Dialing SIP URIs from Asterisk
ENUM and E.164
E.164 and the ITU
ENUM
Asterisk and ENUM
ISN, ITAD, and freenum.org
Got ISN?
ITAD Subscriber Numbers (ISNs)
Management of Internet Numbering
IP Telephony Administrative Domains (ITADs)
Create a DNS Entry for Your ITAD
Testing Your ITAD
Using ISNs in Your Asterisk System
Receiving calls to your ITAD
Security and Identity
Toll Fraud
Spam over Internet Telephony (SPIT)
Distributed Denial of Service Attacks
Phishing
Security Is an Ongoing Process
Conclusion
13. Automatic Call Distribution (ACD) Queues
Creating a Simple ACD Queue
Queue Members
Controlling Queue Members via the CLI
Controlling Queue Members with Dialplan Logic
Automatically Logging Into and Out of Multiple Queues
An Introduction to Device State
The queues.conf File
The agents.conf File
Advanced Queues
Priority Queue (Queue Weighting)
Queue Member Priority
Changing Penalties Dynamically (queuerules.conf)
Announcement Control
Overflow
Controlling timeouts
Controlling when to join and leave a queue
Using Local Channels
Queue Statistics: The queue_log File
Conclusion
14. Device States
Device States
Checking Device States
Extension States
Hints
Checking Extension States
SIP Presence
Asterisk Configuration
Using Custom Device States
An Example
Distributed Device States
Using OpenAIS
Installation
OpenAIS configuration
Asterisk configuration
Testing device state changes
Using XMPP
Installation
Creating XMPP accounts
Asterisk configuration
Testing
Shared Line Appearances
Installing the SLA Applications
Configuration Overview
Key System Example with Analog Trunks
sla.conf
extensions.conf
Additional phone configuration tasks
Key System Example with SIP Trunks
sla.conf
extensions.conf
Shared Extension Example
sla.conf
extensions.conf
Additional Configuration
Limitations
Conclusion
15. The Automated Attendant
An Auto Attendant Is Not an IVR
Designing Your Auto Attendant
The Greeting
The Main Menu
Selection 1
Selection 2
Selection #
Selection 3
Selection 9
Selection 0
Timeout
Invalid
Dial by Extension
Building Your Auto Attendant
Recording Prompts
Using the dialplan to create recordings
The Dialplan
Delivering Incoming Calls to the Auto Attendant
IVR
Conclusion
16. Relational Database Integration
Installing and Configuring PostgreSQL and MySQL
Installing PostgreSQL for CentOS
Installing PostgreSQL for Ubuntu
Installing MySQL for CentOS
Installing MySQL for Ubuntu
Configuring PostgreSQL
Configuring MySQL
Installing and Configuring ODBC
Configuring ODBC for PostgreSQL
Configuring ODBC for MySQL
Configuring ODBC for Microsoft SQL
Validating the ODBC Connector
Configuring res_odbc to Allow Asterisk to Connect Through ODBC
Managing Databases
Troubleshooting Database Issues
A Gentle Introduction to func_odbc
Getting Funky with func_odbc: Hot-Desking
Using Realtime
Static Realtime
Dynamic Realtime
Storing Call Detail Records (CDRs)
ODBC Voicemail
Creating the Large Object Type for PostgreSQL
ODBC Voicemail Storage Table Layout
Configuring voicemail.conf for ODBC Storage
Testing ODBC Voicemail
Verifying binary data stored in PostgreSQL
Verifying binary data stored in MySQL
Conclusion
17. Interactive Voice Response
What Is IVR?
Components of an IVR
IVR Design Considerations
Do
Don’t
Asterisk Modules for Building IVRs
CURL
func_odbc
AGI
AMI
A Simple IVR Using CURL
Installing the cURL Module
The Dialplan
A Prompt-Recording Application
Speech Recognition and Text-to-Speech
Text-to-Speech
Speech Recognition
Conclusion
18. External Services
Calendar Integration
Compiling Calendaring Support into Asterisk
CentOS dependencies
Ubuntu dependencies
Configuring Calendar Support for Asterisk
Triggering Calendar Reminders to Your Phone
Triggering a wakeup call
Scheduling calls between two participants
Calling meeting participants and placing them into a conference
Controlling Calls Based on Calendar Information
Writing Call Information to a Calendar
Conclusion
VoiceMail IMAP Integration
Compiling IMAP VoiceMail Support into Asterisk
CentOS dependencies
Ubuntu dependencies
Compiling the IMAP library
Compiling Asterisk
Configuring Asterisk
Using XMPP (Jabber) with Asterisk
Compiling Jabber Support into Asterisk
CentOS dependencies
Ubuntu dependencies
Jabber Dialplan Commands
Connecting to an XMPP server
Sending messages with JabberSend()
Receiving messages with JABBER_RECEIVE()
chan_gtalk
Configuring gtalk.conf
Accepting calls from Google Talk
Accepting calls from Google Voice
Outgoing calls via Google Talk
Outgoing calls via Google Voice
Skype Integration
Installation of Skype for Asterisk
Using Skype for Asterisk
Configuring chan_skype.conf
Placing and receiving calls via Skype
Sending and receiving messages via Skype
Calling your Skype buddies without assigning extension numbers
LDAP Integration
Configuring OpenLDAP
Compiling LDAP Support into Asterisk
Ubuntu dependencies
CentOS dependencies
Configuring Asterisk for LDAP Support
Configuring res_ldap.conf
Configuring extconfig.conf
Configuring sip.conf for realtime
Text-to-Speech Utilities
Festival
Installing Festival on CentOS
Installing Festival on Ubuntu
Using Festival with Asterisk
Cepstral
Conclusion
19. Fax
What Is a Fax?
Ways to Handle Faxes in Asterisk
spandsp
Obtaining spandsp
Compiling and Installing spandsp
Adding the spandsp Library to Your libpath
Recompiling Asterisk with spandsp Support
Disabling spandsp (Should You Want to Test Digium Fax)
Digium Fax For Asterisk
Obtaining Digium FFA
Disabling Digium FFA (Should You Want to Test spandsp)
Incoming Fax Handling
Fax to TIFF
Fax to Email
Fax Detection
Outgoing Fax Handling
Transmitting a Fax from Asterisk
File Format for Faxing
An Experiment in Email to Fax
Fax Pass-Through
Using Fax Buffers in chan_dahdi.conf
Conclusion
20. Asterisk Manager Interface (AMI)
Quick Start
AMI over TCP
AMI over HTTP
Configuration
manager.conf
http.conf
Protocol Overview
Message Encoding
Events
Actions
AMI over HTTP
Authentication and session handling
/rawman encoding
/manager encoding
/mxml encoding
Manager events
Development Frameworks
CSTA
Interesting Applications
AsteriskGUI
Flash Operator Panel
Conclusion
21. Asterisk Gateway Interface (AGI)
Quick Start
AGI Variants
Process-Based AGI
EAGI
DeadAGI Is Dead
FastAGI—AGI over TCP
Async AGI—AMI-Controlled AGI
AGI Communication Overview
Setting Up an AGI Session
Process-based AGI/FastAGI
Async AGI
Commands and Responses
Process-based AGI/FastAGI
Async AGI
Ending an AGI Session
Process-based AGI/FastAGI
Async AGI
Development Frameworks
Conclusion
22. Clustering
Traditional Call Centers
Hybrid Systems
Pure Asterisk, Nondistributed
Asterisk and Database Integration
Single Database
Replicated Databases
Asterisk and Distributed Device States
Distributing Device States over a LAN
Distributing Device States over a WAN
Multiple Queues, Multiple Sites
Conclusion
23. Distributed Universal Number Discovery (DUNDi)
How Does DUNDi Work?
The dundi.conf File
Configuring Asterisk for Use with DUNDi
General Configuration
Initial DUNDi Peer Definition
Creating Mapping Contexts
Using Mapping Contexts with Peers
Allowing Remote Connections
Controlling Responses
Manually adding responses
Using pattern matches
Dynamically adding extension numbers
Using dialplan functions in mappings
Performing Lookups from the Dialplan
Conclusion
24. System Monitoring and Logging
logger.conf
Reviewing Asterisk Logs
Logging to the Linux syslog Daemon
Verifying Logging
Call Detail Records
CDR Contents
Dialplan Applications
cdr.conf
Backends
cdr_adaptive_odbc
cdr_csv
cdr_custom
cdr_manager
cdr_mysql
cdr_odbc
cdr_pgsql
cdr_radius
cdr_sqlite
cdr_sqlite3_custom
cdr_syslog
cdr_tds
Example Call Detail Records
Single-party call
Two-party call
Caveats
CEL (Channel Event Logging)
Channel Event Types
Channel Event Contents
Dialplan Applications
cel.conf
Backends
cel_odbc
cel_custom
cel_manager
cel_pgsql
cel_radius
cel_sqlite3_custom
cel_tds
Example Channel Events
Single-party call
Two-party call
Blind transfer
SNMP
Installing the SNMP Module for Asterisk
CentOS dependency
Ubuntu dependency
Recompiling Asterisk with the res_snmp module
Configuring SNMP for Asterisk Using OpenNMS
Installing OpenNMS
Editing /etc/asterisk/res_snmp.conf to work with your OpenNMS server
Editing /etc/snmp/snmpd.conf to work with your OpenNMS server
Enabling SNMPv3
Monitoring Asterisk with OpenNMS
Conclusion
25. Web Interfaces
Flash Operator Panel
Queue Status and Reporting
Queue Status Display
Queue Reporting
Call Detail Records
A2Billing
Conclusion
26. Security
Scanning for Valid Accounts
Authentication Weaknesses
Fail2ban
Installation
iptables
Sending email
Configuration
Encrypted Media
Dialplan Vulnerabilities
Securing Asterisk Network APIs
IAX2 Denial of Service
Other Risk Mitigation
Resources
Conclusion—A Better Idiot
27. Asterisk: A Future for Telephony
The Problems with Traditional Telephony
Closed Thinking
Limited Standards Compliancy
Slow Release Cycles
Refusing to Let Go of the Past and Embrace the Future
Paradigm Shift
The Promise of Open Source Telephony
The Itch That Asterisk Scratches
Open Architecture
Standards Compliance
Lightning-Fast Response to New Technologies
Passionate Community
Some Things That Are Now Possible
Legacy PBX migration gateway
Low-barrier IVR
Conference rooms
Home automation
The Future of Asterisk
Speech Processing
Festival
Speech recognition
High-Fidelity Voice
Video
The challenge of videoconferencing
Why we love videoconferencing
Why videoconferencing may never totally replace voice
Wireless
WiFi
WiMAX
Unified Messaging
Peering
E.164
ENUM
e164.org
Challenges
Too much change, too few standards
Toll fraud
VoIP spam
Fear, uncertainty, and doubt
Bottleneck engineering
Regulatory wars
Quality of service
Complexity
Opportunities
Tailor-made private telecommunications networks
Low barrier to entry
Hosted solutions of similar complexity to corporate websites
Proper integration of communications technologies
A. Understanding Telephony
Analog Telephony
Parts of an Analog Telephone
Ringer
Dialpad
Hybrid (or network)
Tip and Ring
Digital Telephony
Pulse-Code Modulation
Digitally encoding an analog waveform
Increasing the sampling resolution and rate
Nyquist’s Theorem
Logarithmic companding
Aliasing
The Digital Circuit-Switched Telephone Network
Circuit Types
The humble DS-0―The foundation of it all
T-carrier circuits
SONET and OC circuits
Digital Signaling Protocols
Channel Associated Signaling (CAS)
ISDN
Signaling System 7
Packet-Switched Networks
Conclusion
B. Protocols for VoIP
The Need for VoIP Protocols
VoIP Protocols
IAX (The “Inter-Asterisk eXchange” Protocol)
History
Future
Security considerations
IAX and NAT
SIP
History
Future
Security considerations
SIP and NAT
H.323
History
Future
Security considerations
H.323 and NAT
MGCP
Proprietary Protocols
Skinny/SCCP
UNISTIM
Codecs
G.711
G.726
G.729A
GSM
iLBC
Speex
G.722
MP3
Quality of Service
TCP, UDP, and SCTP
Transmission Control Protocol
User Datagram Protocol
Stream Control Transmission Protocol
Differentiated Service
Guaranteed Service
MPLS
RSVP
Best Effort
Echo
Why Echo Occurs
Managing Echo on DAHDI Channels
Hardware Echo Cancellation
Asterisk and VoIP
Users and Peers and Friends—Oh My!
Users
Peers
Friends
register Statements
VoIP Security
Spam over Internet Telephony (SPIT)
Encrypting Audio with Secure RTP
Spoofing
What Can Be Done?
Basic network security
Encryption
Physical security
Conclusion
C. Preparing a System for Asterisk
Server Hardware Selection
Performance Issues
Choosing a Processor
Small systems
Medium systems
Large systems
Choosing a Motherboard
Power Supply Requirements
Computer power supplies
Redundant power supplies
Environment
Power Conditioning and Uninterruptible Power Supplies
Power-conditioned UPSs
Grounding
Electrical Circuits
The Equipment Room
Humidity
Temperature
Dust
Security
Telephony Hardware
Connecting to the PSTN
Analog interface cards
Digital interface cards
Channel banks
Other types of PSTN interfaces
Connecting Exclusively to a Packet-Based Telephone Network
Echo Cancellation
Types of Phones
Physical Telephones
Analog telephones
Proprietary digital telephones
ISDN telephones
IP telephones
Softphones
Telephony Adaptors
Communications Terminals
Linux Considerations
Conclusion
Index

List of Figures

2.1. Asterisk vs. PBX architecture
2.2. The Asterisk 1.6.x release process
3.1. menuselect using the newt interface
3.2. menuselect using the curses interface
5.1. Relationship of sip.conf to extensions.conf
5.2. SIP dialogs
6.1. Relation between channel configuration files and contexts in the dialplan
8.1. Simplified SIP enterprise environment
9.1. The old days: dumb devices connect to a smart network
9.2. The situation today: smart devices connect through a dumb network
9.3. A balun
9.4. The BT plug used for analog PSTN connections in the UK (note only pins 2–5 are present)
9.5. The relationship between Linux, DAHDI, and Asterisk
10.1. Time delayed dialing with local channels
12.1. Request for Assignments form
14.1. Device state mappings
14.2. Extension state mappings
16.1. Relationships between func_odbc.conf, res_odbc.conf, /etc/odbc.ini (unixODBC), and the database connection
18.1. Enabling Gmail IMAP
19.1. Typical fax pass-through
20.1. Manager events
20.2. Manager actions
20.3. Manager actions that return a list of data
20.4. AsteriskGUI
20.5. Flash Operator Panel
22.1. Traditional call center
22.2. Remote hybrid system
22.3. Nondistributed Asterisk
22.4. Asterisk database integration, single server
22.5. Asterisk database integration, distributed database
22.6. Device state distribution with OpenAIS
22.7. Device state distribution with XMPP
22.8. Distributed queue infrastructure
23.1. DUNDi peer-to-peer request system
24.1. Graph of active Asterisk channels
24.2. Graph of active DAHDI channels
24.3. Graph of traffic on a network interface
25.1. FOP2
27.1. Asterisk as a PBX gateway
27.2. Find-me-follow-me
27.3. VoIP-enabling a legacy PBX
A.1. Tip and Ring
A.2. A simple sinusoidal (sine) wave
A.3. Sampling our sine wave using four bits
A.4. PCM encoded waveform
A.5. Plotted PCM signal
A.6. Delineated signal
A.7. The same waveform, on a higher-resolution overlay
A.8. The same waveform at double the resolution
A.9. Five-bit plotted PCM signal
A.10. Waveform delineated from five-bit PCM
A.11. Five-bit companding
A.12. Quantized and companded at 5-bit resolution
B.1. The SIP trapezoid
B.2. Call origination relationships of users, peers, and friends to Asterisk
C.1. Visual identification of PCI slots
C.2. One way you might connect a channel bank

List of Tables

2.1. Dialplan applications
2.2. Bridging modules
2.3. Call detail recording modules
2.4. Channel event logging modules
2.5. Channel drivers
2.6. Codec translators
2.7. Format interpreters
2.8. Dialplan functions
2.9. PBX modules
2.10. Resource modules
2.11. Addon modules
3.1. Software dependencies for Asterisk on Ubuntu Server and CentOS Server
4.1. asterisk.conf [directories] section
4.2. asterisk.conf [options] section
4.3. asterisk.conf [files] section
4.4. asterisk.conf [compat] section
4.5. modules.conf [modules] section
8.1. [general] section options for voicemail.conf
8.2. Advanced options for voicemail.conf
8.3. [zonemessages] section options for voicemail.conf
8.4. VoiceMail() optional arguments
8.5. VoiceMailMain() optional arguments
9.1. Internationalization cheat sheet
10.1. Delayed dialing using Local channels
11.1. features.conf [general] section
11.2. features.conf [featuremap] section
11.3. Page() options
12.1. Components of a SIP SRV record
12.2. NameMapping table
13.1. Available options for [general] section of queues.conf
13.2. Available options for defined queues in queues.conf
13.3. Options available under the [general] header in agents.conf
13.4. Options available under the [agents] header in agents.conf
13.5. Options related to prompt control timing within a queue
13.6. Options for controlling the playback of prompts within a queue
13.7. Options that can be set for joinempty or leavewhenempty
13.8. Mapping between old and new values for controlling when callers join and leave queues
13.9. Events in the Asterisk queue log
14.1. Virtual devices in Asterisk
15.1. A basic automated attendant
16.1. Summary of ast_hotdesk table
16.2. Table layout and description of ast_config
16.3. Minimal sippeers/sipusers realtime table
16.4. Example information used to populate the ast_sipfriends table
16.5. Realtime options in sip.conf
16.6. ODBC voicemail storage table layout
17.1. The Read() application
18.1. IMAP library compile time options
18.2. Additional IMAP voicemail options
18.3. jabber.conf options
19.1. Possible values for the faxdetect option in chan_dahdi.conf
19.2. Possible values for the faxdetect option in sip.conf
20.1. Options in the manager.conf [general] section
20.2. Options for [username] sections
20.3. Available values for AMI user account read/write options
20.4. Options in the http.conf [general] section
20.5. AMI development frameworks
21.1. AGI environment variables
21.2. AGI commands
21.3. AGI development frameworks
23.1. Options available in the [general] section
23.2. Options available in the [mappings] section
23.3. Options available for peer definitions in dundi.conf
24.1. logger.conf types
24.2. Default CDR fields
24.3. cdr.conf [general] section
24.4. cdr_adaptive_odbc.conf table configuration options
24.5. cdr.conf [csv] section options
24.6. cdr.conf [radius] section options
24.7. CEL event types
24.8. Defined but unused CEL event types
24.9. CEL event fields
24.10. cel.conf [general] section options
24.11. Event type to integer value mappings for the eventtype column
24.12. cel_odbc.conf table configuration
24.13. CEL variables available for use in [mappings]
24.14. Available options in the cel.conf [radius] section
A.1. DTMF digits
A.2. T-carrier circuits
A.3. OC circuits
B.1. Codec quick reference
C.1. System requirement guidelines

List of Examples

14.1. Custom “do not disturb” functionality using custom device states
14.2. jabber.conf for server1
14.3. jabber.conf for server2
19.1. Proof of concept email to fax gateway, fax.py
21.1. A sample AGI script, hello-world.sh
26.1. Log excerpts from account scanning

Foreword

John Todd

“There’s more than one way to do it.” I’ve been working with Asterisk for nine years, and this motto becomes more true with each release, each added feature, and each clever person who attacks a telecommunications problem with this incredibly flexible toolkit. I had the fantastic opportunity to work as the community manager for the Asterisk project at Digium for two years, which gave me one of the best vantage points for seeing the scope and imagination of the worldwide development effort pushing Asterisk forward. The depth and breadth of Asterisk is staggering—installations with hundreds of thousands of users are now commonplace. I see Asterisk making deep inroads into the financial, military, hospital, Fortune 100 enterprise, service provider, calling card, and mobile environments. In fact, there really aren’t any areas that I can think of where Asterisk isn’t now entrenched as the default choice when there is a need for a generalized voice tool to do “stuff.”

Asterisk has been emblematic of the way that open source software has changed business—and changed the world. My favorite part of any Asterisk project overview or conference talk is answering questions from someone new to Asterisk. As I continue to answer “Yes, it can do that,” I watch as the person’s eyes grow wide. The person starts to smile when he really starts to think about new things to do that his old phone or communication system couldn’t possibly have done. Radio integration? Sure. Streaming MP3s into or out of phone calls? OK. Emailing recorded conference calls to the participants? No problem. Integration of voice services into existing Java apps? Easy. Fax? Instant messages? IVRs? Video? Yes, yes, yes, yes.

The affirmative answers just keep flowing, and at that point, the best thing to do is to sit the person down and start showing him quick demonstrations of how Asterisk can be quickly deployed and developed. Then, I typically point the person toward the first edition of this book, Asterisk: The Future of Telephony, and set him loose. In just a few hours of development (or longer, of course), companies can change the way they deliver products to customers, nonprofits can overhaul how their users interact with the services they offer, and individuals can learn to build a perfectly customized call-handling system for their mobile and home phones. Asterisk scales up and down from individual lines to vast multiserver installations across multiple continents, but the way to start is to install the package, open up some of the configuration files, and start looking at examples.

From the basic beginnings of a PBX that Mark Spencer coded in 1999, the Asterisk project, with the help of thousands of developers, has moved from simply connecting phone calls and has matured into a platform that can handle voice, video, and text across dozens of virtual and physical interface types. The creation and growth of Asterisk were the inescapable results of the convergence of the four horsemen of the proprietary hardware apocalypse: open source development ideas, the Internet, Moore’s Law, and the plummeting costs of telecommunications. Even hardware vendors who may be frightened of Asterisk from a competitive standpoint are using it in their labs and core networks: almost all devices in the Voice-over-IP world are tested with Asterisk, making it the most compatible system across vendors.

At a recent communications conference I attended, the question “Who uses Asterisk?” was posed to the 1000-plus crowd. Nearly 75 percent raised their hands. Asterisk is a mature, robust software platform that permeates nearly every area of the telecommunications industry and has firmly cemented itself as one of the basic elements in any open source service delivery system. I tell people that it’s reasonable for anyone delivering services both via phone and web to want to add an “A” for Asterisk to the LAMP (Linux, Apache, MySQL, [Perl/Python/PHP]) acronym, making it LAAMP. (LAMA-P was another option, but for some reason nobody seems to like that version…I don’t know why.)

The expansion of this book to include more examples is something I’ve been looking forward to for some time. Asterisk is accessible because of the ease with which a novice can understand basic concepts. Then it continues to succeed as the novice becomes a pro and starts tapping the “other ways to do it” with more sophisticated implementations, using AGI with Java, Perl, or Python (or one of the other dozen or so supported languages), or even writing her own custom apps that work as compile-time options in Asterisk. But the first step for anyone, no matter what his or her skill level, is to look at examples of basic apps others have written. Leif, Jim, and Russell have not only put together a fantastic compendium of Asterisk methods, but they have also provided an excellent list of examples that will let the novice or expert quickly learn new techniques and “more than one way to do it.”

Asterisk 1.x is fantastically powerful and can solve nearly any voice problem you might have. For those of you building the most complex installations, there is even more interesting work—which will be realized quite soon—in development. The currently-in-development Asterisk SCF (Scalable Communications Framework) is being built as an adjunct open source project to allow Asterisk 1.x systems to scale in even more powerful ways—stay tuned, or better yet, get involved with the project as a developer.

If you’re an experienced Asterisk developer or integrator, I’m sure this book will have a few “Hey, that’s a neat way to do it!” moments for you, which is one of the joys of Asterisk. If this is your first project with Asterisk, I’d like to welcome you to the huge community of users and developers dedicated to making Asterisk better. This book will take you from a vague idea of doing something with computers and voice communication to the point where you’re able to stun everyone you know with your phone system’s sophisticated tricks.

You’re encouraged to participate in the online mailing lists, IRC chatrooms, and yearly AstriCon conference that provide up-to-the-second news and discussion surrounding the project. Without your interest, input, and code, Asterisk wouldn’t exist. Open source projects are hungry for new ideas and excellent contributions: I encourage you to be a participant in the Asterisk community, and I look forward to seeing your questions and examples in the next edition of this book.

Preface

This is a book for anyone who uses Asterisk.

Asterisk is an open source, converged telephony platform, which is designed primarily to run on Linux. Asterisk combines more than 100 years of telephony knowledge into a robust suite of tightly integrated telecommunications applications. The power of Asterisk lies in its customizable nature, complemented by unmatched standards compliance. No other PBX can be deployed in so many creative ways.

Applications such as voicemail, hosted conferencing, call queuing and agents, music on hold, and call parking are all standard features built right into the software. Moreover, Asterisk can integrate with other business technologies in ways that closed, proprietary PBXs can scarcely dream of.

Asterisk can appear quite daunting and complex to a new user, which is why documentation is so important to its growth. Documentation lowers the barrier to entry and helps people contemplate the possibilities.

Produced with the generous support of O’Reilly Media, Asterisk: The Definitive Guide is the third edition of what was formerly called Asterisk: The Future of Telephony. We decided to change the name because Asterisk has been so wildly successful that it is no longer an up-and-coming technology. Asterisk has arrived.

This book was written for, and by, members of the Asterisk community.

Audience

This book is intended to be gentle toward those new to Asterisk, but we assume that you’re familiar with basic Linux administration, networking, and other IT disciplines. If not, we encourage you to explore the vast and wonderful library of books that O’Reilly publishes on these subjects. We also assume you’re fairly new to telecommunications (both traditional switched telephony and the new world of Voice over IP).

However, this book will also be useful for the more experienced Asterisk administrator. We ourselves use the book as a reference for features that we haven’t used for a while.

Organization

The book is organized into these chapters:

Chapter 1, A Telephony Revolution

This is where we chop up the kindling and light the fire. Welcome to Asterisk!

Chapter 2, Asterisk Architecture

Discusses the file structure of an Asterisk system.

Chapter 3, Installing Asterisk

Covers obtaining, compiling, and installing Asterisk.

Chapter 4, Initial Configuration Tasks

Describes some initial configuration tasks for your new Asterisk system. This chapter goes over some of the configuration files required for all Asterisk installations.

Chapter 5, User Device Configuration

Provides guidance on configuring Asterisk to allow devices such as telephones to connect and make calls.

Chapter 6, Dialplan Basics

Introduces the heart of Asterisk, the dialplan.

Chapter 7, Outside Connectivity

Discusses how to configure Asterisk to connect to other systems, such as other Asterisk servers, Internet telephony service providers, or the plain old telephone network.

Chapter 8, Voicemail

Covers the usage of one of the most popular applications included with Asterisk, the voicemail system.

Chapter 9, Internationalization

Focuses on issues that an Asterisk administrator should be aware of when deploying a system outside of North America.

Chapter 10, Deeper into the Dialplan

Goes over some more advanced dialplan concepts.

Chapter 11, Parking and Paging

Describes the usage of two popular telephony features included with Asterisk, call parking and paging.

Chapter 12, Internet Call Routing

Covers techniques for routing calls between different administrative domains on the Internet.

Chapter 13, Automatic Call Distribution (ACD) Queues

Discusses how to build call queues in Asterisk.

Chapter 14, Device States

Introduces the concept of device states and how they can be used as presence indicators.

Chapter 15, The Automated Attendant

Covers how to build a menuing system using the Asterisk dialplan.

Chapter 16, Relational Database Integration

Discusses various ways that Asterisk can be integrated with a database.

Chapter 17, Interactive Voice Response

Goes over how Asterisk can be used to build applications that act on input provided by a caller.

Chapter 18, External Services

Provides instructions on how to connect to external services including LDAP, calendars, IMAP for voicemail, XMPP, Skype, and text-to-speech.

Chapter 19, Fax

Discusses the various options for integrating sending and receiving faxes with an Asterisk system.

Chapter 20, Asterisk Manager Interface (AMI)

Introduces a network API for monitoring and controlling an Asterisk system.

Chapter 21, Asterisk Gateway Interface (AGI)

Introduces the Asterisk API that allows call control to be implemented in any programming language.

Chapter 22, Clustering

Discusses a number of approaches for clustering multiple Asterisk servers together once the demands of a deployment exceed the capabilities of a single server.

Chapter 23, Distributed Universal Number Discovery (DUNDi)

Covers a peer-to-peer protocol native to Asterisk that can be used for call routing.

Chapter 24, System Monitoring and Logging

Introduces some of the interfaces available for logging and monitoring an Asterisk system.

Chapter 25, Web Interfaces

A survey of some of the web interfaces that complement an Asterisk installation.

Chapter 26, Security

Discusses some common security issues that Asterisk administrators should be aware of.

Chapter 27, Asterisk: A Future for Telephony

In conclusion, we discuss some of the things we expect to see from open source telephony in the near future.

Appendix A, Understanding Telephony

Explores the technologies in use in traditional telecom networks. This used to be a chapter in old versions of this book. Although not directly relevant to Asterisk we felt that it might still be useful to some readers, so we’ve left it in the book as an appendix.

Appendix B, Protocols for VoIP

Delves into all the particularities of Voice over IP. This was also a chapter in old versions of this book.

Appendix C, Preparing a System for Asterisk

Contains information you should be aware of and take into consideration when planning an Asterisk deployment.

Software

This book is focused on documenting Asterisk version 1.8; however, many of the conventions and much of the information in this book is version-agnostic. Linux is the operating system we have run and tested Asterisk on, and we have documented installation instructions for both CentOS (Red Hat Enterprise Linux–based) and Ubuntu (Debian-based) where they differ from each other.

Conventions Used in This Book

The following typographical conventions are used in this book:

Italic

Indicates new terms, URLs, email addresses, filenames, file extensions, pathnames, directories, and package names, as well as Unix utilities, commands, options, parameters, and arguments.

Constant width

Used to display code samples, file contents, command-line interactions, library names, and database commands.

Constant width bold

Indicates commands or other text that should be typed literally by the user. Also used for emphasis in code.

Constant width italic

Shows text that should be replaced with user-supplied values.

[ Keywords and other stuff ]

Indicates optional keywords and arguments.

{ choice-1 | choice-2 }

Signifies either choice-1 or choice-2.

Tip

This icon signifies a tip, suggestion, or general note.

Warning

This icon indicates a warning or caution.

Using Code Examples

This book is here to help you get your job done. In general, you may use the code in this book in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.

We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Asterisk: The Definitive Guide, Third Edition, by Leif Madsen, Jim Van Meggelen, and Russell Bryant (O’Reilly). Copyright 2011 Leif Madsen, Jim Van Meggelen, and Russell Bryant, 978-0-596-51734-2.”

If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at .

Safari Books Online

Note

When you see a Safari Books Online icon on the cover of your favorite technology book, that means the book is available online through the O’Reilly Network Safari Bookshelf.

Safari offers a solution that’s better than ebooks. It’s a virtual library that lets you easily search thousands of top tech books, cut and paste code samples, download chapters, and find quick answers when you need the most accurate, current information. Try it for free at http://safari.oreilly.com.

How to Contact Us

Please address comments and questions concerning this book to the publisher:

O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
(800) 998-9938 (in the United States or Canada)
(707) 829-0515 (international or local)
(707) 829-0104 (fax)

We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at:

http://oreilly.com/catalog/9780596517342

To comment or ask technical questions about this book, send email to:

For more information about our books, conferences, Resource Centers, and the O’Reilly Network, see our website at:

http://www.oreilly.com

Find us on Facebook: http://facebook.com/oreilly

Follow us on Twitter: http://twitter.com/oreillymedia

Watch us on YouTube: http://www.youtube.com/oreillymedia

Acknowledgments

To David Duffett, thanks for the excellent chapter on internationalization, which would not have been served well by being written by us North Americans.

Next, we want to thank our fantastic editor, Michael Loukides, for your patience with this third edition, which took too long to get off the ground, and many long months to finally get written. Mike offered invaluable feedback and found incredibly tactful ways to tell us to rewrite a section (or chapter) when it was needed, and make us think it was our idea. Mike built us up when we were down, and brought us back to earth when we got uppity. You are a master, Mike, and seeing how many books have received your editorial oversight contributes to an understanding of why O’Reilly Media is the success that it is.

Thanks also to Rachel Head (nee Rachel Wheeler), our copyeditor, who fixes all our silly grammar, spelling, and style mistakes (and the many Canadianisms that Leif and Jim feel compelled to include), and somehow leaves the result reading as if it was what we wrote in the first place. Copyeditors are the unsung heroes of publishing, and Rachel is one of the very best.

Also thanks to Teresa Elsey, our production editor, and the rest of the unsung heroes in O’Reilly’s production department.

These are the folks that take our book and make it an O’Reilly book.

During the course of writing this book, we had the pleasure of being able to consult with many people with specific experience in various areas. Their generous contributions of time and expertise were instrumental in our research. Thanks to Randy Resnick, organizer of the VoIP User Group; Kevin Fleming of Digium; Lee Howard, author of iaxmodem and hylafax; Joshua Colp of Digium; Phillip Mullis of the Toronto Asterisk Users Group; Allison Smith, the Voice of Asterisk; Flavio E. Goncalves, author of books on Asterisk, OpenSER, and OpenSIPS; J. Oquendo, Security Guru; Tzafrir Cohen, font of knowledge about security and lots of other stuff; Jeff Gehlbach, for SNMP; Ovidiu Sas, for your encyclopedic knowlege of SIP; Tomo Takebe, for some SMDI help; Steve Underwood, for help with fax and spandsp; and Richard Genthner and John Covert, for helping with LDAP.

A special thanks should also go to John Todd for being one of the first to write comprehensive Asterisk how-tos, all those years ago, and for all the many other things you do (and have done) for the Asterisk community.

Thanks to Sean Bright, Ed Guy, Simon Ditner, and Paul Belanger for assisting us with clarifying best practices for user and group policies for Asterisk installation. In the past it was common to just install Asterisk with root permissions, but we have elected to describe an installation process that is more in keeping with Linux best practices,[2] and these fine gents contributed to our discussions on that.

Kudos to all the folks working on the FreeSWITCH, YATE, SER, Kamailio, OpenSIPS, SER, sipXecs, Woomera, and any other open source telecom projects, for stimulating new thoughts, and for pushing the envelope.

Everyone in the Asterisk community also needs to thank Jim Dixon for creating the first open source telephony hardware interfaces, starting the revolution, and giving his creations to the community at large.

Finally, and most importantly, thanks go to Mark Spencer, the original author of Asterisk and founder of Digium, for Asterisk, for Pidgin (http://www.pidgin.im), and for contributing his creations to the open source community. Asterisk is your legacy!

Leif Madsen

It sort of amazes me where I started with Asterisk, and where I’ve gone with Asterisk. In 2002, while attending school, a bunch of my friends and myself were experimenting with voice over the Internet using Microsoft’s MSN product. It worked quite well, and allowed us to play video games while conversing with each other—at least, until we wanted to add a third participant. So, I went out searching for some software that could handle multiple voices (the word was conferencing, but I didn’t even know that at the time, having had little exposure to PBX platforms). I searched the Internet but didn’t find anything in particular I liked (or that was free). I turned to IRC and explained what I was looking for. Someone (I wish I knew who) mentioned that I should check out some software called Asterisk (he presumably must have thought I was looking for MeetMe(), which I was).

Having the name, I grabbed the software and started looking at what it could do. Incredibly, the functionality I was looking for, which I thought would be the entirety of the software, was only one component in a sea of functionality. And having run a BBS for years prior to going to college, the fact that I could install a PCI card and connect it to the phone network was not lost on me. After a couple of hours of looking at the software and getting it compiled, I started telling one of my teachers about the PCI cards and how maybe we could get some for the classroom for labs and such (our classroom had 30 computers at 10 tables of 3). He liked the idea and started talking to the program coordinator, and within about 30 minutes an order had been placed for 20 cards. Pretty amazing considering they were TDM400Ps decked out with four daughter cards, and they had only heard about them an hour prior to that.

Then the obsession began. I spent every extra moment of that semester with a couple of computers dedicated to Asterisk use. In those two months, I learned a lot. Then we had a co-op break. I didn’t find any work immediately, so I moved home and continued working on Asterisk, spending time on IRC, reading through examples posted by John Todd, and just trying to wrap my head around how the software worked. Luckily I had a lot of help on IRC (for these were the days prior to any documentation on Asterisk), and I learned a lot more during that semester.

Seeing that the people who took a great interest in Asterisk at the time had a strong sense of community and wanted to contribute back, I wanted to do the same. Having no practical level of coding knowledge, I decided documentation would be something useful to start doing. Besides, I had been writing a lot of papers at school, so I was getting better at it. One night I put up a website called The Asterisk Documentation Assigned (TADA) and started writing down any documentation I could. A couple of weeks later Jared Smith and I started talking, and started the Asterisk Documentation Project (http://www.asteriskdocs.org), with the goal of writing an Asterisk book for the community. That project became the basis of the first edition of this book, Asterisk: The Future of Telephony.

Nine years later, I’m still writing Asterisk documentation and have become the primary bug marshal and release manager for the Asterisk project, spoken at every single AstriCon since 2004 (at which Jared and I spoke about the Asterisk Documentation Project; I still have the AsteriskDocs magnet his wife made), and become a consultant specializing in database integration (thanks Tilghman for func_odbc) and clustering (thanks Mark Spencer for DUNDi). I really love Asterisk, and all that it’s allowed me to do.

First, thanks to my parents Rick and Carol, for the understanding and support in everything I’ve done in my life. From the first computer they purchased for far too much money when I was in grade 6 (I started taking an interest in computers in grade 2 using a Commodore 64, and they got me a computer after a parent-teacher interview a few years later) to letting me use the home phone line for my BBS endeavors (and eventually getting me my own phone line), and everything else they have ever done for me, I can never thank them enough. I love you both more than you’ll ever imagine.

Thanks to my Grandma T for letting me use her 286 during the years when I didn’t have a computer at home, and for taking me shopping every year on my birthday for 15 years. Love lots!

To my beautiful wife, Danielle, for setting the alarm every morning before she left for work, letting me sleep those extra 10 minutes before starting on this book, and understanding when I had to work late because I went past my 9 A.M. stop-writing time, thank you and I love you so much.

There are so many people who help me and teach me new things every day, but the most influential on my life in Asterisk are the following: Mark Spencer for writing software that has given me a fantastic career, John Todd for his early examples, Brian K. West for his early help and enthusiasm on IRC, Steve Sokol and Olle Johansson for flying me to my first AstriCon (and subsequent ones!) and letting me be part of the first Asterisk training classes, Jared Smith for helping start the documentation project and doing all the infrastructure that I could never have done, Jim Van Meggelen for joining in early on the project and teaching me new ways to look at life, and Russell Bryant for being an amazing project leader and easy to work with every day, and for not holding a grudge about the bush.

Jim Van Meggelen

When we set out to write the very first edition of this book over five years ago, we were confident that Asterisk was going to be a huge success. Now, a half-decade later, we’ve written this third edition of what the worldwide Asterisk community calls “The Asterisk Book,” and we’ve matured from revolutionaries into Asterisk professionals.

Asterisk has proven that open source telecom is a lasting idea, and the open source telecom landscape is nowadays complemented by more than just Asterisk. Projects like Freeswitch, sipXecs (from SipFoundry), OpenSER/Kamailio/OpenSIPS, and many, many more (and more to come) help to round out the ecosystem.

I want to take this opportunity to thank my very good friend Leif Madsen, who has been with me through all three editions. In our daily lives we don’t always have many opportunities to work with each other (or even grab a pint, these days!), and it’s always a delight to work with you. I also want to thank Russell Bryant, who joined us for this edition, and whose dedication to this project and the Asterisk project in general is an inspiration to me. You’re a Renaissance man, Russell. To Jared Smith, who helped found the Asterisk Documentation Project and coauthored the first two editions with Leif and me (but has since moved on to the Fedora project), I can only say: Asterisk’s loss is Fedora’s gain.

I would like to thank my business partners at Core Telecom Innovations and iConverged LLC, without whom I could not do all the cool things I get to do in my professional career.

I would like to thank all my friends in the improv community, for helping me to keep laughing at all the challenges that life presents.

Thanks to all my family, who bring love into my life.

Finally, thanks to you, the Asterisk community. This book is our gift to you. We hope you enjoy reading it as much as we’ve enjoyed writing it.

Russell Bryant

I started working on Asterisk in 2004. I was a student at Clemson University and was working as a co-op engineer at ADTRAN in Huntsville, Alabama. My first job at ADTRAN was working in the Product Qualification department. I remember working with Keith Morgan to use Asterisk as a VoIP traffic generator for testing QoS across a router test network. Meanwhile, a fellow co-op and friend, Adam Schreiber, introduced me to Mark Spencer. Over the next six months, I immersed myself in Asterisk. I learned as much as I could about Asterisk, telephony, and C programming. When Asterisk 1.0 was released in the fall of 2004, I was named the release maintainer.

At the beginning of 2005, I was hired by Digium to continue my work on Asterisk professionally. I have spent the past six amazing years working with Digium to improve Asterisk. I have worked as a software developer, a software team lead, and now as the engineering manager of the Asterisk development team. I am extremely grateful for the opportunity to contribute to so many areas of the Asterisk project. There are many people that deserve thanks for the support they have provided along the way.

To my wife, Julie, I cannot thank you enough for all the love and support you have given me. Thank you for keeping my life balanced and happy. You are the best. I love you!

To my parents, thank you for giving me so many great opportunities in my life to explore different things and find what I really enjoy. You taught me to work hard and never give up.

To Leif and Jim, thank you for your invitation to contribute to this book. It has been a fun project, largely due to the pleasure of working with the two of you. Thanks for the laughs and for your dedication to this book as a team effort.

I have learned a lot from many people at Digium. There are three people who stand out the most as my mentors: Mark Spencer, Kevin P. Fleming, and David Deaton. Thank you all for going the extra mile to teach me along the way. I am extremely grateful.

To the software development team at Digium, thank you for being such an amazing team to work with. Your dedication and brilliance play a huge part in the success of Asterisk and make Digium a great place to work.

To Travis Axtell, thank you for your help in my early days of learning about Linux and for being a good friend.

To my dogs, Chloe and Baxter, thanks for keeping me company while I worked on the book every morning.

To all of my friends and family, thank you for your love, support, and fun times.

To the entire Asterisk community, thank you for using, enjoying, and contributing to Asterisk. We hope you enjoy the book!



[1] We tried wherever possible to include the contributors’ names, but in some cases could not, and therefore included their handles instead.

[2] Without starting a holy war!

Chapter 1. A Telephony Revolution

First they ignore you, then they laugh at you, then they fight you, then you win.

Mahatma Gandhi

When we first set out—nearly five years ago—to write a book about Asterisk, we confidently predicted that Asterisk would fundamentally change the telecommunications industry. Today, the revolution we predicted is all but complete. Asterisk is now the most successful private branch exchange (PBX) in the world, and is an accepted (albeit perhaps not always loved) technology in the telecom industry.

Unfortunately, over the past five years the telecom industry has continued to lose its way. The methods by which we communicate have changed. Whereas 20 years ago phone calls were the preferred way to converse across distances, the current trend is to message via text (email, IM, etc.). The phone call is seen as a bit of a dead thing, especially by up-and-coming generations.

Asterisk remains pretty awesome technology, and we believe it is still one of the best hopes for any sort of sensible integration between telecom and all the other technologies businesses might want to interconnect with.

With Asterisk, no one is telling you how your phone system should work, or what technologies you are limited to. If you want it, you can have it. Asterisk lovingly embraces the concept of standards compliance, while also enjoying the freedom to develop its own innovations. What you choose to implement is up to you—Asterisk imposes no limits.

Naturally, this incredible flexibility comes with a price: Asterisk is not a simple system to configure. This is not because it’s illogical, confusing, or cryptic; on the contrary, it is very sensible and practical. People’s eyes light up when they first see an Asterisk dialplan and begin to contemplate the possibilities. But when there are literally thousands of ways to achieve a result, the process naturally requires extra effort. Perhaps it can be compared to building a house: the components are relatively easy to understand, but a person contemplating such a task must either a) enlist competent help or b) develop the required skills through instruction, practice, and a good book on the subject.

Asterisk and VoIP: Bridging the Gap Between Traditional and Network Telephony

Voice over IP (VoIP) is often thought of as little more than a method of obtaining free long-distance calling. The real value (and—let’s be honest—challenge as well) of VoIP is that it allows voice to become nothing more than another application in the data network.

It sometimes seems that we’ve forgotten that the purpose of the telephone is to allow people to communicate. It is a simple goal, really, and it should be possible for us to make it happen in far more flexible and creative ways than are currently available to us. Technologies such as Asterisk lower the barriers to entry.

The Zapata Telephony Project

When the Asterisk project was started (in 1999), there were other open-source telephony projects in existence. However, Asterisk, in combination with the Zapata Telephony Project, was able to provide public switched telephone network (PSTN) interfaces, which represented an important milestone in transitioning the software from something purely network-based to something more practical in the world of telecom at that time, which was PSTN-centric.

The Zapata Telephony Project was conceived of by Jim Dixon, a telecommunications consulting engineer who was inspired by the incredible advances in CPU speeds that the computer industry has now come to take for granted. Dixon’s belief was that far more economical telephony systems could be created if a card existed that had nothing more on it than the basic electronic components required to interface with a telephone circuit. Rather than having expensive components on the card, digital signal processing (DSP)[3] would be handled in the CPU by software. While this would impose a tremendous load on the CPU, Dixon was certain that the low cost of CPUs relative to their performance made them far more attractive than expensive DSPs, and, more importantly, that this price/performance ratio would continue to improve as CPUs continued to increase in power.

Like so many visionaries, Dixon believed that many others would see this opportunity, and that he merely had to wait for someone else to create what to him was an obvious improvement. After a few years, he noticed that not only had no one created these cards, but it seemed unlikely that anyone was ever going to. At that point it was clear that if he wanted a revolution, he was going to have to start it himself. And so the Zapata Telephony Project was born:

Since this concept was so revolutionary, and was certain to make a lot of waves in the industry, I decided on the Mexican revolutionary motif, and named the technology and organization after the famous Mexican revolutionary Emiliano Zapata. I decided to call the card the “tormenta” which, in Spanish, means “storm,” but contextually is usually used to imply a big storm, like a hurricane or such.[4]

Perhaps we should be calling ourselves Asteristas. Regardless, we owe Jim Dixon a debt of thanks, partly for thinking this up and partly for seeing it through, but mostly for giving the results of his efforts to the open source community. As a result of Jim’s contribution, Asterisk’s PSTN engine came to be.

Over the years, the Zapata Telephony interface in Asterisk has been modified and improved. The Digium Asterisk Hardware Device Interface (DAHDI) Telephony interface in use today is the offspring of Jim Dixon’s contribution.

Massive Change Requires Flexible Technology

Every PBX in existence suffers from shortcomings. No matter how fully featured it is, something will always be left out, because even the most feature-rich PBX will always fail to anticipate the creativity of the customer. A small group of users will desire an odd little feature that the design team either did not think of or could not justify the cost of building, and, since the system is closed, the users will not be able to build it themselves.

If the Internet had been thusly hampered by regulation and commercial interests, it is doubtful that it would have developed the wide acceptance it currently enjoys. The openness of the Internet meant that anyone could afford to get involved. So, everyone did. The tens of thousands of minds that collaborated on the creation of the Internet delivered something that no corporation ever could have.[5]

As with many other open source projects, such as Linux and so much of the critical software running the Internet, the development of Asterisk was fueled by the dreams of folks who knew that there had to be something more than what traditional industries were producing. These people knew that if one could take the best parts of various PBXs and separate them into interconnecting components—akin to a boxful of LEGO bricks—one could begin to conceive of things that would not survive a traditional corporate risk-analysis process. While no one can seriously claim to have a complete picture of what this thing should look like, there is no shortage of opinions and ideas.[6]

Many people new to Asterisk see it as unfinished. Perhaps these people can be likened to visitors to an art studio, looking to obtain a signed, numbered print. They often leave disappointed, because they discover that Asterisk is the blank canvas, the tubes of paint, the unused brushes waiting.[7]

Even at this early stage in its success, Asterisk is nurtured by a greater number of artists than any other PBX. Most manufacturers dedicate no more than a few developers to any one product; Asterisk has scores. Most proprietary PBXs have a worldwide support team comprising a few dozen real experts; Asterisk has hundreds.

The depth and breadth of the expertise that surrounds this product is unmatched in the telecom industry. Asterisk enjoys the loving attention of old telco guys who remember when rotary dial mattered, enterprise telecom people who recall when voicemail was the hottest new technology, and data communications geeks and coders who helped build the Internet. These people all share a common belief—that the telecommunications industry needs a proper revolution.[8]

Asterisk is the catalyst.

Asterisk: The Hacker’s PBX

Telecommunications companies that choose to ignore Asterisk do so at their peril. The flexibility it delivers creates possibilities that the best proprietary systems can scarcely dream of. This is because Asterisk is the ultimate hacker’s PBX.

The term hacker has, of course, been twisted by the mass media into meaning “malicious cracker.” This is unfortunate, because the term actually existed long before the media corrupted its meaning. Hackers built the networking engine that is the Internet. Hackers built the Apple Macintosh and the Unix operating system. Hackers are also building your next telecom system. Do not fear; these are the good guys, and they’ll be able to build a system that’s far more secure than anything that exists today. Rather than being constricted by the dubious and easily cracked security of closed systems, the hackers will be able to quickly respond to changing trends in security and fine-tune the telephone system in response to both corporate policy and industry best practices.

Like other open source systems, Asterisk will be able to evolve into a far more secure platform than any proprietary system, not in spite of its hacker roots, but rather because of them.

Asterisk: The Professional’s PBX

Never in the history of telecommunications has a system so suited to the needs of business been available, at any price. Asterisk is an enabling technology, and as with Linux, it will become increasingly rare to find an enterprise that is not running some version of Asterisk, in some capacity, somewhere in the network, solving a problem as only Asterisk can.

This acceptance is likely to happen much faster than it did with Linux, though, for several reasons:

  • Linux has already blazed the trail that led to open source acceptance. Asterisk is following that lead.

  • The telecom industry is crippled, with no leadership being provided by the giant industry players. Asterisk has a compelling, realistic, and exciting vision.

  • End users are fed up with incompatible and limited functionality, and horrible support. Asterisk solves the first two problems; entrepreneurs and the community are addressing the latter.

The Asterisk Community

One of the compelling strengths of Asterisk is the passionate community that developed and supports it. This community, led by the fine folks at Digium, is keenly aware of the cultural significance of Asterisk and has an optimistic view of the future.

One of the more powerful side effects of the Asterisk community’s energy is the cooperation it has spawned among telecommunications, networking, and information technology professionals who share a love for this phenomenon. While these cadres have traditionally been at odds with each other, in the Asterisk community they delight in each others’ skills. The significance of this cooperation cannot be underestimated.

If the dream of Asterisk is to be realized, the community must continue to grow—yet one of the key challenges that the community currently faces is a rapid influx of new users. The members of the existing community, having birthed this thing called Asterisk, are generally welcoming of new users, but they’ve grown impatient with being asked the kinds of questions whose answers can often be obtained independently, if one is willing to devote some time to research and experimentation.

Obviously, new users do not fit any particular kind of mold. While some will happily spend hours experimenting and reading various blogs describing the trials and tribulations of others, many people who have become enthusiastic about this technology are completely uninterested in such pursuits. They want a simple, straightforward, step-by-step guide that’ll get them up and running, followed by some sensible examples describing the best methods of implementing common functionality (such as voicemail, auto attendants, and the like).

To the members of the expert community, who (correctly) perceive that Asterisk is like a web development language, this approach doesn’t make any sense. To them, it’s clear that you have to immerse yourself in Asterisk to appreciate its subtleties. Would one ask for a step-by-step guide to programming and expect to learn from it all that a language has to offer?

Clearly, there’s no one approach that’s right for everyone. Asterisk is a different animal altogether, and it requires a totally different mind-set. As you explore the community, though, be aware that it includes people with many different skill sets and attitudes. Some of these folks do not display much patience with new users, but that’s often due to their passion for the subject, not because they don’t welcome your participation.

The Asterisk Mailing Lists

As with any community, there are places where members of the Asterisk community meet to discuss matters of mutual interest. Of the mailing lists you will find at http://lists.digium.com, these three are currently the most important:

Asterisk-Biz

Anything commercial with respect to Asterisk belongs in this list. If you’re selling something Asterisk-related, sell it here. If you want to buy an Asterisk service or product, post here.

Asterisk-Dev

The Asterisk developers hang out here. The purpose of this list is the discussion of the development of the software that is Asterisk, and its participants vigorously defend that purpose. Expect a lot of heat if you post anything to this list not specifically relating to programming or development of the Asterisk code base. General coding questions (such as queries on interfacing with AGI or AMI) should be directed to the Asterisk-Users list.

Warning

The Asterisk-Dev list is not second-level support! If you scroll through the mailing list archives, you’ll see this is a strict rule. The Asterisk-Dev mailing list is about discussion of core Asterisk development, and questions about interfacing your external programs via AGI or AMI should be posted on the Asterisk-Users list.

Asterisk-Users

This is where most Asterisk users hang out. This list generates several hundred messages per day and has over ten thousand subscribers. While you can go here for help, you are expected to have done some reading on your own before you post a query.

Asterisk Wiki Sites

The Asterisk Wiki (which exists in large part due to the tireless efforts of James Thompsonthanks James!) is a source of much enlightenment and confusion. Another important resource is the community-maintained repository of VoIP knowledge at http://www.voip-info.org, which contains a truly inspiring cornucopia of fascinating, informative, and frequently contradictory information about many subjects, just one of which is Asterisk. Since Asterisk documentation forms by far the bulk of the information on this website,[9] and it probably contains more Asterisk knowledge than all other sources put together (with the exception of the mailing list archives), it is a popular place to go for Asterisk knowledge.

An important new wiki project is the official Asterisk Wiki, found at http://wiki.asterisk.org. While not yet as full of content as voip-info.org, this wiki will be more formally supported and is therefore more likely to contain information that is kept current and accurate.

The IRC Channels

The Asterisk community maintains Internet Relay Chat (IRC) channels on irc.freenode.net. The two most active channels are #asterisk and #asterisk-dev.[10] To cut down on spam-bot intrusions, both of these channels now require registration to join.[11]

Asterisk User Groups

Over the past decade, in many cites around the world, lonely Asterisk users began to realize that there were other like-minded people in their towns. Asterisk User Groups (AUGs) began to spring up all over the place. While these groups don’t have any official affiliation with each other, they generally link to one anothers’ websites and welcome members from anywhere. Type “Asterisk User Group” into Google to track down one in your area.

The Asterisk Documentation Project

The Asterisk Documentation Project was started by Leif Madsen and Jared Smith, but several people in the community have contributed.

The goal of the documentation project is to provide a structured repository of written work on Asterisk. In contrast with the flexible and ad hoc nature of the Wiki, the Docs project is passionate about building a more focused approach to various Asterisk-related subjects.

As part of the efforts of the Asterisk Docs project to make documentation available online, this book is available at the http://www.asteriskdocs.org website, under a Creative Commons license.

The Business Case

It is very rare to find businesses these days that do not have to reinvent themselves every few years. It is equally rare to find a business that can afford to replace its communications infrastructure each time it goes in a new direction. Today’s businesses need extreme flexibility in all of their technology, including telecom.

In his book Crossing the Chasm (HarperBusiness), Geoffrey Moore opines, “The idea that the value of the system will be discovered rather than known at the time of installation implies, in turn, that product flexibility and adaptability, as well as ongoing account service, should be critical components of any buyer’s evaluation checklist.” What this means, in part, is that the true value of a technology is often not known until it has been deployed.

How compelling, then, to have a system that holds at its very heart the concept of openness and the value of continuous innovation.

Conclusion

So where to begin? Well, when it comes to Asterisk, there is far more to talk about than we can fit into one book. This book can only lay down the basics, but from this foundation you will be able to come to an understanding of the concept of Asterisk—and from that, who knows what you will build?



[3] The term DSP also means digital signal processor, which is a device (usually a chip) that is capable of interpreting and modifying signals of various sorts. In a voice network, DSPs are primarily responsible for encoding, decoding, and transcoding audio information. This can require a lot of computational effort.

[4] Jim Dixon, “The History of Zapata Telephony and How It Relates to the Asterisk PBX” (http://www.asteriskdocs.org/modules/tinycontent/index.php?id=10).

[5] We realize that the technology of the Internet formed out of government and academic institutions, but what we’re talking about here is not the technology of the Internet so much as the cultural phenomenon of it, which exploded in the early ’90s.

[6] Between the releases of Asterisk 1.2 and Asterisk 1.4, over 4,000 updates were made to the code in the SVN repository. Between the releases of Asterisk 1.4 and 1.8, over 10,000 updates were made.

[7] It should be noted that these folks need not leave disappointed. Several projects have arisen to lower the barriers to entry for Asterisk. By far the most popular and well known is the FreePBX interface (and the multitude of projects based on it). These interfaces (check out http://www.voip-info.org/wiki/view/Asterisk+GUI for an idea of how many there are) do not make it easier to learn Asterisk, because they separate you from the platform or dialplan configuration, but many of them will deliver a working PBX to you much faster than the more hands-on approach we employ in this book.

[8] The telecom industry has been predicting a revolution since before the crash; time will tell how well it responds to the open source revolution.

[9] More than 30%, at last count.

[10] The #asterisk-dev channel is for the discussion of changes to the underlying code base of Asterisk and is also not second-tier support. Discussions related to programming external applications that interface with Asterisk via AGI or AMI are meant to be in #asterisk.

[11] To register, run /msg nickserv help when you connect to the service via your favorite IRC client.

Chapter 2. Asterisk Architecture

First things first, but not necessarily in that order.

Doctor Who

Asterisk is very different from other, more traditional PBXs, in that the dialplan in Asterisk treats all incoming channels in essentially the same manner.

In a traditional PBX, there is a logical difference between stations (telephone sets) and trunks (resources that connect to the outside world). This means, for example, that you can’t install an external gateway on a station port and route external calls to it without requiring your users to dial the extension number first. Also, the concept of an off-site resource (such as a reception desk) is much more difficult to implement on a traditional PBX, because the system will not allow external resources any access to internal features.[12]

Asterisk, on the other hand, does not have an internal concept of trunks or stations. In Asterisk, everything that comes into or goes out of the system passes through a channel of some sort. There are many different kinds of channels; however, the Asterisk dialplan handles all channels in a similar manner, which means that, for example, an internal user can exist on the end of an external trunk (e.g., a cell phone) and be treated by the dialplan in exactly the same manner as that user would be if she were on an internal extension. Unless you have worked with a traditional PBX, it may not be immediately obvious how powerful and liberating this is. Figure 2-1 illustrates the differences between the two architectures.

Figure 2.1. Asterisk vs. PBX architecture

Asterisk vs. PBX architecture

Modules

Asterisk is built on modules. A module is a loadable component that provides a specific functionality, such as a channel driver (for example, chan_sip.so), or a resource that allows connection to an external technology (such as func_odbc.so). Asterisk modules are loaded based on the /etc/asterisk/modules.conf file. We will discuss the use of many modules in this book. At this point we just want to introduce the concept of modules, and give you a feel for the types of modules that are available.

It is actually possible to start Asterisk without any modules at all, although in this state it will not be capable of doing anything. It is useful to understand the modular nature of Asterisk in order to appreciate the architecture.

Note

You can start Asterisk with no modules loaded by default and load each desired module manually from the console, but this is not something that you’d want to put into production; it would only be useful if you were performance-tuning a system where you wanted to eliminate everything not required by your specific application of Asterisk.

The types of modules in Asterisk include the following:

  • Applications

  • Bridging modules

  • Call detail recording (CDR) modules

  • Channel event logging (CEL) modules

  • Channel drivers

  • Codec translators

  • Format interpreters

  • Dialplan functions

  • PBX modules

  • Resource modules

  • Addons modules

  • Test modules

In the following sections we will list each module available within these categories, briefly identify its purpose, and give our opinion on its relative popularity and/or importance (while some modules are proven and deservedly popular, others are quite old, are barely ever used anymore, and are only maintained for the purpose of backward-compatibility). The details of how specific modules work will be covered in various chapters throughout the book, depending on what the module is and what it does. Some modules will be covered thoroughly; others may not be covered at all.

Regarding the Popularity/Status column in the tables that follow, the following list contains our opinions with respect to the meanings we have chosen (your mileage may vary):

Insignificant

This module is ancient history. If you use it, be aware that you are mostly on your own when it comes to any sort of community support.

Unreliable

This module is new or experimental, and is not suitable for production.

Useful

This module is current, maintained, popular, and recommended.

Usable

This module works but may be incomplete or unpopular, and/or is not recommended by the authors.

New

This module is quite new, and its completeness and popularity are difficult to gauge at this time.

Deprecated

This module has been replaced by something that is considered superior.

Limited

This module has limitations that may make it unsuitable to your requirements.

Essential

This module is one you’ll never want to be without.

And now, without further ado, let’s take a look at the modules, grouped by module type.

Applications

Dialplan applications are used in extensions.conf to define the various actions that can be applied to a call. The Dial() application, for example, is responsible for making outgoing connections to external resources and is arguably the most important dialplan application. The available applications are listed in Table 2.1, “Dialplan applications”.

Table 2.1. Dialplan applications

NamePurposePopularity/Status
app_adsiprog Loads Analog Display Services Interface (ADSI) scripts into compatible analog phonesInsignificant
app_alarmreceiver Supports receipt of reports from alarm equipmentInsignificant
app_amd Detects answering machinesUnreliable
app_authenticate Compares dual-tone multi-frequency (DTMF) input against a provided string (password)Useful
app_cdr Writes ad hoc record to CDRUseful
app_celgenuserevent Generates user-defined events for CELNew
app_chanisavail Checks the status of a channelUnreliable
app_channelredirect Forces another channel into a different part of the dialplanUseful
app_chanspy Allows a channel to listen to audio on another channelUseful
app_confbridge Provides conferencing (new version)New—not fully featured yet
app_controlplayback Plays back a prompt and offers fast forward and rewind functionsUseful
app_dahdibarge Allows barging in on a DAHDI channelDeprecated—see app_chanspy
app_dahdiras Creates a RAS server over a DAHDI channel (no modem emulation)Insignificant
app_db Used to add/change/delete records in Asterisk’s built-in Berkeley databaseDeprecated—see func_db
app_dial Used to connect channels together (i.e., make phone calls)Essential
app_dictate Plays back a recording and offers start/stop functionsUseful
app_directed_pickup Answers a call for another extensionUseful
app_directory Presents the list of names from voicemail.confUseful
app_disa Provides dialtone and accepts DTMF inputUseful[a]
app_dumpchan Dumps channel variables to Asterisk command-line interface (CLI)Useful
app_echo Loops received audio back to source channelUseful
app_exec Contains Exec(), TryExec(), and ExecIf(); executes a dialplan application based on conditionsUseful
app_externalivr Controls Asterisk as with an AGI, only asynchronouslyUseful
app_fax Provides SendFax() and ReceiveFax()Useful[b]
app_festival Enables basic text to speech using Festival TTS engineUsable
app_flash Performs a hook-switch flash on channels (primarily analog)Useful
app_followme Performs find me/follow me functionality based on followme.confUseful
app_forkcdr Starts new CDR record on current callUsable
app_getcpeid Gets the ADSI CPE IDInsignificant
app_ices Sends audio to an Icecast serverUsable
app_image Transmits an image to supported devicesLimited
app_ivrdemo Sample application for developersInsignificant
app_jack Works with JACK Audio Connection Kit to share audio between compatible applicationsUseful
app_macro Triggers dialplan macrosDeprecated—see GoSub()
app_meetme Provides multiparty conferencingUseful—fully featured
app_milliwatt Generates 1004-Hz tone for testing loss on analog circuitsUseful
app_minivm Provides primitive functions to allow you to build your own voicemail application in dialplanUsable
app_mixmonitor Records both sides of a call and mixes them togetherUseful
app_morsecode Generates Morse codeUsable
app_mp3 Uses mpg123 to play an MP3Insignificant
app_nbscat Streams audio from Network Broadcast Stream (NBS)Insignificant
app_originate Allows origination of a callUseful
app_osplookup Performs Open Settlement Protocol (OSP) lookupUsable
app_page Creates multiple audio connections to specified devices for public address (paging)Useful
app_parkandannounce Enables automated announcing of parked callsUsable
app_playback Plays a file to the channel (does not accept input)Useful
app_playtones Plays pairs of tones of specified frequenciesUseful
app_privacy Requests input of caller’s phone number if no CallerID is receivedInsignificant
app_queue Provides Automatic Call Distribution (ACD)Useful
app_read Requests input of digits from callers and assigns input to a variableUseful
app_readexten Requests input of digits from callers and passes call to a designated extension and contextUsable
app_readfile Loads contents of a text file into a channel variableDeprecated—see the FILE() function in func_env
app_record Records received audio to a fileUseful
app_rpt Provides a method to interface with an audio board for the app_rpt projectLimited
app_sayunixtime Plays back time in specified formatUseful
app_senddtmf Transmits DTMF to calling partyUseful
app_sendtext Sends a text string to compatible channelsInsignificant
app_setcallerid Sets CallerID on a channelDeprecated—see func_callerid
app_skel Sample application for developersUseful[c]
app_sms Sends SMS message in compatible countriesLimited
app_softhangup Requests hangup of channelUseful
app_speech_utils Provides utilities relating to speech recognitionUseful[d]
app_stack Provides Gosub(), GoSubIf(), Return(), StackPop(), LOCAL(), and LOCAL_PEEK()Essential
app_system Executes commands in a Linux shellUseful
app_talkdetect Similar to app_background, but allows for any received audio to interrupt playbackUseful
app_test Client/server testing applicationUsable
app_transfer Performs a transfer on the current channelUseful
app_url Passes a URI to the called channelLimited
app_userevent Generates a custom event in the Asterisk Manager Interface (AMI)Useful
app_verbose Generates a custom event in the Asterisk CLIUseful
app_voicemail Provides voicemailEssential
app_waitforring Waits for a RING signaling event (not to be confused with RINGING); most likely unnecessary, as only chan_dahdi with analog channels where ringing is received (such as an FXO port) generates the RING signaling eventInsignificant
app_waitforsilence Includes WaitForSilence() and WaitForNoise(); listens to the incoming channel for a specified number of milliseconds of noise/silenceUseful
app_waituntil Waits until current Linux epoch matches specified epochUseful
app_while Includes While(), EndWhile(), ExitWhile(), and ContinueWhile(); provides while-loop functionality in the dialplanUseful
app_zapateller Generates SIT tone to discourage telemarketersUsable

[a] The use of (DISA) is considered to be a security risk.

[b] Requires a suitable DSP engine to handle encoding/decoding of fax signaling (see Chapter 19, Fax).

[c] If you are a developer.

[d] Requires an external speech recognition application.


Bridging Modules

Bridging modules are new in Asterisk 1.8: they perform the actual bridging of channels in the new bridging API. Each provides different features, which get used in different situations depending on what a bridge needs. These modules, listed in Table 2.2, “Bridging modules”, are currently only used for (and are essential to) app_confbridge.

Table 2.2. Bridging modules

NamePurpose Popularity/Status
bridge_builtin_features Performs bridging when utilizing built-in user features (such as those found in features.conf).New
bridge_multiplexed Performs complex multiplexing, as would be required in a large conference room (multiple participants). Currently only used by app_confbridge.New
bridge_simple Performs simple channel-to-channel bridging.New
bridge_softmix Performs simple multiplexing, as would be required in a large conference room (multiple participants). Currently only used by app_confbridge.New

Call Detail Recording Modules

The CDR modules, listed in Table 2.3, “Call detail recording modules”, are designed to facilitate as many methods of storing call detail records as possible. You can store CDRs to a file (default), a database, RADIUS, or syslog.

Note

Call detail records are not intended to be used in complex billing applications. If you require more control over billing and call reporting, you will want to look at channel event logging, discussed next. The advantage of CDR is that it just works.

Table 2.3. Call detail recording modules

NamePurposePopularity/Status
cdr_adaptive_odbc Allows writing of CDRs through ODBC framework with ability to add custom fieldsUseful
cdr_csv Writes CDRs to disk as a comma-separated values fileUsable
cdr_custom As above, but allows for the addition of custom fieldsUseful
cdr_manager Outputs CDRs to Asterisk Manager Interface (AMI)Useful
cdr_odbc Writes CDRs through ODBC frameworkUsable
cdr_pgsql Writes CDRs to PostgreSQLUseful
cdr_radius Writes CDRs to RADIUSUsable—does not support custom fields
cdr_sqlite Writes CDRs to SQLite2 databaseDeprecated—use sqlite3_custom
cdr_sqlite3_custom Writes CDRs to SQLite3 with custom fieldsUseful
cdr_syslog Writes CDRs to syslogUseful
cdr_tds Writes CDRs to Microsoft SQL or SybaseUsable—requires an old version of libtds

We will discuss some reporting packages that you may wish to use with CDR in Chapter 25, Web Interfaces.

Channel Event Logging Modules

Channel event logging provides much more powerful control over reporting of call activity. By the same token, it requires more careful planning of your dialplan, and by no means will it work automatically. Asterisk’s CEL modules are listed in Table 2.4, “Channel event logging modules”.

Table 2.4. Channel event logging modules

NamePurposePopularity/Status
cel_custom CEL to disk/fileUseful
cel_manager CEL to AMIUseful
cel_odbc CEL to ODBCUseful
cel_pgsql CEL to PostgreSQLUseful
cel_radius CEL to RADIUSUsable—does not support custom fields
cel_sqlite3_custom CEL to Sqlite3Useful
cel_tds CEL to Microsoft SQL or SybaseUsable—requires an old version of libtds

Channel Drivers

Without channel drivers, Asterisk would have no way to make calls. Each channel driver is specific to the protocol or channel type it supports (SIP, ISDN, etc.). The channel module acts as a gateway to the Asterisk core. Asterisk’s channel drivers are listed in Table 2.5, “Channel drivers”.

Table 2.5. Channel drivers

NamePurpose Popularity/Status
chan_agent Provides agent channel for Queue()Useful
|chan_alsa Provides connection to Advanced Linux Sound ArchitectureUseful
chan_bridge Used internally by the ConfBridge() application; should not be used directlyEssential [a]
chan_console Provides connection to portaudioNew
chan_dahdi Provides connection to PSTN cards that use DAHDI channel driversUseful
chan_gtalk Provides connection to Google TalkUsable
chan_h323 Provides connection to H.323 endpointsDeprecated—see chan_ooh323 in Table 2.11, “Addon modules”
chan_iax2 Provides connection to IAX2 endpointsUseful
chan_jingle Provides connection to Jingle-enabled endpointsUsable
chan_local Provides a mechanism to treat a portion of the dialplan as a channelUseful
chan_mgcp Media Gateway Control Protocol channel driverUsable
chan_misdn Provides connection to mISDN supported ISDN cardsLimited
chan_multicast_rtp Provides connection to multicast RTP streamsUseful
chan_nbs Network Broadcast Sound channel driverInsignificant
chan_oss Open Sound System driverUseful
chan_phone Linux telephony interface driver (very old)Insignificant
chan_sip Session Initiation Protocol channel driverEssential
chan_skinny Cisco Skinny Client Control Protocol (SCCP) channel driverUsable
chan_unistim Nortel Unistim protocol channel driverUsable
chan_usbradio Channel driver for CM108 USB cards with radio interfaceUsable
chan_vpb Voicetronix channel driverInsignificant[b]

[a] If you are using the ConfBridge() application.

[b] Some Voicetronix hardware is supported by Zaptel using an addon Zaptel module distributed by Voicetronix. However, Zaptel is no longer supported by Asterisk and this driver has not been ported to DAHDI.


Codec Translators

The codec translators (Table 2.6, “Codec translators”) allow Asterisk to convert audio stream formats between calls. So if a call comes in on a PRI circuit (using G.711) and needs to be passed out a compressed SIP channel (e.g., using G.729, one of many codecs that SIP can handle), the relevant codec translator would perform the conversion.[13]

Note

If a codec (such as G.729) uses a complex encoding algorithm, heavy use of transcoding can place a massive burden on the CPU. Specialized hardware for the decoding/encoding of G.729 is available from hardware manufacturers such as Sangoma and Digium (and likely others).

Table 2.6. Codec translators

NamePurposePopularity/Status
codec_adpcm Adaptive Differential Pulse Coded Modulation codecInsignificant
codec_alaw A-law PCM codec used all over the world (except Canada/USA) on the PSTNEssential
codec_a_mu A-law to mu-law direct converterUseful
codec_dahdi Utilizes proprietary Digium hardware transcoding cardEssential[a]
codec_g722 Wideband audio codecUseful
codec_g726 Flavor of ADPCMInsignificant
codec_gsm Global System for Mobile Communications (GSM) codecUseful
codec_ilbc Internet Low Bitrate CodecInsignificant
codec_lpc10 Linear Predictive Coding vocoder (extremely low bandwidth)Insignificant
codec_resample Resamples between 8-bit and 16-bit signed linearUsable
codec_speex Speex codecUsable
codec_ulaw Mu-law PCM codec used in Canada/USA on PSTNEssential

[a] If you are using a Digium codec transcoder card.


Format Interpreters

Format interpreters (Table 2.7, “Format interpreters”) perform the function of codec translators, but they do their work on files rather than channels. If you have a recording on a menu that has been stored as GSM, a format interpreter would need to be used to play that recording to any channels not using the GSM codec.[14]

If you store a recording in several formats (such as WAV, GSM, etc.), Asterisk will determine the least costly format[15] to use when a channel requires that recording.

Table 2.7. Format interpreters

NamePlays files stored in Popularity/Status
format_g723 G.723 .g723Insignificant
format_g726 G.726 .g726Insignificant
format_g729 G.729 .g729Useful
format_gsm RPE-LTP (original GSM codec) .gsmUsable
format_h263 H.263—video .h263Usable
format_h264 H.264—video .h264Usable
format_ilbc Internet Low Bitrate Codec .ilbcInsignificant
format_jpeg Graphic file .jpeg .jpgInsignificant
format _ogg_ vorbis Ogg container .oggUsable
format_pcm Various Pulse-Coded Modulation formats: .alaw, .al, .alw, .pcm, .ulaw, .ul, .mu, .ulw, .g722, .auUseful
format_siren14 G.722.1 Annex C (14 kHz) .siren14New
format_siren7 G.722.1 (7 kHz) .siren7New
format_sln16 16-bit signed linear .sln16New
format_sln 8-bit signed linear .sln .rawUseful
format_vox .vox Insignificant
format_wav .wav Useful
format_wav_gsm GSM audio in a WAV container .WAV, .wav49Usable

Dialplan Functions

Dialplan functions, listed in Table 2.8, “Dialplan functions”, complement the dialplan applications (see the section called “Applications”). They provide many useful enhancements to things like string handling, time and date wrangling, and ODBC connectivity.

Table 2.8. Dialplan functions

NamePurposePopularity/Status
func_aes Encrypts/decrypts an AES stringUseful
func_audiohookinherit Allows calls to be recorded after transferUseful
func_base64 Encodes/decodes a base-64 stringUsable
func_blacklist Writes/reads blacklist in astdbUseful
func_callcompletion Gets/sets call completion configuration parameters for the channelNew
func_callerid Gets/sets CallerIDUseful
func_cdr Gets/sets CDR variableUseful
func_channel Gets/sets channel informationUseful
func_config Includes AST_CONFIG(); reads variables from config fileUsable
func_connectedline Changes connected line information on supported handsetsNew
func_curl Uses cURL to obtain data from a URIUseful
func_cut Slices and dices stringsUseful
func_db Provides astdb functionsUseful
func_devstate Gets state of deviceUseful
func_dialgroup Creates a group for simultaneous dialingUseful
func_dialplan Validates that designated target exists in dialplanUseful
func_enum Performs ENUM lookupUseful
func_env Includes FILE(), STAT(), and ENV(); performs operating system actionsUseful
func_extstate Returns status of a hinted extensionUseful
func_global Gets/sets global variablesUseful
func_groupcount Gets/sets channel count for members of a groupUseful
func_iconv Converts between character setsUsable
func_lock Includes LOCK(), UNLOCK(), and TRYLOCK(); sets a lock that can be used to avoid race conditions in the dialplanUseful
func_logic Includes ISNULL(), SET(), EXISTS(), IF(), IFTIME(), and IMPORT(); performs various logical functionsUseful
func_math Includes MATH(), INC(), and DEC(); performs mathematical functionsUseful
func_md5 Converts supplied string to an MD5 hashUseful
func_module Checks to see if supplied module is loaded into memoryUsable
func_odbc Allows dialplan integration with ODBC resourcesUseful
func_pitchshift Shifts the pitch of an audio streamUseful
func_rand Returns a random number within a given rangeUseful
func_realtime Performs lookups within the Asterisk Realtime Architecture (ARA)Useful
func_redirecting Provides access to information about where this call was redirected fromUseful
func_sha1 Converts supplied string to an SHA1 hashUseful
func_shell Performs Linux shell operations and returns resultsUseful
func_speex Reduces noise and performs dB gain/loss on an audio streamUseful
func_sprintf Performs string format functions similar to C function of same nameUseful
func_srv Perform SRV lookups in the dialplanUseful
func_strings Includes over a dozen string manipulation functionsUseful
func_sysinfo Gets system information such as RAM, swap, load average, etc.Useful
func_timeout Gets/sets timeouts on channelUseful
func_uri Converts strings to URI-safe encodingUseful
func_version Returns Asterisk version informationUsable
func_vmcount Returns count of messages in a voicemail folder for a particular userUseful
func_volume Sets volume on a channelUseful

PBX Modules

The PBX modules are peripheral modules that provide enhanced control and configuration mechanisms. For example, pbx_config is the module that loads the traditional Asterisk dialplan. The currently available PBX modules are listed in Table 2.9, “PBX modules”.

Table 2.9. PBX modules

NamePurposePopularity/Status
pbx_ael Asterisk Extension Logic (AEL) offers a dialplan scripting language that looks like a modern programming language.Usable[a]
pbx_config This is the traditional, and most popular, dialplan language for Asterisk. Without this module, Asterisk cannot read extensions.conf.Useful
pbx_dundi Performs data lookups on remote Asterisk systems.Useful
pbx_loopback Performs something similar to a dialplan include, but in a deprecated manner.Insignificant[b]
pbx_lua Allows creation of a dialplan using the Lua scripting language.Useful
pbx_realtime Provides functionality related to the Asterisk Realtime Architecture.Useful
pbx_spool Provides outgoing spool support relating to Asterisk call files.Useful

[a] We have not found too many people using AEL. We suspect this is because most developers will tend to use AGI/AMI if they do not want to use traditional dialplans.

[b] We’ve never heard of this being used in production.


Resource Modules

Resource modules integrate Asterisk with external resources. For example, res_odbc allows Asterisk to interoperate with ODBC database connections. The currently available resource modules are listed in Table 2.10, “Resource modules”.

Table 2.10. Resource modules

NamePurposePopularity/Status
res_adsi Provides ADSIEssential[a]
res_ael_share Provides shared routines for use with pbx_aelEssential if you’re using AEL
res_agi Provides Asterisk Gateway InterfaceUseful
res_ais Provides distributed message waiting indication (MWI) and device state notifications via an implementation of the AIS standard, such as OpenAISUseful
res_calendar Enables base integration to calendaring systemsUseful
res_calendar_caldav Provides CalDAV-specific capabilitiesUseful
res_calendar_exchange Provides MS Exchange capabilitiesUseful
res_calendar_icalendar Provides Apple/Google iCalendar capabilitiesUseful
res_clialiases Creates CLI aliasesUseful
res_clioriginate Originates a call from the CLIUsable
res_config_curl Pulls configuration information using cURLUseful
res_config_ldap Pulls configuration information using LDAPUsable
res_config_odbc Pulls configuration information using ODBCUseful
res_config_pgsql Pulls configuration information using PostgreSQLUsable
res_config_sqlite Pulls configuration information using SQLiteUsable
res_convert Uses the CLI to perform file conversionsUsable
res_crypto Provides cryptographic capabilitiesUseful
res_curl Provides common subroutines for other cURL modulesUseful
res_fax Provides common subroutines for other fax modulesUseful
res_fax_spandsp Plug-in for fax using the spandsp packageUseful
res_http_post Provides POST upload support for the Asterisk HTTP serverUsable
res_jabber Provides Jabber/XMPP resourcesUseful
res_limit Enables adjusting of system limits on the Asterisk processUsable
res_monitor Provides call recording resourcesUseful
res_musiconhold Provides music on hold (MOH) resourcesEssential
res_mutestream Allows muting/unmuting of audio streamsNew
res_odbc Provides common subroutines for other ODBC modulesUseful
res_phoneprov Provisions phones from Asterisk HTTP serverNew
res_pktccops Provides PacketCable COPS resourcesNew
res_realtime Provides CLI commands for the Asterisk Realtime Architecture (ARA)Useful
res_rtp_asterisk Provides RTPEssential
res_rtp_multicast Provides multicast-RTPNew
res_security_log Enables security loggingNew
res_smdi Provides voicemail notification using the SMDI protocolLimited
res_snmp Provides system status information to an SNMP-managed networkUsable
res_speech Generic speech recognition APILimited[b]
res_timing_dahdi Provides timing using the DAHDI kernel interfaceUseful
res_timing_kqueue Provides timing using a kernel feature in some BSDs, including Mac OS XNew
res_timing_pthread Provides timing using only parts of the standard pthread API; less efficient but more portable than other timing modules.Useful
res_timing_timerfd Provides timing using the timerfd API provided by newer versions of the Linux kernelUseful

[a] While most of the ADSI functionality in Asterisk is never used, the voicemail application uses this resource.

[b] Requires a separately licensed product in order to be used.


Addon Modules

Addon modules are community-developed modules with different usage or distribution rights from those of the main code. They are kept in a separate directory and are not compiled and installed by default. To enable these modules, use the menuselect build configuration utility. Currently available addon modules are listed in Table 2.11, “Addon modules”.

Table 2.11. Addon modules

NamePurposePopularity/Status
app_mysql Executes MySQL queries with a dialplan applicationDeprecated—see func_odbc
app_saycountpl Says Polish counting wordsDeprecated—now integrated in say.conf
cdr_mysql Logs call detail records to a MySQL databaseUsable—we recommend cdr_adaptive_odbc instead
chan_mobile Enables making and receiving phone calls using cell phones over BluetoothLimited[a]
chan_ooh323 Enables making and receiving VoIP calls using the H.323 protocolUsable
format_mp3 Allows Asterisk to play MP3 filesUsable
res_config_mysql Uses a MySQL database as a real-time configuration backendUseful

[a] While chan_mobile works great with many phones, problems have been reported with some models. When a problem does occur, it is very difficult for developers to solve unless they have a phone of the same model to test with.


Test Modules

Test modules are used by the Asterisk development team to validate new code. They are constantly changing and being added to, and are not useful unless you are developing Asterisk software.

If you are an Asterisk developer, however, the Asterisk Test Suite may be of interest to you as you can build automated tests for Asterisk and submit those back to the project, which runs on several different operating systems and types of machines. By expanding the number of tests constantly, the Asterisk project avoids the creation of regressions in code. By submitting your own tests to the project, you can feel more confident in future upgrades.

More information about installing the Asterisk Test Suite is available in this blog post: http://blogs.asterisk.org/2010/04/29/installing-the-asterisk-test-suite/. More information about building tests is available in this document: http://svn.asterisk.org/svn/testsuite/asterisk/trunk/README.txt or you can join the #asterisk-testing channel on the Freenode IRC network.

File Structure

Asterisk is a complex system, composed of many resources. These resources make use of the filesystem in several ways. Since Linux is so flexible in this regard, it is helpful to understand what data is being stored, so that you can understand where you are likely to find a particular bit of stored data (such as voicemail messages or log files).

Configuration Files

The Asterisk configuration files include extensions.conf, sip.conf, modules.conf, and dozens of other files that define parameters for the various channels, resources, modules, and functions that may be in use.

These files will be found in /etc/asterisk. You will be working in this folder a lot as you configure and administer your Asterisk system.

Modules

Asterisk modules are usually installed to the /usr/lib/asterisk/modules folder. You will not normally have to interact with this folder; however, it will be occasionally useful to know where the modules are located. For example, if you upgrade Asterisk and select different modules during the menuselect phase of the install, the old (incompatible) modules from the previous Asterisk version will not be deleted, and you will get a warning from the install script. Those old files will need to be deleted from the modules folder. This can be done either manually or with the “uninstall” make (make uninstall) target.

The Resource Library

There are several resources that require external data sources. For example, music on hold (MOH) can’t happen unless you have some music to play. System prompts also need to be stored somewhere on the hard drive. The /var/lib/asterisk folder is where system prompts, AGI scripts, music on hold, and other resource files are stored.

The Spool

The spool is where Linux stores files that are going to change frequently, or will be processed by other processes at a later time. For example, under Linux print jobs and pending emails are normally written to the spool until they are processed.

For Asterisk, the spool is used to store transient items such as voice messages, call recordings,[16] call files, and so forth.

The Asterisk spool will be found under the /var/spool/asterisk directory.

Logging

Asterisk is capable of generating several different kinds of log files. The /var/log/asterisk folder is where things such as call detail records (CDRs), channel events from CEL, debug logs, queue logs, messages, errors, and other output are written.

This folder will be extremely important for any troubleshooting efforts you undertake. We will talk more about how to make use of Asterisk logs in Chapter 24, System Monitoring and Logging.

The Dialplan

The dialplan is the heart of Asterisk. All channels that arrive in the system will be passed through the dialplan, which contains the call-flow script that determines how the incoming calls are handled.

A dialplan can be written in one of three ways:

  • Using traditional Asterisk dialplan syntax in /etc/asterisk/extensions.conf

  • Using asterisk Extension Logic (AEL) in /etc/asterisk/extensions.ael

  • Using LUA in /etc/asterisk/extensions.lua

Later in this book, we’ll have devoted several chapters to the subject of how to write a dialplan using traditional dialplan syntax (by far the most popular choice). Once you learn this language, it should be fairly easy to transition to AEL or LUA, should you desire.

Hardware

Asterisk is capable of communicating with a vast number of different technologies. In general, these connections are made across a network connection; however, connections to more traditional telecom technologies, such as the PSTN, require specific hardware.

Many companies produce this hardware, such as Digium (the sponsor, owner, and primary developer of Asterisk), Sangoma, Rhino, OpenVox, Pika, Voicetronix, Junghanns, Dialogic, Xorcom, beroNet, and many others. The authors prefer cards from Digium and Sangoma; however, the products offered by other Asterisk hardware manufacturers may be more suitable to your requirements.

The most popular hardware for Asterisk is generally designed to work through the Digium Asterisk Hardware Device Interface (known as DAHDI). These cards will all have different installation requirements and different file locations.

In Chapter 7, Outside Connectivity, we will discuss DAHDI in more detail; however, we will limit our discussion to DAHDI only. You will need to refer to the specific documentation provided by the manufacturers of any cards you install for details on those cards.

Asterisk Versioning

The Asterisk release methodology has gone through a couple of iterations over the last few years, and this section is designed to help you understand what the version numbers mean. Of particular relevance is the change in versioning that happened with the 1.6.x series of releases, which followed a different numbering logic than all other Asterisk releases (1.0 to 1.8 and onward for the foreseeable future).

Previous Release Methodologies

When we had just Asterisk 1.2 and 1.4, all new development was carried out in trunk (it still is), and only bug fixes went into the 1.2 and 1.4 branches. The Asterisk 1.2 branch has been marked as EOL (End of Life), and is no longer receiving bug fixes or security updates. Prior to the 1.6.x branches, bug fixes were carried out only in trunk and in the 1.4 branch.

Because all new development was done in trunk, until the 1.6 branch was created people were unable to get access to the new features and functionality. This isn’t to say the new functionality wasn’t available, but with all the changes that can happen in trunk, running a production server based on it requires a very Asterisk-savvy (and C code–savvy) administrator.

To try to relieve the pressure on administrators, and to enable faster access to new features (in the time frame of months, and not years), a new methodology was created. Branches in 1.6 would actually be marked as 1.6.0, 1.6.1, 1.6.2, etc., with the third number increasing by one each time a new feature release was created. The goal was to provide new feature releases every 3–4 months (which would be branched from trunk), providing a shorter and clearer upgrade path for administrators. If you needed a new feature, you’d only have to wait a few months and could then upgrade to the next branch.

Tags from these branches look like this:

  • 1.6.0.1 -- 1.6.0.2 -- 1.6.0.3 -- 1.6.0.4 -- etc.

  • 1.6.1.1 -- 1.6.1.2 -- 1.6.1.3 -- 1.6.1.4 -- etc.

  • 1.6.2.1 -- 1.6.2.2 -- 1.6.2.3 -- 1.6.2.4 -- etc.

Figure 2.2, “The Asterisk 1.6.x release process” gives a visual representation of the branching and tagging process in relation to Asterisk trunk.

Figure 2.2. The Asterisk 1.6.x release process

The Asterisk 1.6.x release process

So, so far we have branches, which are 1.2, 1.4, 1.6.0, 1.6.1, and 1.6.2 (there is no 1.6 branch). Within each of those branches, we create tags (releases), which look like 1.2.14, 1.4.30, 1.6.0.12, 1.6.1.12, and 1.6.2.15.

Unfortunately, it ended up not working out that 1.6.x branches were created from trunk every 3–4 months: the development process has led to a minimum release time of 6–8 months. Not only that, but the 1.6.x numbering methodology adds problems of its own. People got confused as to what version to run, and that the 1.6.0, 1.6.1, and 1.6.2 branches were all separate major version upgrades. When you increase the number from 1.2 to 1.4, and then to 1.8, it is obvious that those are distinct branches and major version changes. With 1.6.0, 1.6.1, and 1.6.2, it is less obvious.

The New Release Methodology

The development team learned a lot of things during the 1.6.x releases. The idea surrounding the releases was noble, but the implementation ended up being flawed when put into real use. So, with Asterisk 1.8, the methodology has changed again, and will look a lot more like that used in the 1.2 and 1.4 releases.

While the development team still wants to provide access to new features and core changes on a more regular basis (every 12 months being the goal), there is recognition that it is also good to provide long-term support to a stable, popular version of Asterisk. You can think of the Asterisk 1.4 branch as being a long-term support (LTS) version. The 1.6.0, 1.6.1, and 1.6.2 branches can be thought of as feature releases that continue to receive bug fixes after release, but are supported for a shorter period of time (about a year). The new LTS version is Asterisk 1.8 (what this book is based on); it will receive bug fixes for four years and an additional year of security releases after that, providing five years of support from the Digium development team.

During the long-term support phase of Asterisk 1.8, additional branches will be created on a semi-regular basis as feature releases. These will be tagged as versions 1.10, 1.12, and 1.14, respectively. Each of these branches will receive bug fixes for a period of one year, and security releases will continue to be made for an additional year before the branches are marked as EOL.

The current statuses of all Asterisk branches, their release dates, when they will go into security release–only mode, and when they will reach EOL status are all documented on the Asterisk wiki at https://wiki.asterisk.org/wiki/display/AST/Asterisk+Versions.

Conclusion

Asterisk is composed of many different technologies, most of which are complicated in their own right. As such, the understanding of Asterisk architecture can be overwhelming. Still, the reality is that Asterisk is well-designed for what it does and, in our opinion, has achieved remarkable balance between flexibility and complexity.



[12] To be fair, many traditional PBXs do offer this sort of functionality. However, it is generally kludgy, limited in features, and requires complex, proprietary software to be installed in the PBX (such as vendor-specific protocol extensions).

[13] More information about what codecs are and how they work is available in the section called “Codecs”.

[14] It is partly for this reason that we do not recommend the default GSM format for system recordings. WAV recordings will sound better and use less CPU.

[15] Some codecs can impose a significant load on the CPU, such that a system that could support several hundred channels without transcoding might only be able to handle a few dozen when transcoding is in use.

[16] Not call detail records (CDRs), but rather audio recordings of calls generated by the MixMonitor() and related applications.

Chapter 3. Installing Asterisk

I long to accomplish great and noble tasks, but it is my chief duty to accomplish humble tasks as though they were great and noble. The world is moved along, not only by the mighty shoves of its heroes, but also by the aggregate of the tiny pushes of each honest worker.

Helen Keller

In this chapter we’re going to walk through the installation of Asterisk from the source code. Many people shy away from this method, claiming that it is too difficult and time-consuming. Our goal here is to demonstrate that installing Asterisk from source is not actually that difficult to do. More importantly, we want to provide you with the best Asterisk platform on which to learn.

In this book we will be helping you build a functioning Asterisk system from scratch. In this chapter you will build a base platform for your Asterisk system. Given that we are installing from source, there is potentially a lot of variation in how you can do this. The process we discuss here is one that we’ve used for many years, and following it will provide you with a suitable foundation for Asterisk.

As part of this process we will also explain installation of some of the software dependencies on the Linux platform that will be needed for topics covered later in this book (such as database integration). We will show instructions for installing Asterisk on both CentOS (a Red Hat–based distribution) and Ubuntu (a Debian-based distribution), which we believe covers the vast majority of Linux distributions being installed today. We’ll try to keep the instructions general enough that they should be useful on any distribution of your choice.[17]

We have chosen to install on CentOS and Ubuntu because they are the most popular options, but Asterisk is generally distribution-agnostic. Asterisk will even install on Solaris, BSD, or OS X[18] if you like. We won’t be covering them in this book, though, as Asterisk is most heavily developed on the Linux platform.

Some commands you see in this chapter will be split into separate rows, each labeled for the distribution on which the command should be performed. Commands for which distributions are not specified are for common commands that can be run on both distributions.

Installation Cheat Sheet

If you just want the nitty-gritty on how to get Asterisk up and running quickly, perform the following at the shell prompt. We encourage you to read through the entire chapter at least once, though, in order to better understand the full process.[20]

The instructions provided here assume you’ve already installed either CentOS or Ubuntu using the steps outlined in the section called “Distribution Installation”.

Note

Remember that Ubuntu requires commands to be prefixed with sudo.

  1. Perform a system update and reboot:

    CentOS

    yum update -y && reboot

    CentOS 64-bit

    yum remove *.i386 && yum update -y && reboot

    Ubuntu

    sudo apt-get update && sudo apt-get upgrade && sudo reboot

  2. Synchronize time and install the NTP (Network Time Protocol) daemon:

    CentOS

    yum install -y ntp && ntpdate pool.ntp.org && chkconfig ntpd \

    on && service ntpd start

    CentOS 64-bit

    yum install -y ntp && ntpdate pool.ntp.org && chkconfig ntpd \

    on && service ntpd start

    Ubuntu

    sudo apt-get install ntp

    Note

    Some additional configuration of text files is required on Ubuntu. See the section called “Enable NTP for accurate system time”.

  3. On CentOS, add a new system user:

    CentOS (32 and 64 bit)

    adduser asteriskpbx && passwd asteriskpbx && yum install \

    sudo && visudo

    Note

    See the section called “Adding a system user” for specific information.

    Note

    For an Ubuntu install, we are assuming that the user created during the installation process is asteriskpbx.

  4. Install software dependencies:

    CentOS

    sudo yum install gcc gcc-c++ make wget subversion \

    libxml2-devel ncurses-devel openssl-devel \

    vim-enhanced

    CentOS 64-bit

    sudo yum install gcc.x86_64 gcc-c++.x86_64 \

    make.x86_64 wget.x86_64 subversion.x86_64 \

    libxml2-devel.x86_64 ncurses-devel.x86_64 \

    openssl-devel.x86_64 vim-enhanced.x86_64

    Ubuntu

    sudo apt-get install build-essential subversion \

    libncurses5-dev libssl-dev libxml2-dev vim-nox

  5. Create your directory structure:

    $ mkdir -p ~/src/asterisk-complete/asterisk
    $ cd ~/src/asterisk-complete/asterisk
  6. Get the latest source code via Subversion:

    $ svn co http://svn.asterisk.org/svn/asterisk/branches/1.8

    Or alternatively, you could check out a specific tag:

    $ svn co http://svn.asterisk.org/svn/asterisk/tags/1.8.1

  7. Build and install the software:

    $ cd ~/src/asterisk-complete/asterisk/1.8/
    $ ./configure
    $ make
    $ sudo make install
    $ sudo make config

  8. Install additional sound prompts from menuselect:

    $ cd ~/src/asterisk-complete/asterisk/1.8/
    $ make menuselect
    $ sudo make install

  9. Modify the file permissions of the directories Asterisk was installed to:

    $ sudo chown -R asteriskpbx:asteriskpbx /usr/lib/asterisk/
    $ sudo chown -R asteriskpbx:asteriskpbx /var/lib/asterisk/
    $ sudo chown -R asteriskpbx:asteriskpbx /var/spool/asterisk/
    $ sudo chown -R asteriskpbx:asteriskpbx /var/log/asterisk/
    $ sudo chown -R asteriskpbx:asteriskpbx /var/run/asterisk/
    $ sudo chown asteriskpbx:asteriskpbx /usr/sbin/asterisk
  10. On CentOS, disable SELinux:

    $ sudo vim /etc/selinux/config

    Change the value of SELINUX from enforcing to disabled, then reboot.

  11. Create the /etc/asterisk/ directory and copy the indications.conf sample file into it:

    $ sudo mkdir -p /etc/asterisk
    $ sudo chown asteriskpbx:asteriskpbx /etc/asterisk
    $ cd /etc/asterisk/
    $ cp ~/src/asterisk-complete/asterisk/1.8/configs/indications.conf.sample \
    ./indications.conf

  12. Copy the sample asterisk.conf file into /etc/asterisk and change runuser and rungroup to have values of asteriskpbx:

    $ cp ~/src/asterisk-complete/asterisk/1.8/configs/asterisk.conf.sample \
    /etc/asterisk/asterisk.conf

    $ vim /etc/asterisk/asterisk.conf

    See the section called “indications.conf and asterisk.conf” for more information.

  13. Create the modules.conf file. Enable loading of modules automatically, and disable extra modules:

    $ cat >> /etc/asterisk/modules.conf
    
    ; The modules.conf file, used to define which modules Asterisk should load (or 
    ; not load).
    ;
    [modules]
    autoload=yes
    
    ; Resource modules currently not needed
    noload => res_speech.so
    noload => res_phoneprov.so
    noload => res_ael_share.so
    noload => res_clialiases.so
    noload => res_adsi.so
    
    ; PBX modules currently not needed
    noload => pbx_ael.so
    noload => pbx_dundi.so
    
    ; Channel modules currently not needed
    noload => chan_oss.so
    noload => chan_mgcp.so
    noload => chan_skinny.so
    noload => chan_phone.so
    noload => chan_agent.so
    noload => chan_unistim.so
    noload => chan_alsa.so
    
    ; Application modules currently not needed
    noload => app_nbscat.so
    noload => app_amd.so
    noload => app_minivm.so
    noload => app_zapateller.so
    noload => app_ices.so
    noload => app_sendtext.so
    noload => app_speech_utils.so
    noload => app_mp3.so
    noload => app_flash.so
    noload => app_getcpeid.so
    noload => app_setcallerid.so
    noload => app_adsiprog.so
    noload => app_forkcdr.so
    noload => app_sms.so
    noload => app_morsecode.so
    noload => app_followme.so
    noload => app_url.so
    noload => app_alarmreceiver.so
    noload => app_disa.so
    noload => app_dahdiras.so
    noload => app_senddtmf.so
    noload => app_sayunixtime.so
    noload => app_test.so
    noload => app_externalivr.so
    noload => app_image.so
    noload => app_dictate.so
    noload => app_festival.so
    
    Ctrl+D
  14. Configure musiconhold.conf:

    $ cat >> musiconhold.conf
    
    ; musiconhold.conf
    [default]
    mode=files
    directory=moh
    
    Ctrl+D
  15. Save your changes and your module configuration is done. Your system is ready to configure your dialplan and channels.

Distribution Installation

Because Asterisk relies so heavily on having priority access to the CPU, it is essential that you install Asterisk onto a server without any graphical interface, such as the X Windowing system (Gnome, KDE, etc.). Both CentOS and Ubuntu ship a GUI-free distribution designed for server usage. We will cover instructions for both distributions.

CentOS Server

CentOS means “Community Enterprise Operating System,” and it is based on Red Hat Enterprise Linux (RHEL). For more information about what CentOS is and its history, see http://www.centos.org.

You will need to download an ISO from the CentOS website, located at http://mirror.centos.org/centos/5/isos/. Select either the i386 or x86_64 directory for 32-bit or 64-bit hardware, respectively. You will then be presented with a list of mirrors that appear to be close to you physically. Choose one of the mirrors, and you will be presented with a list of files to download. Likely you will want the first available selection, which is the first ISO file of a set. You will only need the first ISO file of the set as we’ll be installing additional software with yum.

Once you’ve downloaded the ISO file, burn it to a CD or DVD and start the installation process. If you’re installing into a virtual machine (which we don’t recommend for production use,[21] but can be a great way to test out Asterisk), you should be able to mount the ISO file directly and install from there.

Base system installation

Upon booting from the CD, type linux text and then press Enter.[22]

At this point the text installation interface will start. You will be asked whether you want to test the media. These instructions assume you’ve already done so, and therefore can skip that step.

CentOS will then welcome you to the installation. Press Enter to continue.

Choose your language and make a keyboard selection.[23] If you’re in North America, you will probably just select the defaults.

If you’ve previously formatted your hard drive, you will be asked to initialize the drive, which will erase all data. Select Yes.

The installer will ask if you want to remove the existing partitioning scheme and create a new one. Select Remove all partitions on selected drives and create default layout. If a more appropriate option exists, select that instead. In the drive window, verify that the correct disk drive is selected. (Pressing Tab will cycle through the selections on the screen.) Once the drive window is selected, you can scroll up and down (presuming you have multiple drives) and select which hard drive you wish to install to. Toggle the selections by pressing space bar. Verify that the correct drive is selected, press Tab until the OK button is highlighted, and press Enter.

A message confirming that you want to remove all Linux partitions and create the new partition scheme will be presented. Select Yes.

You will be asked to review the partitioning layout. Feel free to modify the partition scheme if you prefer something different (see the following sidebar for some advice on this); however, the default answer No is fine for light production use where storage requirements will be low.[24]

A message will appear asking if you’d like to configure the eth0 network interface on your system. Select Yes. Be sure the Activate on boot and Enable IPv4 support options are enabled, then select OK.

If your network provides automatic IP provisioning via DHCP, you can just select OK. Otherwise, select Manual address configuration, enter the appropriate information, and then select OK.

Next, you’ll be asked to provide a hostname. You can either allow the DHCP server to provide one for you (if your network assigns hostnames automatically) or enter one manually, then select OK.

You will be presented with a list of time zones. Highlight your local time zone and select OK.

At this point, you will be asked for a root password. Enter a secure password and type it again to confirm. After entering your secure password, select OK.

Next up will be the package selection. Several packages that you don’t need to install (and that require additional ISO files you probably haven’t downloaded) are selected by default. Deselect all options in the list using the space bar, then select the Customize software selection option. Once you’ve done that, select OK.

You will then be presented with the Package Group Selection screen. Scroll through the whole list, deselecting each item. If any packages are selected, you’ll be prompted for additional CDs that you have not downloaded. We’ll be installing additional packages with the yum application after the operating system is installed. Once you’ve deselected all packages, select OK.

A dependency check will then be performed and a confirmation that installation is ready to begin will be presented. Select OK to start the installation. The filesystem will then be formatted, the installation image transferred to the hard drive, and installation of the system packages performed. Upon installation, you will be asked to reboot. Remove any media in the drives and select the Reboot button.

Base system update

Once you’ve rebooted your system, you need to run the yum update command to make sure you have the latest base packages. To do this, log in using the username root and the password you created during installation. Once logged in, run the following:

# yum update
Is this ok [y/N]: y

When prompted to install the latest packages, press y and wait for the packages to update. If you’re asked to accept a GPG key, press y. When complete, reboot the system as it is likely the kernel will have been updated[25]:

# reboot

Note

If you’re running CentOS Server 64-bit, you’ll need to remove all the 32-bit libraries manually. Once you’ve rebooted, or just prior to reboot, run the following command:

# yum remove *.i386 -y

This will remove all the 32-bit libraries on your 64-bit system, which can otherwise cause conflicts and issues when compiling Asterisk and other software.

Congratulations! You’ve successfully installed and updated the base CentOS system.

Enabling NTP for accurate system time

Keeping accurate time is essential on your Asterisk system, both for maintaining accurate call detail records and for synchronization with your other programs. You don’t want the times of your voicemail notifications to be off by 10 or 20 minutes, as this can lead to confusion and panic from those who might think their voicemail notifications are taking took too long to be delivered. The ntpd command can be used to ensure that the time on your Asterisk server remains in sync with the rest of the world:

# yum install ntp
...
Is this ok [y/N]: y
...
# ntpdate pool.ntp.org
# chkconfig ntpd on
# service ntpd start

The defaults shipped with CentOS are sufficient to synchronize the time and keep the machine’s time in sync with the rest of the world.

Adding a system user

The Ubuntu server install process asks you to add a system user other than root, but CentOS does not. In order to be consistent in the book and to be more secure, we’re going to add another system user and provide it sudo access.[26] To add the new user, execute the adduser command:

# adduser asteriskpbx
# passwd asteriskpbx
Changing password for user asteriskpbx.
New UNIX password:
Retype new UNIX password:

Now we need to provide the asteriskpbx user sudo access. We do this by modifying the sudoers file with the visudo command. You’ll need to install visudo the first time you use it:

# yum install sudo

With the sudo-related applications and file installed, we can modify the sudoers file. Execute the visudo command and look for the lines shown below:

# visudo

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

With the %wheel line uncommented as shown in our example, save the file by pressing Esc, then typing :wq and pressing Enter. Now open the /etc/group file in your favorite editor (nano is easy to use) and find the line that starts with the word wheel. Modify it like so:

wheel:x:10:root,asteriskpbx

Save the file, log out from root by typing exit, and log in as the asteriskpbx user you created. Test your sudo access by running the following command:

$ sudo ls /root/
[sudo] password for asteriskpbx:

After typing your password, you should get the output of the /root/ directory. If you don’t, go back and verify the steps to make sure you didn’t skip or mistype anything. The rest of the instructions in this chapter will assume that you’re the asteriskpbx user and that you have sudo access.

One last thing needs to done, which will allow you to enter commands without having to enter the full path. By default only root has /sbin/ and /usr/sbin/ in the default system PATH, but we’ll add it to our asteriskpbx user as well since we’ll be running many applications located in those directories.

Start by opening the hidden file .bash_profile located within the asteriskpbx home directory with an editor. We’re then going to append :/usr/sbin:/sbin to the end of the line starting with PATH:

$ vim ~/.bash_profile
PATH=$PATH:$HOME/bin:/usr/sbin:/sbin

As previously, save the file by pressing Esc and then typing :wq and pressing Enter.

With the operating system installed, you’re ready to install the dependencies required for Asterisk. The next section deals with Ubuntu, so you can skip ahead to the section the section called “Software Dependencies”, which provides an in-depth review of the installation process. Alternatively, if you’ve already reviewed the information in that section, you may want to refer back to the the section called “Installation Cheat Sheet” for a high-level review of how to install Asterisk.

Ubuntu Server

Ubuntu Server is a popular Linux distribution loosely based on Debian. There is also a popular desktop version of the software. The Ubuntu Server package contains no GUI and is ideal for Asterisk installations.

To get the latest version of Ubuntu Server,[27] visit http://www.ubuntu.com and select the Server tab at the top of the page. You will be provided with a page that contains information about Ubuntu Server Edition. Clicking the orange Download button in the upper-right corner will take you to a page where you can select either the 32-bit or 64-bit version of Ubuntu Server. After selecting one of the options, you can press the Start download button.

Once you’ve downloaded the ISO file, burn it to a CD and start the installation process. If you’re installing into a virtual machine (which we don’t recommend for production use, but can be a great way to test out Asterisk), you should be able to mount the ISO file directly and install from there.

Base system installation

Upon booting from the CD, you will be presented with a screen where you can select your language of choice. By default English is the selected language, and after a timeout period, it will be automatically selected. After selecting your language, press Enter.

The next screen will give you several options, the first of which is Install Ubuntu Server. Select it by pressing Enter.

You will then be asked which language to use for the installation (yes, this is slightly redundant). Select your language of choice (the default is English), and press Enter.

You will be presented with a list of countries. Once you’ve found your country and highlighted it, press Enter.

You will then be asked if you would like to use the keyboard layout detector. If you know which keyboard type you have, you can select No and then pick it from a list of formats.

If you are utilizing the keyboard layout detector, you will be prompted to press a series of keys. If you use the keyboard detector and it does not detect your keyboard correctly (typical when installing into a virtual machine via a remote console), you can go back and select from a list manually.

Once you’ve picked your keyboard, the installation will continue by attempting to set up your network automatically. If all goes well, you will be prompted to enter a hostname for your system. You can pick anything you want here, unless your network requires your system to a have a specific hostname. Input it now and then press Enter.

The installer will attempt to contact a Network Time Protocol (NTP) server to synchronize your clock. Ubuntu will then try to autodetect your time zone and present you with its choice. If correct, select Yes, otherwise, select No and you’ll be presented with a list of time zones to select from. Select your time zone, or select from the worldwide list if your time zone is not shown. Once you’ve selected your time zone, press Enter to continue.

The installer will then ask you some questions about partitioning your system. Typically the default is fine, which is to use the guided system, utilizing the entire disk, and to set up the Logical Volume Manager (LVM). Press Enter once you’ve made your selection. Then you’ll be asked which partition to install to, which likely is the only one on your system. Press Enter to continue, at which point you’ll be asked to confirm the changes to the partition table. Select Yes and press Enter to continue.

You will now be asked how much space to use (the default value will be to use the entire disk). Press Enter once you’ve entered and confirmed the amount of space you want to use. The installer will then request one last confirmation before making the changes to the disk. Select Yes to write the changes to disk. The installer will now format the hard disk, write the partitioning scheme to disk, copy the files, and perform the file installation.

When the file installation is complete, you’ll be asked to enter the Full name of the new user, from which a username will be generated. The system will suggest a username, but you are free to change the username to whatever you like.

After entering your username, you’ll be asked to supply a password, and then asked to confirm the password you’ve entered. Ubuntu does a good job of providing a secure system by not providing direct access to root, but rather using the sudo application, which allows you to run commands as root without being the root user. Enter a username,[28] such as asteriskpbx, and a secure password to continue. You’ll use these to log into the system once the installer ends. The installer will then ask you if you want to encrypt your home directory. This is not necessary and will add CPU overhead.

Note

The rest of the installation instructions will assume that asteriskpbx was chosen as the username.

If your system is behind a web proxy, enter the proxy information now. If you’re not behind a proxy, or don’t know if you are, simply press Enter.

You will then be asked if you want to install updates automatically. The default is to perform no automatic updates, which is what we recommend. Should a system reboot occur, an update to the kernel will render Asterisk nonstartable until you recompile it[29] (which won’t make you popular). It is better practice to identify updates on a regular basis and perform them manually in a controlled manner. Normally, you would want to advise your users of the expected downtime and schedule the downtime to happen after business hours (or while a redundant system is running). Select No automatic updates and press Enter.

Since we’ll be installing our dependencies with apt-get, we only need to select one package during the install: OpenSSH server. SSH is essential if you wish to perform remote work on the system. However, if your local policy states that your server needs to be managed directly, you may not want to install the OpenSSH server.

Warning

Pressing the Enter key will accept the current selections and move on with the install. You need to use space bar to toggle your selections.

After you’ve selected OpenSSH server, press Enter.

If this is the only operating system on the machine (which it likely is), Ubuntu will give you the option to install the GRUB bootloader on your system. It provides this prompt in order to give you the option of skipping the GRUB installation, as it will modify the master boot record (MBR) on your system. If there is another operating system it has failed to detect that has information loaded into the MBR, it’s nice to be able to skip modifying it. If this is the only operating system installed on your server, select Yes.

When the system has finished the install, you’ll be asked to remove any media in the drives and to reboot the system by selecting Continue, at which point the installation will be complete and the system will reboot.

Base system update

Now that we’ve completed installing Ubuntu Server, we need to perform a system update with apt-get to make sure we have the latest packages installed. You’ll be presented with a login prompt where you’ll log in with the username and password you created in the installer (e.g., asteriskpbx). Once logged in, run the following command:

$ sudo apt-get update
[sudo] password for asteriskpbx:
...
Reading package lists... Done

$ sudo apt-get upgrade
Reading state information... Done
...
Do you want to continue [Y/n]? y

Tip

The password that sudo wants is the password you just logged in with.

Press Enter when prompted to continue, at which point the latest package updates will be installed. When complete, reboot the system for the changes to take effect as the kernel has probably been updated.

$ sudo reboot

Congratulations! You’ve successfully installed and updated the base Ubuntu Server system.

Enable NTP for accurate system time

Keeping accurate time is essential on your Asterisk system, both for maintaining accurate call detail records as well as for synchronization with your other programs. You don’t want the times of your voicemail notifications to be off by 10 or 20 minutes, as this can lead to confusion and panic from those who might think their voicemail notification took too long to be delivered:

$ sudo apt-get install ntp

The default on Ubuntu is to run a time sync server without ever changing the time on your own machine. This won’t work for our needs, so we’ll need to change the configuration file slightly. Because of this, we need to guide you through using a command line editor. The nano editor is already installed on your Ubuntu machine and is remarkably easy to use[30]:

$ sudo nano /etc/ntp.conf

Your terminal will switch to full-screen output.

Use your arrow keys to move down to the section that looks like

# By default, exchange time with everybody, but don't allow configuration.
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery

Add two new lines after this section, to allow ntpd to synchronize your time with the outside world, such that the above section now looks like

# By default, exchange time with everybody, but don't allow configuration.
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery

restrict -4 127.0.0.1
restrict -6 ::1

That’s everything we need to change, so exit the editor by pressing Ctrl+X. When prompted whether to save the modifications, press Y; nano will additionally ask you for the filename. Just hit Enter to confirm the default /etc/ntp.conf.

Now restart the NTP daemon:

$ sudo /etc/init.d/ntp restart

With the operating system installed, you’re ready to install the dependencies required for Asterisk. The next section provides an in-depth review of the installation process. If you’ve already reviewed the information in the section called “Software Dependencies”, you may want to refer back to the section called “Installation Cheat Sheet” for a high-level review of how to install Asterisk.

Software Dependencies

The first thing you need to do once you’ve completed the installation of your operating system is to install the software dependencies required by Asterisk. The commands listed in Table 3.1, “Software dependencies for Asterisk on Ubuntu Server and CentOS Server” have been split into two columns, for Ubuntu Server and CentOS Server. These packages will allow you to build a basic Asterisk system, along with DAHDI and LibPRI. Not every module will be available at compile time with these dependencies; only the most commonly used modules will be built. If additional dependencies are required for other modules used later in the book, instructions will be provided as necessary.

Warning

Please be aware that the dependency information on CentOS 64-bit does not take into account that 32-bit libraries should not be installed. If such libraries are installed, you will end up with additional packages that use disk space and can cause conflicts if the system attempts to compile against a 32-bit library instead of its 64-bit counterpart. In order to resolve this problem, add .x86_64 to the end of each package name when installing it. So, for example, instead of executing yum install ncurses-devel, you will execute yum install ncurses-devel.x86_64. This is not necessary on a 32-bit platform.

Table 3.1. Software dependencies for Asterisk on Ubuntu Server and CentOS Server

UbuntuCentOS

sudo apt-get install build-essential \

subversion libncurses5-dev libssl-dev \

libxml2-dev vim-nox

sudo yum install gcc gcc-c++ make wget \

subversion libxml2-devel ncurses-devel \

openssl-devel vim-enhanced


These packages will get you most of what you’ll need to get started with installing Asterisk, DAHDI, and LibPRI. Note that you will also require the software dependencies for each package that we indicate needs to be installed. These will be resolved automatically for you when you use either yum or apt-get.

We have also included the OpenSSL development libraries, which are not strictly necessary to compile Asterisk, but are good to have: they enable key support and other encryption functionality.

We have installed vim as our editor, but you can choose anything you want, such as nano, joe, or emacs.

Asterisk contains a script that will install the dependencies for all features in Asterisk. At this time it is complete for Ubuntu but does not list all required packages for CentOS. Once you have downloaded Asterisk using the instructions in the section called “Downloading What You Need”, use the following commands if you would like to run it:

$ cd ~/src/asterisk-complete/asterisk/1.8
$ sudo ./contrib/scripts/install_prereq install
$ sudo ./contrib/scripts/install_prereq install-unpackaged

Downloading What You Need

There are several methods of getting Asterisk: via the Subversion code repository, via wget from the downloads site, or via a package-management system such as apt-get or yum. We’re only going to cover the first two methods, since we’re interested in building the latest version of Asterisk from source. Typically, package-management systems will have versions that are older than those available from Subversion or the downloads site, and we want to make sure we have the most recent fixes available to us, so we tend to avoid them.

Tip

The official packages from Digium do tend to stay up to date. There are currently packages for CentOS/RHEL available at http://www.asterisk.org/downloads/yum.

Before we start getting the source files, let’s create a directory structure to house the downloaded code. We’re going to create the directory structure within the home directory for the asteriskpbx user on the system. Once everything is built, it will be installed with the sudo command. We’ll then go back and change the permissions and ownership of the installed files in order to build a secure system. To begin, issue the following command:

$ mkdir -p ~/src/asterisk-complete/asterisk

Now that we’ve created a directory structure to hold everything, let’s get the source code. Choose one of the following two methods to get your files:

Getting the Source via Subversion

Subversion is a version control system that is used by developers to track changes to code over a period of time. Each time the code is modified, it must first be checked out of the repository; then it must be checked back in, at which point the changes are logged. Thus, if a change creates a regression, the developers can go back to that change and remove it if necessary. This is a powerful and robust system for development work. It also happens to be useful for Asterisk administrators seeking to retrieve the software. To download the source code to the latest version of Asterisk 1.8, use these commands:

$ cd ~/src/asterisk-complete/asterisk
$ svn co http://svn.asterisk.org/svn/asterisk/branches/1.8

You can now skip directly to the section called “How to Install It”.

Note

The preceding commands will retrieve the latest changes to the source in that particular branch, which are changes that have been made after the latest release. If you would prefer to use a released version, please refer to the next section.

Getting the Source via wget

To obtain the latest released versions of DAHDI, LibPRI, and Asterisk using the wget application, issue the following commands:

$ cd ~/src/asterisk-complete/asterisk
$ wget \
http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-1.8-current.tar.gz
$ tar zxvf asterisk-1.8-current.tar.gz

The next step is to compile and install the software, so onward to the next section.

How to Install It

With the source files downloaded you can compile the software and install it. The order for installing is:

  1. LibPRI[31]

  2. DAHDI[32]

  3. Asterisk[33]

Installing in this order ensures that any dependencies for DAHDI and Asterisk are installed prior to running the configuration scripts, which will subsequently ensure that any modules dependent on LibPRI or DAHDI will be built.

So, let’s get started.

LibPRI

LibPRI is a library that adds support for ISDN (PRI and BRI). The use of LibPRI is optional, but since it takes very little time to install, doesn’t interfere with anything, and will come in handy if you ever want to add cards to a system at a later point, we recommend that you install it now.

Check out the latest version of LibPRI and compile it like so:

$ cd ~/src/asterisk-complete/
$ mkdir libpri
$ cd libpri/
$ svn co http://svn.asterisk.org/svn/libpri/tags/1.4.<your version number>
$ cd 1.4.<your version number>
$ make
$ sudo make install

Note

You can also download the source via wget from http://downloads.asterisk.org/pub/telephony/libpri/.

With LibPRI installed, we can now install DAHDI.

DAHDI

The Digium Asterisk Hardware Device Interface, or DAHDI (formerly known as Zaptel), is the software Asterisk uses to interface with telephony hardware. We recommend that you install it even if you have no hardware installed, because DAHDI is a dependency required for building the timing module res_timing_dahdi and is used for Asterisk dialplan applications such as MeetMe().

Another dependency is required for installing DAHDI, and that is the kernel source. It is important that the kernel version being used match exactly that of the kernel source being installed. You can use uname -a to verify the currently running kernel version:

  • CentOS: sudo yum install kernel-devel-`uname -r`

  • Ubuntu: sudo apt-get install linux-headers-`uname -r`

The use of uname -r surrounded by backticks (`) is for filling in the currently running kernel version so the appropriate package is installed.

The following commands show how to install DAHDI-linux-complete 2.4.0+2.4.0. There may be a newer version available by the time you are reading this, so check downloads.asterisk.org first. If there is a newer version available, just replace the version number in the commands:

$ cd ~/src/asterisk-complete/
$ mkdir dahdi
$ cd dahdi/
$ svn co http://svn.asterisk.org/svn/dahdi/linux-complete/tags/2.4.0+2.4.0
$ cd 2.4.0+2.4.0
$ make
$ sudo make install
$ sudo make config

Warning

You will need to have Internet access when running the make all command, as it will attempt to download the latest hardware firmware from the Digium servers.

After installing DAHDI, we can move on to installing Asterisk.

Note

You can also download the source via wget from http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/.

Asterisk

With both DAHDI and LibPRI installed, we can now install Asterisk:

$ cd ~/src/asterisk-complete/asterisk/1.8
$ ./configure
$ make
$ sudo make install
$ sudo make config

With the files now installed in their default locations, we need to modify the permissions of the directories and their contents.

Note

There is an additional step that is not strictly required, but is quite common (and arguably important): the make menuselect command, which provides a graphical interface that allows detailed selection of which modules and features will be compiled. We will discuss this in the section called “make menuselect”.

Setting File Permissions

In order to run our system more securely, we’ll be installing Asterisk and then running it as the asteriskpbx user. After installing the files into their default locations, we need to change the file permissions to match those of the user we’re going to be running as. Execute the following commands after running make install (which we did previously):

$ sudo chown -R asteriskpbx:asteriskpbx /usr/lib/asterisk/
$ sudo chown -R asteriskpbx:asteriskpbx /var/lib/asterisk/
$ sudo chown -R asteriskpbx:asteriskpbx /var/spool/asterisk/
$ sudo chown -R asteriskpbx:asteriskpbx /var/log/asterisk/
$ sudo chown -R asteriskpbx:asteriskpbx /var/run/asterisk
$ sudo chown asteriskpbx:asteriskpbx /usr/sbin/asterisk

In order to use MeetMe() and DAHDI with Asterisk as non-root, you must change the /etc/udev/rules.d/dahdi.rules so that the OWNER and GROUP fields match the non-root user Asterisk will be running as. In this case, we’re using the asteriskpbx user.

Change the last line of the dahdi.rules file to the following:

SUBSYSTEM=="dahdi", OWNER="asteriskpbx", GROUP="asteriskpbx", MODE="0660"

With that out of the way, we can move on to performing the base configuration that should be done after all installations.

Base Configuration

Now that we’ve got Asterisk installed, we can get our system up and running. The purpose here is to get Asterisk loaded up and ready to go, as it isn’t doing anything useful yet. These are the steps that all system administrators will need to start out with when installing a new system. If the commands that need to be run differ on CentOS and Ubuntu, you will see a table with rows labeled for each distribution; otherwise, you will see a single command that should be run regardless of which Linux distribution you have chosen.

Disable SELinux

Note

This section applies only to CentOS users, so if you’re using Ubuntu, you can skip to the next section.

In CentOS, the Security-Enhanced Linux (SELinux) system is enabled by default, and it often gets in the way of Asterisk. Sometimes the issues are quite subtle, and at least one of the authors has spent a good number of hours debugging issues in Asterisk that turned out to be resolved by disabling SELinux. There are many articles on the Internet that describe the correct configuration of SELinux, but we’re going to disable it for the sake of simplicity.

Note

While disabling SELinux is not the ideal situation, the configuration of SELinux is beyond the scope of this book, and frankly, we just don’t have enough experience with it to configure it correctly.

To temporarily switch off SELinux, perhaps in order to verify whether an issue you’re having is being caused by SELinux, run the following command as root:

$ sudo echo 0 > /selinux/enforce

You can reenable SELinux by doing the same thing, but replacing the 0 with a 1:

$ sudo echo 1 > /selinux/enforce

To disable SELinux permanently, modify the /etc/selinux/config file:

$ cd /etc/selinux/
$ sudo vim config

Change the SELINUX option from enforcing to disabled.

Note

Alternatively, you can change the value of enforcing to permissive, which simply logs the errors instead of enforcing the policy.

When you’re done modifying the configuration file, you’ll have the following:

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - SELinux is fully disabled.
SELINUX=disabled
# SELINUXTYPE= type of policy in use. Possible values are:
#       targeted - Only targeted network daemons are protected.
#       strict - Full SELinux protection.
SELINUXTYPE=targeted

# SETLOCALDEFS= Check local definition changes
SETLOCALDEFS=0

Since you can’t disable SELinux without rebooting, you’ll need to do that now:

$ sudo reboot

Initial Configuration

In order to get Asterisk up and running cleanly, we need to create some configuration files. We could potentially install the sample files that come with Asterisk (by executing the make samples command in our Asterisk source) and then modify those files to suit our needs, but the make samples command installs many sample files, most of them for modules that you will never use. We want to limit which modules we are loading, and we also believe that it’s easier to understand Asterisk configuration if you build your config files from scratch, so we’re going to create our own minimal set of configuration files.[34]

The first thing we need to do (assuming it does not already exist) is create the /etc/asterisk/ directory where our configuration files will live:

$ sudo mkdir /etc/asterisk/
$ sudo chown asteriskpbx:asteriskpbx /etc/asterisk/

Warning

Running make samples on a system that already has configuration files will overwrite the existing files.

We’re now going to step through all the files that are required to get a simple Asterisk system up and running.

indications.conf and asterisk.conf

The first file needed is indications.conf, a file that contains information about how to detect different telephony tones for different countries. There is a perfectly good sample file that we can use in the Asterisk source, so let’s copy it into our /etc/asterisk/ directory:

$ cp ~/src/asterisk-complete/asterisk/1.8/configs/indications.conf.sample \
/etc/asterisk/indications.conf

Because we’re running Asterisk as non-root, we need to tell Asterisk which user to run as. This is done with the asterisk.conf file. We can copy a sample version of it from the Asterisk source to /etc/asterisk:

$ cp ~/src/asterisk-complete/asterisk/1.8/configs/asterisk.conf.sample \
/etc/asterisk/asterisk.conf

The asterisk.conf file contains many options that we won’t go over here (they are covered in the section called “asterisk.conf”), but we do need to make an adjustment. Near the end of the [options] section, there are two options we need to enable: runuser and rungroup.

Open the asterisk.conf file with an editor such as nano or vim: Uncomment the runuser and rungroup lines, and modify them so that they each contain asteriskpbx as the assigned value. Open the /etc/asterisk/asterisk.conf file with vim:

$ vim /etc/asterisk/asterisk.conf

Then modify the file by uncommenting the two lines starting with runuser and rungroup and modifying the value to asteriskpbx.

runuser=asteriskpbx
rungroup=asteriskpbx

We now have all the configuration files required to start a very minimal version of Asterisk.[36] Give it a shot by starting Asterisk up in the foreground:

$ /usr/sbin/asterisk -cvvv

Tip

We are specifying the full path to the asterisk binary, but if you modify your PATH system variable to include the /usr/sbin/ directory you don’t need to specify the full path. See the section called “Adding a system user” for information about modifying the $PATH environment variable.

Asterisk will start successfully without any errors or warnings (although it does warn you that some files are missing), and present to you the Asterisk command-line interface (CLI). At this point there are no modules, minimal core functionality, and no channel modules with which to communicate, but Asterisk is up and running.

Executing the module show command at the Asterisk CLI shows that there are no external modules loaded:

*CLI> module show
Module                         Description                              Use Count 
0 modules loaded

We’ve done this simply to demonstrate that Asterisk can be run in a very minimal state, and doesn’t require the dozens of modules that a default install will enable. Let’s stop Asterisk with the core stop now CLI command:

*CLI> core stop now

modules.conf

So, we’ve managed to get Asterisk running, but it’s not able to do anything useful for us yet. To tell Asterisk what modules we expect it to load, we’ll need a modules.conf file.

Create the file modules.conf in your /etc/asterisk/ directory with the following command (replace the >> with > if you instead want to overwrite an existing file):

$ cat >> /etc/asterisk/modules.conf

Type (or paste) the following lines, and press Ctrl+D on a new line when you’re finished:

          ; The modules.conf file, used to define which modules Asterisk should load (or
; not load).
;
[modules]
autoload=yes

        

The autoload=yes line will tell Asterisk to automatically load all modules located in the /usr/lib/asterisk/modules/ directory. If you wanted to, you could leave the file like this, and Asterisk would simply load any modules it found in the modules folder.

With your new modules.conf file in place, starting Asterisk will cause a whole slew of modules to be loaded. You can verify this by starting Asterisk and running the module show command:

$ asterisk -c
*CLI> module show
Module                         Description                              Use Count 
res_speech.so                  Generic Speech Recognition API           0
res_monitor.so                 Call Monitoring Resource                 0
...
func_math.so                   Mathematical dialplan function           0         
171 modules loaded

We now have many modules loaded, and many additional dialplan applications and functions at our disposal. We don’t need all these resources loaded, though, so let’s filter out some of the more obscure modules that we don’t need at the moment. Modify your modules.conf file to contain the following noload lines, which will tell Asterisk to skip loading the identified modules:

; Resource modules
noload => res_speech.so
noload => res_phoneprov.so
noload => res_ael_share.so
noload => res_clialiases.so
noload => res_adsi.so

; PBX modules
noload => pbx_ael.so
noload => pbx_dundi.so

; Channel modules
noload => chan_oss.so
noload => chan_mgcp.so
noload => chan_skinny.so
noload => chan_phone.so
noload => chan_agent.so
noload => chan_unistim.so
noload => chan_alsa.so

; Application modules
noload => app_nbscat.so
noload => app_amd.so
noload => app_minivm.so
noload => app_zapateller.so
noload => app_ices.so
noload => app_sendtext.so
noload => app_speech_utils.so
noload => app_mp3.so
noload => app_flash.so
noload => app_getcpeid.so
noload => app_setcallerid.so
noload => app_adsiprog.so
noload => app_forkcdr.so
noload => app_sms.so
noload => app_morsecode.so
noload => app_followme.so
noload => app_url.so
noload => app_alarmreceiver.so
noload => app_disa.so
noload => app_dahdiras.so
noload => app_senddtmf.so
noload => app_sayunixtime.so
noload => app_test.so
noload => app_externalivr.so
noload => app_image.so
noload => app_dictate.so
noload => app_festival.so

There are, of course, other modules that you could remove, and others that you may find extremely useful, so feel free to tweak this file as you wish. Ideally, you should be loading only the modules that you need for the system you are running. The examples in this book assume that your modules.conf file looks like our example here.

Additional information about the modules.conf file can be found in the section the section called “modules.conf”.

musiconhold.conf

The musiconhold.conf file defines the classes for music on hold in your Asterisk system. By defining different classes, you can specify different hold music to be used in various situations, such as different announcements to be played while holding in a queue, or different hold music if you have multiple PBXs hosted on the same system. For now, we’ll just create a default music on hold class so that we have at a minimum some hold music when placing callers on hold:

$ cd /etc/asterisk/
$ cat >> musiconhold.conf
; musiconhold.conf
[default]
mode=files
directory=moh

Ctrl+D

We’ve created a musiconhold.conf file and defined our [default] hold music class. We’re also assuming you installed the hold music from the menuselect system; by default there is at least one music on hold package installed, so unless you disabled it, you should have music in at least one format.

Additional information about musiconhold.conf can be found in the section the section called “musiconhold.conf”.

make menuselect

menuselect is a text-based menu system in Asterisk used to configure which modules to compile and install. The modules are what give Asterisk its power and functionality. New modules are constantly being created.

In the installation sections, we conveniently skipped over using the menuselect system in order to keep the instructions simple and straightforward. However, it is important enough that we have given menuselect its own section.

In addition to specifying which modules to install, menuselect also allows you to set flags that can aid in debugging issues (see Chapter 2, Asterisk Architecture), set optimization flags, choose different sound prompt files and formats, and do various other nifty things.

Uses for menuselect

We would need a whole chapter in order to fully explore menuselect, and for the most part you won’t need to make many changes to it. However, the following example will give you an idea of how menuselect works, and is recommend for any installation.

By default Asterisk only installs the core sound prompt files, and only in GSM format. Also, the three OpSound music on hold files available for download are only selected in .wav format.[37]

We’re going to want extra sound prompts installed instead of just the default core sound prompts, and in a better-sounding format than GSM. We can do this with the menuselect system by running make menuselect in the Asterisk source directory. Before exploring that, though, let’s talk about the different menuselect interfaces.

menuselect interfaces

There are two interfaces available for menuselect: curses and newt. If the libnewt libraries are installed, you will get the blue and red interface shown in Figure 3.1, “menuselect using the newt interface”. Otherwise, by default menuselect will use the curses (black and white) interface shown in Figure 3.2, “menuselect using the curses interface”.

Tip

The minimum screen size for the curses interface is 80x27, which means it may not load if you’re using the default terminal size for a simple distribution installation. This is not a problem when you’re using SSH to reach the server remotely, as typically your terminal can be resized, but if you’re working at the terminal directly you may need to have screen buffers installed to enable a higher resolution, which is not recommended for a system running Asterisk. The solution is to use the newt-based menuselect system.

Figure 3.1. menuselect using the newt interface

menuselect using the newt interface

Figure 3.2. menuselect using the curses interface

menuselect using the curses interface

Using menuselect

Run the following commands to start menuselect:

$ cd ~/src/asterisk-complete/asterisk/1.8.<your version>/
$ make menuselect

You will be presented with a screen such as that in Figure 3.1, “menuselect using the newt interface” or Figure 3.2, “menuselect using the curses interface”. You can use the arrow keys on your keyboard to move up and down. The right arrow key will take you into a submenu, and the left arrow key will take you back. You can use the space bar or Enter key to select and deselect modules. Pressing the q key will quit without saving, while the x key will save your selections and then quit.

Once you’ve started menuselect, scroll down to Core Sound Packages and press the right arrow key (or Enter) to open the menu. You will be presented with a list of available options. These options represent the core sound files in various languages and formats. By default, the only set of files selected is CORE-SOUNDS-EN-GSM, which is the English-language Core Sounds package in GSM format.

Select CORE-SOUNDS-EN-WAV and CORE-SOUNDS-EN-ULAW (or ALAW if you’re outside of North America or Japan[39]), and any other sound files that may be applicable in your network.

Note

The reason we have multiple formats for the same files is that Asterisk can play back the appropriate format depending on which codec is negotiated by an endpoint. This can lower the CPU load on a system significantly.

After selecting the appropriate sound files, press the left arrow key to go back to the main menu. Then scroll down two lines to the Extra Sound Packages menu and press the right arrow key (or Enter). You will notice that by default there are no packages selected. As with the core sound files, select the appropriate language and format to be installed. A good option is probably to install the English sound files in the WAV, ULAW, and ALAW formats.

Once you’ve completed selecting the sound files, press the x key to save and exit menuselect. You then need to install your new prompts by downloading them from the Asterisk downloads site. This is done simply by running make install again:

$ sudo make install
$ sudo chown -R asteriskpbx:asteriskpbx /var/lib/asterisk/sounds/

The files will be downloaded, extracted, and installed into the appropriate location (/var/lib/asterisk/sounds/<language>/ by default). Your Asterisk server will need to have a working Internet connection in order to retrieve the files.

Scripting menuselect

Administrators often build tools when performing installations on several machines, and Asterisk is no exception. If you need to install Asterisk onto several machines, you may wish to build a set of scripts to help automate this process. The menuselect system contains command-line options that you can use to enable or disable the modules that are built and installed by Asterisk.

If you are starting with a fresh checkout of Asterisk, you must first execute the configure script in order to determine what dependencies are installed on the system. Then you need to build the menuselect application and run the make menuselect-tree command to build the initial tree structure:

$ cd ~/src/asterisk-complete/asterisk/1.8.<your version>/
$ ./configure
$ cd menuselect
$ make menuselect
$ cd ..
$ make menuselect-tree
Generating input for menuselect ...

For details about the options available, run menuselect/menuselect --help from the top level of your Asterisk source directory. You will be returned output like the following:

Usage: menuselect/menuselect [--enable <option>] [--disable <option>]
   [--enable-category <category>] [--enable-all]
   [--disable-category <category>] [--disable-all] [...]
   [<config-file> [...]]
Usage: menuselect/menuselect { --check-deps | --list-options
   | --list-category <category> | --category-list | --help }
   [<config-file> [...]]

The options displayed can then be used to control which modules are installed via the menuselect application. For example, if you wanted to disable all modules and install a base system (which wouldn’t be of much use) you could use the command:

$ menuselect/menuselect --disable-all menuselect.makeopts

If you then look at the menuselect.makeopts file, you will see a large amount of text that displays all the modules and categories that have been disabled. Let’s say you now want to enable the SIP channel and the Dial() application. Enabling those modules can be done with the following command, but before doing that look at the current menuselect.makeopts (after disabling all the modules) and locate app_dial in the MENUSELECT_APPS category and chan_sip in the MENUSELECT_CHANNELS category. After executing the following command, look at the menuselect.makeopts file again, and you will see that those modules are no longer listed:

$ menuselect/menuselect --disable-all --enable chan_sip \
--enable app_dial menuselect.makeopts

Tip

The modules listed in the menuselect.makeopts file are those that will not be built—modules that are not listed will be built when the make application is executed.

You can then build the menuselect.makeopts file in any way you want by utilizing the other commands, which will allow you to build custom installation scripts for your system using any scripting language you prefer.

Updating Asterisk

If this is your first installation, you can skip ahead to the section the section called “Base Configuration”. If you’re in the process of updating your system, however, there are a couple of things you should be aware of.

Note

When we say updating your system, that is quite different from upgrading your system. Updating your system is the process of installing new minor versions of the same branch. For example, if your system is running Asterisk 1.8.2 and you need to upgrade to the latest bug fix version for the 1.8 branch, which was version 1.8.3, you’d be updating your system to 1.8.3. In contrast, we use the term upgrade to refer to changes between Asterisk branches (major version number increases). So, for example, an upgrade would be going from Asterisk 1.4.34 to Asterisk 1.8.0.

When performing an update, you follow the same instructions outlined in the section the section called “How to Install It”.

Tip

Additionally, if you’ve checked out a new directory for this version of Asterisk (versus running svn up on a checked-out branch), and previously used menuselect to tweak the modules to be compiled, you can copy the menuselect.makeopts file from one directory to another prior to running ./configure. By copying menuselect.makeopts from the old version to the new version, you save the step of having to (de)select all your modules again.

The basic steps are:

$ cd ~/src/asterisk-complete/asterisk/1.8.<your version number>/
$ ./configure
$ make
$ make install

Tip

You don’t need to run sudo make install because we’ve already set the directory ownership to the asteriskpbx user. You should be able to install new files directly into the appropriate directories.

Upon installation, however, you may get a message like the following:

 WARNING WARNING WARNING

 Your Asterisk modules directory, located at
 /usr/lib/asterisk/modules
 contains modules that were not installed by this
 version of Asterisk. Please ensure that these
 modules are compatible with this version before
 attempting to run Asterisk.

    chan_mgcp.so
    chan_oss.so
    chan_phone.so
    chan_skinny.so
    chan_skype.so
    codec_g729a.so
    res_skypeforasterisk.so

 WARNING WARNING WARNING

This warning message is indicating that modules installed in the /usr/lib/asterisk/modules/ directory are not compatible with the version you’ve just installed. This most often occurs when you have installed modules in one version of Asterisk, and then installed a new version of Asterisk without compiling those modules (as the installation process will overwrite any modules that existed previously, replacing them with their upgraded versions).

To get around the warning message, you can clear out the /usr/lib/asterisk/modules/ directory prior to running make install. There is a caveat here, though: if you’ve installed third-party modules, such as commercial modules from Digium (including chan_skype, codec_g729a, etc.), you will need to reinstall those if you’ve cleared out your modules directory.

It is recommended that you keep a directory with your third-party modules in it that you can reinstall from upon update of your Asterisk system. So, for example, you might create the /usr/src/asterisk-complete/thirdparty/1.8 directory as follows:

$ cd ~/src/asterisk-complete/
$ mkdir thirdparty/
$ mkdir thirdparty/1.8/

Downloading third-party modules into this directory allows you to easily reinstall those modules when you upgrade. Just follow the installation instructions for your module, many of which will be as simple as rerunning make install from the modules source directory or copying the precompiled binary to the /usr/lib/asterisk/modules/ directory.

Warning

Be sure to change the file permissions to match those of the user running Asterisk!

Common Issues

In this section we’re going to cover some common issues you may run into while compiling Asterisk, DAHDI, or LibPRI. Most of the issues you’ll run into have to do with missing dependencies. If that is the case, please review the section called “Software Dependencies” to make sure you’ve installed everything you need.

Note

Any time you install additional packages, you will need to run the ./configure script in your Asterisk source in order for the new package to be detected.

-bash: wget: command not found

This message means you have not installed the wget application, which is required for you to download packages from the Asterisk downloads site, for Asterisk to download sound files, or for DAHDI to download firmware for hardware.

Ubuntu CentOS 
$ sudo apt-get install wget$ sudo yum -y install wget

configure: error: no acceptable C compiler found in $PATH

This means that the Asterisk configure script is unable to find your C compiler, which typically means you have not yet installed one. Be sure to install the gcc package for your system.

UbuntuCentOS 
$ sudo apt-get install gcc$ sudo yum install gcc

make: gcc: command not found

This means that the Asterisk configure script is unable to find your C compiler, which typically means you have not yet installed one. Be sure to install the gcc package for your system.

UbuntuCentOS 
$ sudo apt-get install gcc$ sudo yum install gcc

configure: error: C++ preprocessor “/lib/cpp” fails sanity check

This error is presented by the Asterisk configure script when you have not installed the GCC C++ preprocessor.

UbuntuCentOS 
$ sudo apt-get install g++$ sudo yum install gcc-c++

configure: error: *** Please install GNU make. It is required to build Asterisk!

This error is encountered when you have not installed the make application, which is required to build Asterisk.

UbuntuCentOS 
$ sudo apt-get install make$ sudo yum install make

configure: *** XML documentation will not be available because the ‘libxml2’ development package is missing.

You will encounter this error when the XML parser libraries are not installed. These are required by Asterisk 1.8 and later, since console documentation (e.g., when you run core show application dial on the Asterisk CLI) is generated from XML.

UbuntuCentOS 
$ sudo apt-get install libxml2-dev$ sudo yum install libxml2-devel

configure: error: *** termcap support not found

This error happens when you don’t have the ncurses development library installed, which is required by menuselect and for other console output in Asterisk.

UbuntuCentOS 
$ sudo apt-get install ncurses-dev$ sudo yum install ncurses-devel

You do not appear to have the sources for the 2.6.18-164.6.1.el5 kernel installed.

You will get this error when attempting to build DAHDI without having installed the Linux headers, which are required for building Linux drivers.

UbuntuCentOS 
$ sudo apt-get install linux-headers-`uname -r`$ sudo yum install kernel-devel

E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?

If you encounter this error it’s likely that you forgot to prepend sudo to the start of the command you were running, which requires root permissions.

Upgrading Asterisk

Upgrading Asterisk between major versions, such as from 1.2 to 1.4 or from 1.6.2 to 1.8 is akin to upgrading an operating system. Once a phone switch is in production, it is terribly disruptive for that system to be unavailable for nearly any length of time, and the upgrade of that phone system needs to be well thought-out, planned, and tested as much as possible prior to deployment. And because every deployment is different, it is difficult, if not impossible, for us to walk you through a real system upgrade. However, we can certainly point you in the right direction for the information you require in order to perform such an upgrade, thereby giving you the tools you need to be successful.

A production Asterisk system should never be upgraded between major versions without first deploying it into a development environment where the existing configuration files can be tested and reviewed against new features and syntax changes between versions. For example, it may be that your dialplan relies on a deprecated command and should be updated to use a new command that contains more functionality, has a better code base, and will be updated on a more regular basis. Commands that are deprecated are typically left in the code for backward-compatibility, but issues reported about these deprecated commands will be given lower priority than issues to do with the newer preferred methods.

There exist two files that should be read prior to any system upgrade: CHANGES and UPGRADE.txt, which are shipped with the Asterisk source code. These files contain details on changes to syntax and other things to be aware of when upgrading between major versions. The files are broken into different sections that reference things such as dialplan syntax changes, channel driver syntax changes, functionality changes, and deprecation of functionality, with suggestions that you update your configuration files to use the new methods.

Another thing to consider when performing an upgrade is whether you really need to perform the upgrade in the first place. If you’re using a long-term support (LTS)[40] version of Asterisk and that version is happily working along for you, perhaps there is no reason to upgrade your existing production system. An alternative to upgrading the entire system is simply to add functionality to your system by running two versions simultaneously on separate systems. By running separate boxes, you can access the functionality added to a later version of Asterisk without having to disrupt your existing production system. You can then perform the migration more gradually, rather than doing a complete system upgrade instantly.

Two parts of Asterisk should be thoroughly tested when performing an upgrade between major versions: the Asterisk Manager Interface (AMI) and the Asterisk Gateway Interface (AGI).

These two parts of Asterisk rely on testing your code to make sure any cleanup of syntax changes in either the AMI or the AGI, or added functionality, does not interfere with your existing code. By performing a code audit on what your program is expecting to send or receive against what actually happens, you can save yourself a headache down the road.

The testing of call detail records (CDRs) is also quite important, especially if they are relied upon for billing. The entire CDR structure is really designed for simple call flows, but it is often employed in complex call flows, and when someone reports an issue to the tracker and it is fixed, it can sometimes have an effect on others who are relying on the same functionality for different purposes. Asterisk 1.8 now includes channel event logging (CEL), which is a system designed to get around some of the limitations of CDR in more complex call flows (such as those that involve transfers, etc.). More information about CEL is available in the section called “CEL (Channel Event Logging)”.

Upgrading Asterisk can be a successful endeavor as long as sufficient planning and testing are carried out prior to the full rollout. In some cases migrating to a separate physical machine on which you’ve performed testing is preferred, as it can give you a system to roll back to in case of some failure that can’t be resolved immediately. It’s the planning, and particularly having a backup plan, that is the most important aspect of an Asterisk upgrade.

Conclusion

In this chapter we looked at how to install an operating system (one of Ubuntu or CentOS) and Asterisk itself. We did this securely by installing via sudo and running Asterisk as the non-root user asteriskpbx. We are well on our way to building a functional Asterisk system that will serve us well. In the following chapters we will explore how to connect devices to our Asterisk system in order to start placing calls internally and how to connect Asterisk to outside services in order to place phone calls to endpoints connected to the PSTN and accept calls from those endpoints.



[17] If you are using another distribution, we’re willing to bet you are quite comfortable with Linux and should have no trouble installing Asterisk.

[18] Leif calls this “Oh-Eh-Sex,” but Jim thinks it should be pronounced “OS Ten.” We wasted several precious minutes arguing about this.

[19] After you read our book, of course.

[20] Once you have experience with several Asterisk installations, you’ll agree that it’s a quick and painless process. Nevertheless, this chapter may make the process look complex. This is simply because we have an obligation to ensure you are provided with all the information you need to accomplish a successful install.

[21] Actually, some people have great success running Asterisk inside virtual machines. It does depend what you’re planning on using it for though, as you’ll have limited access to hardware, for example.

[22] You should test the media the first time you are using that particular CD/DVD.

[23] Bear in mind that Asterisk is developed using the US keyboard and language, and we’re not aware of any testing having been done on anything other than US English.

[24] Due to the ever-increasing size of hard drives, capacity is becoming less of a problem. A system with a 1 terabyte drive can store somewhere in the range of 2 million minutes of telephony-quality recordings.

[25] This reboot step is essential prior to installing Asterisk.

[26] sudo is an application that allows a user to execute commands as another user, such as root, or the superuser.

[27] Of course, projects can change their websites whenever they want. Hopefully the instructions we’ve provided here are accurate enough to help guide you through the site even in the event of changes.

[28] Ubuntu has reserved the username asterisk internally.

[29] While we say Asterisk here, specifically it is DAHDI that is the problem. DAHDI is a set of Linux kernel modules used with Asterisk.

[30] If you’re already familiar with another editor, go ahead and use it. The nano editor has been selected for its ease of use and its handy on-screen instructions. We even know a developer at Digium who uses it while writing code for Asterisk, though most people tend to use more complex editors such as emacs or vim.

[31] Strictly speaking, if you are not going to be using any ISDN connections (BRI and PRI), you can install Asterisk without LibPRI. However, we are going to install it for the sake of completeness.

[32] This package contains the kernel drivers to allow Asterisk to connect to traditional PSTN circuits. It is also required for the MeetMe() conferencing application. Again, we will install this for completeness.

[33] If you don’t install this, none of the examples in this book will work, but it could still make a great bathroom reader. Just sayin’.

[34] If your /etc/asterisk/ folder has files in it already, move those files to another directory, or delete them if you are sure you don’t need what is there.

[35] /usr/src/asterisk-complete/asterisk/asterisk-1.8.<your version>/

[36] So minimal, in fact, that it’s completely useless at this point. But we digress.

[37] A good way to put the final touches on your new system is to install some appropriate sound files to be used as music on hold. There are only three songs installed by default, and callers will quickly tire of listening to the same three songs over and over again. We’ll discuss this more in the section called “musiconhold.conf”.

[38] Which we will cover in Chapter 16, Relational Database Integration, along with many other cool things.

[39] If you want to understand all about mu-law and A-law, you can read the section the section called “Logarithmic companding”. All you need to know here is that outside of North America and Japan, A-law is used.

[40] More information about Asterisk releases and their support schedule is available at https://wiki.asterisk.org/wiki/display/AST/Asterisk+Versions.

Chapter 4. Initial Configuration Tasks

Careful. We don’t want to learn from this.

Calvin & Hobbes

In the last chapter, we covered how to install Asterisk. But where should you get started with configuration? That is the question this chapter answers. There are a few common configuration files that are relevant regardless of what you are using Asterisk to accomplish. In some cases they may not require any modification, but you need to be aware of them.

asterisk.conf

The asterisk.conf configuration file allows you to tweak various settings that can affect how Asterisk runs as a whole.

There is a sample asterisk.conf file included with the Asterisk source. It is not necessary to have this file in your /etc/asterisk folder in order to have a working system, but you may find that some of the possible options will be of use to you.

Note

Asterisk will look for asterisk.conf in the default configuration location, which is usually /etc/asterisk. To specify a different location for asterisk.conf, use the -C command-line option:

$ sudo asterisk -C /custom/path/to/asterisk.conf

The [directories] Section

For most installations of Asterisk, changing the directories is not necessary. However, this can be useful for running more than one instance of Asterisk at the same time, or if you would like files stored in nonstandard locations.

The default directory locations and the options you can use to modify them are listed in Table 4.1, “asterisk.conf [directories] section”. For additional information about the usage of these directories, see the File Structure section of Chapter 2, Asterisk Architecture.

Table 4.1. asterisk.conf [directories] section

OptionValue/ExampleNotes
astetcdir/etc/asteriskThe location where the Asterisk configuration files are stored.
astmoddir/usr/lib/asterisk/modulesThe location where loadable modules are stored.
astvarlibdir/var/lib/asteriskThe base location for variable state information used by various parts of Asterisk. This includes items that are written out by Asterisk at runtime.
astdbdir/var/lib/asteriskAsterisk will store its internal database in this directory as a file called astdb.
astkeydir/var/lib/asteriskAsterisk will use a subdirectory called keys in this directory as the default location for loading keys for encryption.
astdatadir/var/lib/asteriskThis is the base directory for system-provided data, such as the sound files that come with Asterisk.
astagidir /var/lib/asterisk/ agi-binAsterisk will use a subdirectory called agi-bin in this directory as the default location for loading AGI scripts.
astspooldir/var/spool/asteriskThe Asterisk spool directory, where voicemail, call recordings, and the call origination spool are stored.
astrundir/var/run/asteriskThe location where Asterisk will write out its UNIX control socket as well as its process ID (PID) file.
astlogdir/var/log/asteriskThe directory where Asterisk will store its log files.

The [options] Section

This section of the asterisk.conf file configures defaults for global runtime options. The available options are listed in Table 4.2, “asterisk.conf [options] section”. Most of these are also controllable via command-line parameters to the asterisk application. For a complete list of the command-line options that relate to these options, see the Asterisk manpage:

$ man asterisk

Table 4.2. asterisk.conf [options] section

OptionValue/ExampleNotes
verbose3Sets the default verbose setting for the Asterisk logger. This value is also set by the -v command-line option. The verbose level is 0 by default.
debug3Sets the default debug setting for the Asterisk logger. This value is also set by the -d command-line option. The debug level is 0 by default.
alwaysforkyesForking forces Asterisk to always run in the background. This option is set to no by default.
noforkyesForces Asterisk to always run in the foreground. This option is set to no by default.
quietyesQuiet mode reduces the amount of output seen at the console when Asterisk is run in the foreground. This option is set to no by default.
timestampyesAdds timestamps to all output except output from a CLI command. This option is set to no by default.
execincludesyesEnables the use of #exec in Asterisk configuration files. This option is set to no by default.
consoleyesRuns Asterisk in console mode. Asterisk will run in the foreground and will present a prompt for CLI commands. This option is set to no by default.
highpriorityyesRuns the Asterisk application with real-time priority. This option is set to no by default.
initcryptoyesLoads keys from the astkeydir at startup. This option is set to no by default.[a]
nocoloryesSuppresses color output from the Asterisk console. This is useful when saving console output to a file. This option is set to no by default.
dontwarnyesDisables a few warning messages. This option was put in place to silence warnings that are generally correct, but may be considered to be so obvious that they become an annoyance. This option is set to no by default.
dumpcoreyesTells Asterisk to generate a core dump in the case of a crash. This option is set to no by default.[b]
languageprefixyesConfigures how the prompt language is used in building the path for a sound file. By default, this is yes, which places the language before any subdirectories, such as en/digits/1.gsm. Setting this option to no causes Asterisk to behave as it did in previous versions, placing the language as the last directory in the path, (e.g. digits/en/1.gsm).
internal_timingyesUses a timing source to synchronize audio that will be sent out to a channel in cases such as file playback or music on hold. This option is set to yes by default and should be left that way; its usefulness has greatly diminished over the last few major versions of Asterisk.
systemname my_ system _nameGives this instance of Asterisk a unique name. When this has been set, the system name will be used as part of the uniqueid field for channels. This is incredibly useful if more than one system will be logging CDRs to the same database table. By default, this option is not set.
autosystemnameyesAutomatically sets the system name by using the hostname of the system. This option is set to no by default.
maxcalls100Sets a maximum number of simultaneous inbound channels. No limit is set by default.
maxload0.9Sets a maximum load average. If the load average is at or above this threshold, Asterisk will not accept new calls. No threshold is set by default.
maxfiles1000Set the maximum number of file descriptors that Asterisk is allowed to have open. The default limit imposed by the system is commonly 1024, which is not enough for heavily loaded systems. It is common to set this limit to a very high number. The default system-imposed limit is used by default.
minmemfree1Sets the minimum number of megabytes of free memory required for Asterisk to continue accepting calls. If Asterisk detects that there is less free memory available than this threshold, new calls will not be accepted. This option is not set by default.
cache_record_filesyesWhen doing recording, stores the file in the record_cache_dir until recording is complete. Once complete, it will be moved into the originally specified destination. The default for this option is no.
record_cache_dir/tmpSets the directory to be used when cache_record_files is set to yes. The default location is a directory called tmp within the astspooldir.
transmit_silenceyesTransmits silence to the caller in cases where there is no other audio source. This includes call recording and the Wait() family of dialplan applications, among other things. The default for this option is no.[c]
transcode_via_slnyesWhen building a codec translation path, forces signed linear to be one of the steps in the path. The default for this option is yes.
runuserasteriskSets the system user that the Asterisk application should run as. This option is not set by default, meaning that the application will continue to run as the user that executed the application.
rungroupasteriskSets the system group that the Asterisk application should run as. This option is not set by default.
lightbackgroundyesWhen using colors in the Asterisk console, it will output colors that are compatible with a light-colored background. This option is set to no by default, in which case Asterisk uses colors that look best on a black background.
documentation_languageen_USThe built-in documentation for Asterisk applications, functions, and other things is included in an external XML document. This option specifies the preferred language for documentation. If it is not available, the default of en_US will be used.
hideconnectyesSetting this option to yes causes Asterisk to not display notifications of remote console connections and disconnections at the Asterisk CLI. This is useful on systems where there are scripts that use remote consoles heavily. The default setting is no.
lockconfdirnoWhen this option is enabled, the Asterisk configuration directory will be protected with a lock. This helps protect against having more than one application attempting to write to the same file at the same time. The default value is no.

[a] If any of the keys require a passphrase, this will block the startup process of Asterisk. An alternative is to run keys init at the Asterisk command line.

[b] This is critical for debugging crashes. However, Asterisk must be compiled with the DONT_OPTIMIZE option enabled in menuselect for the core dump to be useful.

[c] There is an important caveat to note when this option is enabled. The silence is generated in uncompressed signed linear format, which means that it will have to be transcoded into the format that the caller’s channel expects. The result may be that transcoding is required for a call that would not normally require it.


The [files] Section

This section of asterisk.conf includes options related to the Asterisk control socket. It is primarily used by remote consoles (asterisk -r). The available options are listed in Table 4.3, “asterisk.conf [files] section”.

Table 4.3. asterisk.conf [files] section

OptionValue/ExampleNotes
astctlpermissions0660Sets the permissions for the Asterisk control socket.
astctlownerrootSets the owner for the Asterisk control socket.
astctlgroupapacheSets the group for the Asterisk control socket.
astctlasterisk.ctlSets the filename for the Asterisk control socket. The default is asterisk.ctl.

The [compat] Section

Occasionally the Asterisk development team decides that the best way forward involves making a change that is not backward-compatible. This section contains some options (listed in Table 4.4, “asterisk.conf [compat] section”) that allow reverting behavior of certain modules back to previous behavior.

Table 4.4. asterisk.conf [compat] section

OptionValue/ExampleNotes
pbx_realtime1.6In versions earlier than Asterisk 1.6.x, the pbx_realtime module would automatically convert pipe characters into commas for arguments to Asterisk applications. This is no longer done by default. To enable this previous behavior, set this option to 1.4.
res_agi1.6In versions earlier than Asterisk 1.6.x, the EXEC AGI command would automatically convert pipe characters into commas for arguments to Asterisk applications. This is no longer done by default. To enable this previous behavior, set this option to 1.4.
app_set1.6Starting with the Asterisk 1.6.x releases, the Set() application only allows setting the value of a single variable. Previously, Set() would allow setting more than one variable by separating them with a &. This was done to allow any characters in the value of a variable, including the & character, which was previously used as a separator. MSet() is a new application that behaves like Set() used to. However, setting this option to 1.4 makes Set() behave like MSet().

modules.conf

This file is not strictly required in an Asterisk installation; however, without any modules Asterisk won’t really be able to do anything, so for all practical purposes, you need a modules.conf file in your /etc/asterisk folder. If you simply define autoload=yes in your modules.conf file, Asterisk will search for all modules in the /usr/lib/asterisk/modules folder and load them at startup.

Although most modules do not use much in the way of resources, and they all load very quickly, it just seems cleaner to our minds to load only those modules that you are planning on using in your system. Additionally, there are security benefits to not loading modules that accept connections over a network.

In the past we felt that explicitly loading each desired module was the best way to handle this, but we have since found that this practice creates extra work. After every upgrade we found ourselves having to edit the modules.conf file to correct all the module differences between releases, and the whole process ended up being needlessly complicated. What we prefer to do these days is to allow Asterisk to automatically load the modules that it finds, but to explicitly tell Asterisk not to load any modules we do not want loaded by use of the noload directive. A sample modules.conf file can be found in the section called “modules.conf”.

The [modules] Section

The modules.conf file contains a single section. The options available in this section are listed in Table 4.5, “modules.conf [modules] section”. With the exception of autoload, all of the options may be specified more than once.

Note

A list of all loadable modules is available in Chapter 2, Asterisk Architecture, with notes on our opinion regarding the popularity/status of each of them.

Table 4.5. modules.conf [modules] section

OptionValue/ExampleNotes
autoloadyesInstead of explicitly listing which modules to load, you can use this directive to tell Asterisk to load all modules that it finds in the modules directory, with the exception of modules listed as not to be loaded using the noload directive. The default, and our recommendation, is to set this option to yes.
preloadres_odbc.soIndicates that a module should be loaded at the beginning of the module load order. This directive is much less relevant than it used to be; modules now have a load priority built into them that solves the problems that this directive was previously used to solve.
loadchan_sip.soDefines a module that should be loaded. This directive is only relevant if autoload is set to no.
noloadchan_alsa.soDefines a module that should not be loaded. This directive is only relevant if autoload is set to yes.
requirechan_sip.soDoes the same thing as load; additionally, Asterisk will exit if this module fails to load for some reason.
preload-requireres_odbc.soDoes the same thing as preload; additionally, Asterisk will exit if this module fails to load for some reason.

indications.conf

The sounds that people expect from the telephone network vary in different parts of the world. Different countries or regions present different sounds for events such as dialtone, busy signal, ringback, congestion, and so forth.

The indications.conf file defines the parameters for the various sounds that a telephone system might be expected to produce, and allows you to customize them. In the early days of Asterisk this file only contained sounds for a limited number of countries, but it is now quite comprehensive.

To assign the tones common for your region to channels, you can simply assign the tonezone using the CHANNEL() function, and that tonezone will apply for the duration of the call (unless changed later):

Set(CHANNEL(tonezone)=[yourcountry]) ; i.e., uk, de, etc.

However, since signaling from a call could come from various places (from the carrier, from Asterisk, or even from the set itself), you should note that simply setting the tonezone in your dialplan does not guarantee that those tones will be presented in all situations.

While Asterisk will run without an indications.conf file, it is strongly recommended that you include one: copy the sample over with sudo cp ~/src/asterisk-complete/1.8/configs/indications.conf.sample, modify the country parameter in the [general] section to match your region, and restart Asterisk.

If your system supports multiple countries (for example, if you have a centralized Asterisk system that has users from different regions), you may not be able to simply define the default country. In this case, you have a couple of options:

  1. Define the country in the channel definition file for the user.

  2. Define the country in the dialplan using the CHANNEL(tonezone) function.

For more information about using Asterisk in different countries, see Chapter 9, Internationalization.

musiconhold.conf

If you plan on selling Asterisk-based telephone systems and you do not change the default music on hold that ships with Asterisk, you are sending the message, loud and clear, that you don’t really know what you are doing.[41]

Part of the problem with music on hold is that while in the past it was common to just plug a radio or CD player into the phone system, the legal reality is that most music licenses do not actually allow you to do this. That’s right: if you want to play music on hold, somebody, somewhere, typically wants you to pay them for the privilege.

So how to deal with this? There are two legal ways: 1) pay for a music on hold license from the copyright holder, or 2) find a source of music that is released under a license suitable for Asterisk.

We’re not here to give you legal advice; you are responsible for understanding what is required of you in order to use a particular piece of music as your music on hold source. What we will do, however, is show you how to take the music you have and make it work with Asterisk.

Converting Music to a Format That Works Best with Asterisk

It’s quite common to have music in MP3 format these days. While Asterisk can use MP3s as a music source, this method is not at all ideal. MP3s are heavily compressed, and in order to play them the CPU has to do some serious work to decompress them in real time. This is fine when you are only playing one song and want to save space on your iPod, but for music on hold, the proper thing to do is convert the MP3 to a format that is easier on the CPU.

If you are familiar with the file formats and have some experience working with audio engineering software such as Audacity, you can convert the files on your PC and upload them to Asterisk. We find it is simpler to upload the source MP3 files to the Asterisk server (say, to the /tmp folder), and then convert them from the command line.

To convert your MP3 files to a format that Asterisk understands, you need to run the commands outlined here (in this example we are using a file named SilentCity.mp3).

CentOS

First, convert the MP3 file to a WAV file:

$ mpg123 -w SilentCity.wav SilentCity.mp3

Then, downsample the resulting WAV file to a sampling rate that Asterisk understands:

$ sox SilentCity.wav -t raw -r 8000 -s -w -c 1 SilentCity.sln

Ubuntu

If you have not done so already, install sox, and the libsox-fmt-all package:

# sudo apt-get install sox libsox-fmt-all

Then, convert your MP3 file directly to the uncompressed SLN format:

$ sox SilentCity.mp3 -t raw -r 8000 -s -w -c 1 SilentCity.sln

Note

In newer versions of sox (e.g., version 14.3.0, which shipped with Ubuntu 10.10), the -w option has changed to -2.

Completing file conversion

The resulting file will exist in the /tmp folder (or wherever you uploaded to) and needs to be copied to the /var/lib/asterisk/moh folder:

$ cp *.sln /var/lib/asterisk/moh

You now need to reload musiconhold in Asterisk in order to have it recognize your new files:

$ asterisk -rx "module unload res_musiconhold.so"
$ asterisk -rx "module load res_musiconhold.so"

To test that your music is working correctly, add the following to the [UserServices] context in your dialplan:

exten => 664,1,NoOp()
    same => n,Progress()
    same => n,MusicOnHold()

Dialing 664 from one of your sets should play a random file from your moh directory.

Conclusion

This chapter helped you complete some initial configuration of Asterisk. From here you can move on to setting up some phones and taking advantage of the many features Asterisk has to offer.



[41] Note that Leif uses the default music, but his excuse is that he’s lazy and wants to go and play Forza on his Xbox. The cobbler’s kids have no shoes.

Chapter 5. User Device Configuration

I don’t always know what I’m talking about, but I know I’m right.

Muhammad Ali

In this chapter we’ll delve into the user devices that you might want to connect to Asterisk, typically VoIP telephones of some sort. Configuring a channel in Asterisk for the device to connect through is relatively straightforward, but you also need to configure the device itself so it knows where to send its calls.[42] In other words, there are two parts to configuring a device on Asterisk: 1) telling Asterisk about the device, and 2) telling the device about Asterisk.

While most devices will have a web-based interface for defining parameters, if you’re putting more than one or two phones into production we recommend using a server-based configuration process, wherein the set is only told the location of a file server. The set will identify itself and download customized files that define the required parameters for that telephone. As an example, these could be XML files on an FTP server. The exact download process and syntax of these files will differ from manufacturer to manufacturer. In this chapter we will only talk about the configuration of sets from the perspective of Asterisk.

Telephone Naming Concepts

Before we get started with configuring Asterisk for our telephones, we are going to recommend some best practices regarding telephone naming, abstracting the concepts of users, extension numbers, and telephones from each other.

In Asterisk, all the system cares about is the channel name. There is really no concept of a user at all,[43] and extensions are simply ways of directing call flow through the system. For example, your dialplan might inform Asterisk that when extension number 100 is requested it should call the phone on my desk, but extension 100 could just as easily call a company voicemail box, play back a prompt, or join a conference room. We can even specify that extension 100 should ring the device on my desk from Monday to Friday between 9 A.M. and 5 P.M., but ring a device on someone else’s desk the rest of the time. Inversely, when a call is made from a device during business hours, the callerID could show a daytime number, and the rest of the time could show an after-hours number (many reception desks become security desks at night).

The abstraction between the name of an extension and what that extension does is a powerful concept in Asterisk, as extension 100 could do a number of things depending on any number of variables that are programmed into the system. This is especially relevant in the context of features such as hot-desking.

Hot-desking is a feature that allows someone to log into a device and receive his calls at that device. Let’s say we have three sales agents who typically work outside of the office, but spend a couple of days each month in the office to do paperwork. Since they are unlikely to be on-site at the same time, instead of having a separate telephone for each of those three sales agents, they could share a single office phone (or on a larger scale, a dozen folks could share a pool of, say, three phones). This scenario illustrates the convenience (and necessity) of allowing the system to separate the concept of a user and extension from the physical phone.

So what are some examples of bad names for telephone devices? Something like a person’s name, such as [SimonLeBon], would be a poor name for a telephone as the phone may also be used by Joan Jett and Rick Astley. The same reasoning can be applied to why you would not want to name a phone based on an extension number: a phone name of [100] would be a poor choice since you might want to reprovision the device for extension 160 in the future, or it might be used by several people with different extensions in a hot-desking solution. Using numeric account names is also very bad from a security perspective and is discussed in more detail in Chapter 26, Security.

A popular way to name a phone is using the MAC address of the device. This is a unique identifier specific to the phone that follows it where it goes and doesn’t directly relate to the user operating the phone or the extension number currently associated with it. Some corporations have stickers they place on their equipment with a bar code and other information that allows them to keep stock of provisioned equipment; these unique codes would also be an acceptable choice to use for phone names as they don’t provide any logical relation to a particular person, but do provide specific information about the devices themselves.

The choice is yours as to how you want to name your phones, but we primarily want to abstract any concept of the telephone being owned by a person, or even its location in the network, since these concepts are outside the realm of Asterisk and can change at any time.

Throughout this book, you’ll see us using phone names that look like MAC addresses (such as 0000FFFF0001 and 0000FFFF0002) to differentiate between devices. You will want to use phone names that match the hardware you are using (or some other string that is unique to the device you are registering).

As a final consideration, we should make it clear that what we are suggesting regarding device names is not a technical requirement. You are free to name your devices anything you want, as long as they meet the requirements of Asterisk’s naming conventions for devices (stay with alphanumeric characters with no spaces and you’ll be fine).

Hardphones, Softphones, and ATAs

There are three types of endpoints you would typically provide your users with that could serve as a telephone set. They are popularly referred to as hardphones, softphones, and Analog Terminal Adaptors (ATAs).

A hardphone is a physical device. It looks just like an office telephone: it has a handset, numbered buttons, etc. It connects directly to the network, and it’s what people are referring to when they talk about a VoIP telephone (or a SIP telephone).

A softphone is a software application that runs on a laptop or desktop. The audio must pass through the PC’s sound system, so you normally need a headset that will work well with telephony applications. More recently, softphone applications have been written for smart phones that allow you to connect to other networks other than just the cellular network. The interface of the softphone is often styled to look like a physical telephone, but this is not necessary.

An ATA is designed to allow traditional analog telephones (and other analog devices, such as fax machines, cordless phones, paging amplifiers, and such) to connect to a SIP network,[44] and will typically be a sandwich-sized box that contains an RJ-11 connector for the phone (commonly referred to as an FXS port), an RJ-45 connector for the network, and a power connector. Some ATAs may support more than one phone.

Hardphones have the advantage that the handsets have good acoustic properties for voice communications. Any decent-quality telephone is engineered to pick up the frequencies of the human voice, filter out unwanted background noise, and normalize the resulting waveform. People have been using telephones for as long as the telephone network has existed, and we tend to like what is familiar, so having a device that communicates with Asterisk using a familiar interface will be attractive to many users. Also, a hardphone does not require your computer to be running all the time.

Disadvantages to hardphones include that they are nonportable and expensive, relative to the many quality softphones on the market today that are available for free. Also, the extra clutter on your desk may not be desirable if you have limited work space, and if you move around a lot and are not generally at the same location, a hardphone is not likely to suit your needs (although, one at each location you frequent might be a valid solution).

Softphones solve the portability issue by being installed on a device that is likely already moving with you, such as your laptop or smart phone. Also, their minimal cost (typically free, or around the $30 price range for a fully featured one) is attractive. Because many softphones are free, it is likely that the first telephone set you connect to Asterisk will be a softphone. Also, because softphones are just software, they are easy to install and upgrade, and they commonly have other features that utilize other peripherals, like a webcam for video calling, or perhaps an ability to load files from your desktop for faxing.

Some of the disadvantages of softphones are the not-always-on nature of the devices, the necessity to put on a headset each time you take a call, and the fact that many PCs will at random times during the day choose to do something other than what the user wants them to do, which might cause the softphone to stop working while some background task hogs the CPU.

ATAs have the advantage of allowing you to connect to your SIP network analog devices,[45] such as cordless phones (which are still superior in many cases to more advanced types of wireless phones[46]), paging amplifiers, and ringers. ATAs can also sometimes be used to connect to old wiring, where a network connection might not function correctly.

The main disadvantage of an ATA is that you will not get the same features through an analog line as you would from a SIP telephone. This is technology that is over a century old.

With Asterisk, we don’t necessarily need to make the choice between having a softphone, a hardphone, or an ATA; it’s entirely possible and quite common to have a single extension number that rings multiple devices at the same time, such as a desk phone, the softphone on a laptop, a cell phone, and perhaps a strobe light in the back of the factory (where there is too much noise for a ringer to be heard).

Asterisk will happily allow you to interact with the outside world in ways that were scarcely dreamed of only a few years ago. As we see more unification of communications applications with the popularity of social networks, communities such as Skype, and more focus on network-based services such as those provided by Google, the flexibility and popularity of software-based endpoints will continue to grow. The blurring of the lines between voice and applications is constantly evolving, and softphones are well positioned to rapidly respond to these changes.

We still like a desk phone, though.

Configuring Asterisk

In this section we’ll cover how to create the sip.conf and iax.conf configuration files in the /etc/asterisk/ directory, which are used for defining the parameters by which SIP and IAX2 devices can communicate with your system.

Note

Asterisk allows devices using many different protocols to speak to it (and therefore to each other). However, the SIP and IAX2 protocols are the most popular and mature VoIP modules, so we will focus our attention on them. For your first Asterisk build, you might be best off not bothering with the other protocols (such as Skinny/SCCP, Unistim, H.323, and MGCP), and getting comfortable working with SIP and IAX2 first. The configuration for the other protocols is similar, and the sample configuration files are full of information and examples, so once you have the basics down, other protocols should be fairly easy to work with.

The channel configuration files, such as sip.conf and iax.conf, contain the configuration for the channel driver, such as chan_iax2.so or chan_sip.so, along with the information and credentials required for a telephony device to contact and interact with Asterisk.

Common information about the channel driver is contained at the top of the configuration file, in the [general] section. All section names are encased in square brackets, including device names. Anything that follows a section name (or device definition, which for our purposes is essentially the same thing) is applied to that section. The [general] section can also contain information to define defaults for device configurations, which are overridden in the section for each device, or in a template. Asterisk also comes with defaults that are hardcoded, so while some settings are mandatory, many other settings can be ignored as long as you are happy with the defaults.

Tip

Asterisk will check for parameters in the following order:

  1. Check the specific section for the relevant channel.

  2. Check the template for the section.

  3. Check the [general] section.

  4. Use the hardcoded defaults.

This means that just because you didn’t specify a setting for a particular parameter doesn’t mean your device isn’t going to have a setting for that parameter. If you are not sure, set the parameter explicitly in the section of the configuration file that deals with that specific channel, or in the relevant template.

This concept should make more sense as you read on.

How Channel Configuration Files Work with the Dialplan

While we haven’t discussed Asterisk dialplans yet, it is useful to be able to visualize the relationship between the channel configuration files (sip.conf, iax.conf) and the dialplan (extensions.conf). The dialplan is the heart of an Asterisk system: it controls how call logic is applied to any connection from any channel, such as what happens when a device dials extension 101 or an incoming call from an external provider is routed. Both the relevant channel configuration file and the extensions.conf file play a role in most calls routed through the system. Figure 5.1, “Relationship of sip.conf to extensions.conf” provides a graphical representation of the relationship between the sip.conf and extensions.conf files.

When a call comes into Asterisk, the identity of the incoming call is matched in the channel configuration file for the protocol in use (e.g., sip.conf). The channel configuration file also handles authentication and defines where that channel will enter the dialplan.

Once Asterisk has determined how to handle the channel, it will pass call control to the correct context in the dialplan. The context parameter in the channel configuration file tells the channel where it will enter the dialplan (which contains all the information about how to handle and route the call).

Figure 5.1. Relationship of sip.conf to extensions.conf

Relationship of sip.conf to extensions.conf

Conversely, if the dialplan has been programmed to dial another device when the request for extension number 101 is being processed, a request to dial telephony device 0000FFFF0002 will use the channel configuration file to determine how to pass the call back out of the dialplan to the telephone on the network (including such details as authentication, codec, and so forth).

A key point to remember is that the channel configuration files control not only how calls enter the system, but also how they leave the system. So, for example, if one set calls another set, the channel configuration file is used not only to pass the call through to the dialplan, but also to direct the call from the dialplan to the destination.

sip.conf

The SIP[47] channel module is arguably the most mature and feature-rich of all the channel modules in Asterisk. This is due to the enormous popularity of the SIP protocol, which has taken over the VoIP/telecom industry and been implemented in thousands of devices and PBXs. If you look through the sip.conf.sample file in the ./configs subdirectory of your Asterisk source you will notice a wealth of options available. Fortunately, the default options are normally all you need, and therefore you can create a very simple configuration file that will allow most standard SIP telephones to connect with Asterisk.

The first thing you need to do is create a configuration file in your /etc/asterisk directory called sip.conf.

Paste or type the following information into the file:

[general]
context=unauthenticated         ; default context for incoming calls
allowguest=no                   ; disable unauthenticated calls
srvlookup=yes                   ; enabled DNS SRV record lookup on outbound calls
udpbindaddr=0.0.0.0             ; listen for UDP requests on all interfaces
tcpenable=no                    ; disable TCP support

[office-phone](!)   ; create a template for our devices
type=friend         ; the channel driver will match on username first, IP second
context=LocalSets   ; this is where calls from the device will enter the dialplan
host=dynamic        ; the device will register with asterisk
nat=yes             ; assume device is behind NAT
                    ; *** NAT stands for Network Address Translation, which allows  
                    ; multiple internal devices to share an external IP address.
secret=s3CuR#p@s5   ; a secure password for this device -- DON'T USE THIS PASSWORD!
dtmfmode=auto       ; accept touch-tones from the devices, negotiated automatically
disallow=all        ; reset which voice codecs this device will accept or offer
allow=ulaw          ; which audio codecs to accept from, and request to, the device
allow=alaw          ; in the order we prefer

; define a device name and use the office-phone template
[0000FFFF0001](office-phone)

; define another device name using the same template
[0000FFFF0002](office-phone)

Open the sip.conf file you’ve just created, and we’ll go over each item.

We’ve created four sections, the first one being the [general] section. This is a standard section that appears at the top of the configuration file for all channel modules, and must always be named in this way. The [general] section contains general configuration options for how that protocol relates to your system, and can be used to define default parameters as well.

For example, we’ve defined the default context as unauthenticated, to ensure that we have explicitly declared where unauthenticated guest calls will enter the dialplan (rather than leaving that to chance). We’ve named it unauthenticated to make it obvious that calls processed in this context are not trusted, and thus should not be able to do things such as make outbound calls to the PSTN (which could potentially cost money, or represent identity theft). You should be aware that we could have used any name we wanted, and also that there needs to be an identically named context in extensions.conf to define the call flow for unauthenticated calls.

The next option is allowguest, which we’ve disabled as we don’t want to accept any unauthenticated calls at this time. Keep in mind that for some channels you may actually want to accept unauthenticated calls. A common use for allowing unauthenticated calls is for companies that allow dialing by uniform resource identifiers (URIs), like email addresses. If we wanted to allow customers to call us from their phones without having to authenticate, we could enable guest calls and handle them in the unauthenticated context defined by the previous option.

Note

You may be wondering why you might ever want to allow unauthenticated calls. The reason is that if you publish your SIP URI on your business cards (e.g., sip:leif.madsen@shifteight.org), calls to that URI will fail if your unauthenticated context simply hangs up. What you want instead is for your unauthenticated context to put incoming calls into a controlled environment. You may wish to allow the calls, but you won’t necessarily trust them.[48]

The srvlookup option is used to enable Asterisk to perform a lookup via a DNS SRV record, which is typically used for outbound connections to service providers. We’ll talk more about Asterisk and DNS in Chapter 12, Internet Call Routing.

The udpbindaddr[49]option takes the value of an IP address or 0.0.0.0 to tell Asterisk which network interface it should listen to for requests carried by the UDP network transport protocol (which is the protocol that actually carries the voice channels). By defining 0.0.0.0, we’re instructing the channel driver to listen on all available interfaces. Alternatively, we could limit VoIP connections for this protocol to a single interface by defining the IP address of a specific network interface on our system.

Warning

Currently in Asterisk the udpbindaddr and tcpbindaddr options are an all-or-one proposition. In other words, if you have three NICs in your system, you can’t restrict VoIP traffic to two of them: it’s either one only, or all of them.

The tcpenable option allows us to accept requests via the TCP network transport protocol. For now we’ve disabled it, as the UDP method is currently more mature (and more popular) and we’re attempting to eliminate as many barriers as possible. Having said that, feel free to test TCP support once you’re comfortable configuring your devices.

Note

There are also tlsenable and tlsbindaddr options for enabling SIP over TLS (encrypted SIP). We’ll cover the configuration of SIP with TLS in Chapter 7, Outside Connectivity.

The next section we’ve defined is a template we have chosen to name [office-phone](!). We’ve created it as a template so that we can use the values within it for all of our devices.

Tip

Following the section name with (!) tells Asterisk to treat this section as a template. By doing this we eliminate the need to repetitively add and change configuration options for every device we choose to define. Templates are extremely useful and are available in all of Asterisk’s configuration files. If you want to change something for an individual device that was previously defined in the template for that device, you can do that under the section header, and it will override what was defined by the template. It is not necessary to use templates, but they are extremely handy, and we use them extensively.

In the [office-phone] template we’ve defined several options required for authentication and control of calls to and from devices that use that template. The first option we’ve configured is the type, which we’ve set to friend. This tells the channel driver to attempt to match on name first, and then IP address.

When a request from a telephone is received and authenticated by Asterisk, the requested extension number is handled by the dialplan in the context defined in the device configuration; in our case, the context named LocalSets.

The host option is used when we need to send a request to the telephone (such as when we want to call someone). Asterisk needs to know where the device is on the network. By defining the value as dynamic, we let Asterisk know that the telephone will tell us where it is on the network instead of having its location defined statically. If we wanted to define the address statically, we could replace dynamic with an IP address such as 192.168.128.30.

The nat option is used to tell Asterisk to enable some tricks to make phone calls work when a SIP phone may be located behind a NAT. This is important because the SIP protocol includes IP addresses in messages. If a phone is on a private network, it may end up placing private addresses in SIP messages, which are often not useful.

The password for the device is defined by the secret parameter. While this is not strictly required, you should note that it is quite common for unsavory folks to run phishing scripts that look for exposed VoIP accounts with insecure passwords and simple device names (such as a device name of 100 with a password of 1234). By utilizing an uncommon device name such as a MAC address, and a password that is a little harder to guess, we can significantly lower the risk to our system should we need to expose it to the outside world.

Tip

You can generate a secure password using one of several password generators available on the Internet and on your operating system. Here is a simple script that you can run at your console to generate one:

          $ 
          dd if=/dev/random count=1 bs=8 2>/dev/null | base64 | sed -e 's/=*$//'
        

Warning

Do not use the password we have defined in the example. This book will be available online and can be downloaded by anyone, and that particular password is almost certain to become one of the first passwords added to the list employed by VoIP phishing scripts in brute-force password attacks. If your SIP ports are exposed to the Internet and you use simple passwords, rest assured that you will eventually be defrauded.

The dtmfmode option is used to define which DTMF (touch-tone) format Asterisk should expect to be sent by the telephone. The four options are: info, inband, rfc2833, and auto. The info value means to use the SIP INFO method, inband is for inband audio tones, and rfc2833 is for the out-of-band method defined by that RFC. Using auto allows Asterisk to automatically determine which DTMF mode to use (it prefers rfc2833 if available).

The last two options, disallow and allow (sip.conf), are used to control which audio codecs are accepted from and offered to the telephone. By defining disallow=all first, we’re telling Asterisk to reset any previously defined codec definitions in the [general] section (or the internal defaults); then we explicitly declare which codecs we’ll accept (and the order we prefer). In our example we’ve enabled both ulaw and alaw, with ulaw most preferred (if you are outside of Canada or the US, you’ll likely want to declare alaw first).

Now that we’re finished with our template, we can define our device names and, utilizing the office-phone template, greatly simplify the amount of details required under each device section. The device name is defined in the square brackets, and the template to be applied is defined in the parentheses following the device name. We can add additional options to the device name by specifying them below the device name:

[0000FFFF0003](office-phone) ; template must be on same line and no space between
secret=@N0th3rP4S5
allow=gsm

As far as the SIP module in Asterisk can tell, it will end up reading this in as if it was a section defined like this, which is a configuration section with all of the options specified from the template first:

[0000FFFF0003]

;
; These options came from the template section.
;
type=friend
context=LocalSets
host=dynamic
nat=yes 
secret=s3CuR#p@s5
dtmfmode=auto
disallow=all
allow=ulaw
allow=alaw

;
; These options came from the specific section.
;
secret=@N0th3rP4S5 ; Overrides the secret from the template
allow=gsm          ; Adds gsm to the list of allowed codecs

Note that if you specify an option that was also specified in the template, the module will see that option twice. For most options, it will override the value in the template, but for some, such as type, allow, and disallow, it will not.

iax.conf

IAX2 stands for the Inter-Asterisk eXchange protocol, version 2. It was originally developed to connect Asterisk systems together across different physical networks, and especially those behind firewalls and NAT devices. IAX2 was designed to limit the number of ports required to carry VoIP calls across a firewall, and to easily traverse networks that employed NAT devices (which historically have been problematic for the SIP protocol). As Asterisk has developed over the years, the IAX2 protocol has matured. It was standardized in an IETF RFC in 2009,[50] but IAX2 has not become popular with hardware vendors, possibly due to the relative recency of the RFC, and certainly due to the fact that SIP is far and away the most recognized VoIP protocol in terms of mind-share (i.e., nontechnical folks have probably heard of SIP). IAX2, however, has advantages that make it a protocol worth discussing.

One of the primary advantages of IAX is single-port firewall penetration. All traffic, including signaling and audio data, is transferred over a single UDP port (4569), which can greatly simplify securing the VoIP network.[51]

Another advantage is IAX2 trunking, which encapsulates packets for several voice frames into the same datagram using a single IAX2 header. The benefit of this is a reduction in the amount of overhead required to send many simultaneous calls between two endpoints. The amount of bandwidth saved with IAX2 trunking when sending just a couple of calls between locations is pretty insignificant, but when you start scaling to the size of dozens or hundreds of calls, the savings can be substantial.

For now, we’re only interested in the minimal configuration required to get our IAX2 endpoints talking to each other, so let’s explore what we need to configure in iax.conf to do so.

First, we need to create our iax.conf file in the /etc/asterisk configuration directory and add the following configuration information to the file:

[general]
autokill=yes   ; don't stall for a long time if other endpoint doesn't respond
srvlookup=yes  ; enable DNS SRV lookups for outbound calls

[office-phone](!)    ; template for IAX-based office phones
type=friend          ; Asterisk will allow calls to and from this phone
host=dynamic         ; inform Asterisk that the phone will tell us where
                     ;   it is on the network
secret=my5UP3rp@s5!  ; a secure password -- which means DON'T USE THIS ONE!
context=LocalSets    ; the context where incoming requests will enter the dialplan
disallow=all         ; reset the available voice codecs
allow=ulaw           ; prefer the ulaw codec
allow=alaw           ; but also allow the alaw codec

[0000FFFF0004](office-phone) ; define our first phone with the office-phone template

[0000FFFF0005](office-phone) ; define another phone with our office-phone template

Let’s go over the options we added to this file, starting first with the [general] section. This is where we define our default configuration, our global options, and our general channel driver setup. There are many options we can define here, and we encourage you to check out the iax.conf.sample file in the configs directory of your Asterisk source,[52] but since we’re looking for a straightforward configuration, we’re going to allow many of the default options to be applied.

One option we have added is autokill, which is used to instruct the chan_iax2.so channel driver not to wait around too long on stalled connections. Also, srvlookup has been enabled to allow DNS SRV lookups for outgoing calls.

The next section we’ve defined is named [office-phone](!), which is a template that contains the options we’ll apply to our IAX phones and the authentication information required for communication between the phones and Asterisk.

Tip

As mentioned in the preceding section, following the section name with (!) tells Asterisk to treat this section as a template. Templates are useful, so use them(!).

The first option we’ve configured in our template is the type. We’ve defined the type to be friend, which informs Asterisk that we plan on placing calls to the phone and that we expect to receive requests (calls) from the phone.

Note

The other two types are user and peer. In IAX2, a friend is a combination of both a user and a peer, which is common for telephones because we expect to send calls to them, and to receive requests for placing calls from them. We could alternatively define two separate sections with the same name with types of user and peer, and then define only the required information for each of those types; or if we only ever expected to send calls to or place calls using a section (such as in the case of an inbound- or outbound-only service provider), we would define it as only either a user or a peer. However, in the vast majority of cases, just utilizing the type of friend is the most logical choice.

Note the difference between the meaning of the type option in iax.conf versus sip.conf (see the sidebar SIP Configuration Matching and the type Option). In iax.conf, the meaning is much simpler: it only has to do with the direction of the phone calls.

Following the type option, we’ve set host to dynamic, which means the phone will register with us to identify where it exists on the network (so that we know where to send its calls). Alternatively, we could statically define an IP address such as 192.168.128.50 where all calls will be sent to and accepted from. This will only work if the device will always have the same IP address.

The next option is secret, which defines the password.

Warning

You should make sure you are implementing a secure password here, especially if you plan on opening your system up to the outside world at all. Do not use something stupid such as 1234, or you’ll regret it. No, seriously. We’re not kidding. Not even in the lab.

The number of successful attacks on VoIP-enabled telephone systems (not just Asterisk) is on the rise, and will continue to get worse. Commonly, successful intrusions are due to weak passwords. If you get in the habit of using strong passwords now, you’ll have that much more protection in the future.

Tip

You can generate a complex password using a password generator like those available on the Internet and on your operating system. Here is a simple script that you can run at the Linux shell prompt to generate a string that’ll be suitable as a password:

$ dd if=/dev/random count=1 bs=8 2>/dev/null | base64 | sed -e 's/=*$//'

Warning

Do not use the password we have defined in the example. You can be sure that shortly after this book is published, that will be one of the first passwords a brute-force bot will try to use on your system.

The context option defines the context at which this channel will enter the dialplan. When a call is placed by a telephone and the request is received by Asterisk, it is handled by the logic defined in the context configured here within the dialplan (extensions.conf).

Following that are the disallow and allow options. These define the codecs that will be allowed for this channel (in order of preference). The directive disallow=all resets any default codecs that may have been permitted in the [general] section (or as part of the channel defaults). Then, we define the specific codecs we wish to permit with allow.

Note

If we wanted to use specific codecs for one of our devices, we could define that codec within the device configuration section for that channel simply by adding it below the device section header:

[0004F2FF0006](office-phone)
disallow=all ; Clear previous codec settings.
allow=gsm    ; Allow only gsm.

Modifying Your Channel Configuration Files for Your Environment

Our examples so far have been based on hypothetical device names. To create actual channels based on whatever you have in your environment, you will want to change the device names in your sip.conf and iax.conf files to something that makes more sense.

For example, if you have a Polycom IP 430 set with a MAC address of 0004f2119698, you’ll want to define a device identifier in sip.conf for that device:

[0004f2119698](office-phone)

If you have an IAX softphone on your PC that you wish to use, your iax.conf file may want something like this:

[001b63a28ccc](office-phone) ; you could have a comment like Leif's Laptop

Remember that you can name your devices anything you want. Asterisk doesn’t care, but for ease of management, make sure you choose a naming convention that is logical, scalable, and sustainable.

Loading Your New Channel Configurations

In order to inform Asterisk of the new configurations, you will need to pass it a command that instructs it to reload the relevant configuration file. The Asterisk CLI is where you can pass various commands to a running Asterisk system.

The Asterisk CLI

The best way to see what is happening with your Asterisk system is through the Asterisk CLI. This interface provides various levels of output to let you know what is happening on your system, and offers a wealth of useful utilities to allow you to affect your running system. Begin by calling up the Asterisk CLI and reloading the configuration files for your channel modules:

$ sudo asterisk -r
*CLI> module reload chan_sip.so
*CLI> module reload chan_iax2.so

Verify that your new channels have been loaded:

*CLI> sip show peers
*CLI> sip show users
*CLI> iax2 show peers
*CLI> iax2 show users

Note

At this point your Asterisk system should be configured to handle registrations from the defined devices. Calls to and from the sets will not work until the configuration on the devices has been completed. Since each device is different in this regard, detailed configuration instructions for each model are outside of the scope of this book.

Testing to Ensure Your Devices Have Registered

Once your device has registered to Asterisk, you will be able to query the location and state of the device from the Asterisk CLI.

Note

It is a common misconception that registration is how a device authenticates itself for the purpose of obtaining permission to make calls. This is incorrect. The only purpose of registration is to allow a device to identify its location on the network, so that Asterisk[53] knows where to send calls intended for that device.

Authentication for outgoing calls is an entirely separate process and always happens on a per-call basis, regardless of whether a set has registered. This means that your set may be able to make calls, but not receive them. This will normally happen when the set has not registered successfully (so Asterisk does not know where it is), and yet has the correct credentials for making calls (so Asterisk is willing to accept calls from it).

To check the registration status of a device, simply call up the Asterisk CLI:

$ sudo asterisk -r

Typing the following command returns a listing of all the peers that Asterisk knows about (regardless of their state):

*CLI> sip show peers
Name/username              Host            Dyn Nat ACL Port     Status
0000FFFF0001/0000FFFF0001    192.168.1.100    D   N      5060     Unmonitored
0000FFFF0002/0000FFFF0002    192.168.1.101    D   N      5060     Unmonitored

Note

You may notice that the Name/username field does not always show the full name of the device. This is because this field is limited to 25 characters.

Note that the Status in our example is set to Unmonitored. This is because we are not using the qualify=yes option in our sip.conf file.

Analog Phones

There are two popular methods for connecting analog phones to Asterisk. The first is by using an ATA that most commonly connects to Asterisk using the SIP protocol. The Asterisk configuration for an ATA is the same as it would be for any other SIP-based handset. The other method is to directly connect the phones to the Asterisk server using telephony hardware from a vendor such as Digium. Digium sells telephony cards that can be added to your server to provide FXS ports for connecting analog phones (or fax machines). For the purposes of demonstrating the configuration, we’re going to show the configuration required if you had a Digium AEX440E card, which is an AEX410 half-length PCI-Express with four FXS modules and hardware-based echo cancellation.

Tip

Regardless of which hardware you are using, consult your vendor’s documentation for any hardware-specific configuration requirements.

First, ensure that both Asterisk and DAHDI are installed (refer back to the section called “How to Install It” for instructions). Note that DAHDI must be installed before you install Asterisk. When you install DAHDI, be sure to install the init script as well. This will ensure that your hardware is properly initialized when the system boots up. The init script is installed from the DAHDI-tools package.

The init script uses the /etc/dahdi/modules file to determine which modules should be loaded to support the hardware in the system. The installation of the init script attempts to automatically set up this file for you, but you should check it to make sure it is correct:

# Autogenerated by tools/xpp/dahdi_genconf (Dahdi::Config::Gen::Modules) on 
# Tue Jul 27 10:31:46 2010
# If you edit this file and execute tools/xpp/dahdi_genconf again,
# your manual changes will be LOST.
wctdm24xxp

There is one more configuration file required for DAHDI: /etc/dahdi/system.conf. It looks like this:

# Specify that we would like DAHDI to generate tones that are
# used in the United States.
loadzone = us
defaultzone = us

# We have 4 FXS ports; configure them to use FXO signaling.
fxoks = 1-4

Tip

This configuration assumes the card is being used in the United States. For some tips on internationalization, see Chapter 9, Internationalization.

If the card you are configuring does not have hardware-based echo cancellation, another line will need to be added to /etc/dahdi/system.conf to enable software-based echo cancellation:

echocanceller = mg2,1-4

Tip

MG2 is the recommended echo canceller that comes with the official DAHDI package. There is another open source echo canceller out there that is compatible with DAHDI, called OSLEC (Open Source Line Echo Canceller). Many people report very good results with the use of OSLEC. For more information about the installation of OSLEC on your system, see the website at http://www.rowetel.com/blog/oslec.html.

Now, use the init script to load the proper modules and initialize the hardware:

$ sudo /etc/init.d/dahdi start
Loading DAHDI hardware modules:
  wctdm24xxp:                                              [  OK  ]

Running dahdi_cfg:                                         [  OK  ]

Now that DAHDI has been configured, it is time to move on to the relevant configuration of Asterisk. Once Asterisk is installed, ensure that the chan_dahdi module has been installed. If it is not loaded in Asterisk, check to see if it exists in /usr/lib/asterisk/modules/. If it is there, edit /etc/asterisk/modules.conf to load chan_dahdi.so. If the module is not present on disk, DAHDI was not installed before installing Asterisk; go back and install it now (see the section called “DAHDI” for details). You can verify its presence using the following command:

*CLI> module show like chan_dahdi.so
Module                         Description                              Use Count 
chan_dahdi.so                  DAHDI Telephony Driver                   0         
1 modules loaded

Next, you must configure /etc/asterisk/chan_dahdi.conf. This is the configuration file for the chan_dahdi module, which is the interface between Asterisk and DAHDI. It should look like this:

[trunkgroups]

; No trunk groups are needed in this configuration.

[channels]

; The channels context is used when defining channels using the
; older deprecated method.  Don't use this as a section name.

[phone](!)
;
; A template to hold common options for all phones.
;
usecallerid = yes
hidecallerid = no
callwaiting = no
threewaycalling = yes
transfer = yes
echocancel = yes
echotraining = yes
immediate = no
context = LocalSets
signalling = fxo_ks ; Uses FXO signaling for an FXS channel 

[phone1](phone)
callerid = "Mark Michelson" <(256)555-1212>
dahdichan = 1

[phone2](phone)
callerid = "David Vossel" <(256)555-2121>
dahdichan = 2

[phone3](phone)
callerid = "Jason Parker" <(256)555-3434>
dahdichan = 3

[phone4](phone) 
callerid = "Matthew Nicholson" <(256)555-4343>
dahdichan = 4

You can verify that Asterisk has loaded your configuration by running the dahdi show channels CLI command:

*CLI> dahdi show channels
   Chan Extension  Context         Language   MOH Interpret    Blocked    State     
 pseudo            default                    default                     In Service
      1            LocalSets                  default                     In Service
      2            LocalSets                  default                     In Service
      3            LocalSets                  default                     In Service
      4            LocalSets                  default                     In Service

For detailed information on a specific channel, you can run dahdi show channel 1.

A Basic Dialplan to Test Your Devices

We’re not going to dive too deeply into the dialplan just yet, but an initial dialplan that you can use to test your newly registered devices will be helpful. Place the following contents in /etc/asterisk/extensions.conf:

[LocalSets]

exten => 100,1,Dial(SIP/0000FFFF0001) ; Replace 0000FFFF0001 with your device name

exten => 101,1,Dial(SIP/0000FFFF0002) ; Replace 0000FFFF0002 with your device name

;
; These will allow you to dial each of the 4 analog phones configured
; in the previous section.
;
exten => 102,1,Dial(DAHDI/1)
exten => 103,1,Dial(DAHDI/2)
exten => 104,1,Dial(DAHDI/3)
exten => 105,1,Dial(DAHDI/4)

exten => 200,1,Answer()
    same => n,Playback(hello-world)
    same => n,Hangup()

This basic dialplan will allow you to dial your SIP devices using extensions 100 and 101. The four lines of the analog card can be dialed with extensions 102 through 105, respectively. You can also listen to the hello-world prompt that was created for this book by dialing extension 200. All of these extensions are arbitrary numbers, and could be anything you want. Also, this is by no means a complete dialplan; we’ll develop it further in later chapters.

You will need to reload your dialplan before changes will take effect in Asterisk. You can reload it from the Linux shell:

$ sudo asterisk -rx "dialplan reload"

or from the Asterisk CLI:

*CLI> dialplan reload

You should now be able to dial between your two new extensions. Open up the CLI in order to see the call progression. You should see something like this (and the set you are calling should ring):

    -- Executing [100@LocalSets:1] Dial("SIP/0000FFFF0001-0000000c", 
       "SIP/0000FFFF0001") in new stack
    -- Called 0000FFFF0001
    -- SIP/0000FFFF0001-0000000d is ringing

If this does not happen, you are going to need to review your configuration and ensure you have not made any typos.

Under the Hood: Your First Call

In order to get you thinking about what is happening under the hood, we’re going to briefly cover some of what is actually happening with the SIP protocol when two sets on the same Asterisk system call each other.

Asterisk as a B2BUA

Bear in mind that there are actually two calls going on here: one from the originating set to Asterisk, and another from Asterisk to the destination set. SIP is a peer-to-peer protocol, and from the perspective of the protocol there are two calls happening. The SIP protocol is not aware that Asterisk is bridging the calls; each set understands its connection to Asterisk, with no real knowledge of the set on the other side. It is for this reason that Asterisk is often referred to as a B2BUA (Back to Back User Agent). This is also why it is so easy to bridge different protocols together using Asterisk.

For the call you just made, the dialogs shown in Figure 5.2, “SIP dialogs” will have taken place.

For more details on how SIP messaging works, please refer to Appendix B, Protocols for VoIP and the SIP RFC at http://www.ietf.org/rfc/rfc3261.txt.

Figure 5.2. SIP dialogs

SIP dialogs

Conclusion

In this chapter we learned best practices for device naming by abstracting the concepts of users, extension numbers, and devices, and how to define the device configuration and authentication parameters in the channel configuration files. Next, we’ll delve into the magic of Asterisk that is the dialplan, and see how simple things can create great results.



[42] This has nothing to do with Asterisk configuration, and each hardware manufacturer will have its own tools to allow you to configure its devices.

[43] Actually, Asterisk does try to implement and abstract the concepts of users and devices internally by using the users.conf file; however, it is typically only used by the Asterisk GUI. Abstracting the concepts logically using the dialplan is easier to understand and far more flexible.

[44] Or any other network, for that matter. ATAs could more formally be said to be analog-to-digital gateways, where the nature of the digital protocol may vary (e.g., proprietary ATAs on traditional PBXs).

[45] An ATA is not the only way to connect analog phones. Hardware vendors such as Digium sell cards that go in the Asterisk server and provide analog telephony ports.

[46] For a really awesome cordless analog phone, you want to check out the EnGenius DuraFon devices, which are expensive, but impressive.

[47] The SIP RFC is a long read, but about the first 25 pages are a good introduction. Check it out at http://www.ietf.org/rfc/rfc3261.txt.

[48] The whole concept of security and trust on a VoIP network is something that can become quite complex. Spammers are already hard at work figuring out this technology, and you need to be aware of the concepts. We’ll cover this in more depth later in the book, such as in Chapter 7, Outside Connectivity and Chapter 26, Security.

[49] The complement to this option is tcpbindaddr, used for listening for requests carried via the TCP network transport protocol.

[51] SIP, which has separate signaling and voice data protocols and ports, requires port 5060 for signaling, and at least two RTP ports for every active call for voice. By default, Asterisk uses ports 5060 for SIP and 10,000 through 20,000 for RTP, although that can be tuned with the rtp.conf file.

[52] We also encourage you to read the section called “sip.conf” in this chapter, as it contains many concepts that apply equally to other Asterisk configuration files.

[53] Or any other SIP registrar server, for that matter.

Chapter 6. Dialplan Basics

Everything should be made as simple as possible, but not simpler.

Albert Einstein

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.

Dialplan Syntax

The Asterisk dialplan is specified in the configuration file named extensions.conf.

Tip

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.

Contexts

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 the section called “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]

Note

Context names have a maximum length of 79 characters (80 characters – 1 terminating null).

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 the section called “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, “Relation between channel configuration files and contexts in the dialplan” illustrates the relationship between channel configuration files and contexts in the dialplan.

Figure 6.1. Relation between channel configuration files and contexts in the dialplan

Relation between channel configuration files and contexts in the dialplan

Note

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.

Warning

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, Security 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.

Extensions

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.

Tip

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:

  • The name (or number) of the extension

  • The priority (each extension can include multiple steps; the step number is called the “priority”)

  • The application (or command) that will take place at that step

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().

Priorities

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()

Unnumbered priorities

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.

The 'same =>' operator

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

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.

Warning

A very common mistake when writing labels is to insert a comma between the n and the (, like this:

exten => 123,n,(label),application() ;<-- THIS IS NOT GOING TO WORK

This mistake will break that part of your dialplan, and you will get an error stating that the application cannot be found.

Applications

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.

Tip

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(), Playback(), and Hangup() Applications

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]

Tip

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, Installing Asterisk). 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.

A Simple Dialplan

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, User Device Configuration). We’re going to add to that.

Hello World

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, User Device Configuration, 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()

Tip

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, User Device Configuration 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

or from the shell with:

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

Important

We do not recommend that you move forward in this book until you have verified the following:

  1. Calls between extension 100 and 101 are working

  2. Calling extension 200 plays “Hello World”

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.

Building an Interactive Dialplan

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.

The Goto(), Background(), and WaitExten() Applications

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

Note

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.

Tip

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.

Handling Invalid Entries and Timeouts

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().

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

Argument 1: Destination

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/guest@misery.digium.com/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)

Argument 2: Timeout

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.

Argument 3: Option

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()

Argument 4: URI

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.

Tip

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, External Services, and more specifically the section on Jabber in the section called “Using XMPP (Jabber) with Asterisk”.

Updating the dialplan

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()

Blank arguments

Note that the second, third, and fourth arguments may be left blank; only the first argument is required. For example, if you want to specify an option but not a timeout, simply leave the timeout argument blank, like this:

exten => 1,1,Dial(DAHDI/1,,m)

Using Variables

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.

Tip

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.

Global variables

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

Channel variables

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

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.

Adding variables to our dialplan

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 the section called “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.

Pattern Matching

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.

Pattern-matching syntax

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.

Warning

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

Matches any single digit from 0 to 9.

Z

Matches any single digit from 1 to 9.

N

Matches any single digit from 2 to 9.

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

Warning

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].
! (bang)

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.

Pattern-matching examples

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.

Let’s try another:

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

And finally this one:

_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.)

Using the ${EXTEN} channel variable

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.

Includes

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, Outside Connectivity.

Conclusion

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 the section called “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, The Automated Attendant and Chapter 17, Interactive Voice Response.

[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 the section called “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, The Automated Attendant.

[62] See the dialplan function TIMEOUT() for information on how to change the default timeouts. See Chapter 10, Deeper into the Dialplan 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 the section called “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.

Chapter 7. Outside Connectivity

You cannot always control what goes on outside. But you can always control what goes on inside.

Wayne Dyer

In the previous chapters, we have covered a lot of important information that is essential to a working Asterisk system. However, we have yet to accomplish the one thing that is vital to any useful PBX: namely, connecting it to the outside world. In this chapter we will rectify that situation.

The architecture of Asterisk is significant, due in large part to the fact that it treats all channel types as equal. This is in contrast to a traditional PBX, where trunks (which connect to the outside world) and extensions (which connect to users and resources) are very different. The fact that the Asterisk dialplan treats all channels in a similar manner means that in an Asterisk system you can accomplish very easily things that are much more difficult (or impossible) to achieve on a traditional PBX.

This flexibility does come with a price, however. Since the system does not inherently know the difference between an internal resource (such as a telephone set) and an external resource (for example, a telco circuit), it is up to you to ensure that your dialplan handles each type of resource appropriately.

The Basics of Trunking

The purpose of trunking is to provide a shared connection between two entities. For example, a trunk road would be a highway that connects two towns together. Railroads used the term “trunk” extensively, to refer to a major line that connected feeder lines together.

Similarly, in telecom, trunking is used to connect two systems together. Carriers use telecom trunks to connect their networks together, and in a PBX, the circuits that connect the PBX to the outside world are commonly referred to as trunks (although the carriers themselves do not generally consider these to be trunks). From a technical perspective, the definition of a trunk is not as clear as it used to be (PBX trunks used totally different technology from station circuits), but as a concept, trunks are still very important. For example, with VoIP, everything is actually peer-to-peer (so from a technology perspective there isn’t really such a thing as a trunk anymore), but it is still useful to be able to differentiate between VoIP resources that connect to the outside world and VoIP resources that connect to user endpoints (such as SIP telephones).

It’s probably easiest to think of a trunk as a collection of circuits that service a route. So, in an Asterisk PBX, you might have trunks that go to your VoIP provider for long-distance calls, trunks for your PSTN circuits, and trunks that connect your various offices together. These trunks might actually run across the same network connection, but in your dialplan you could treat them quite differently.

While we believe that VoIP will eventually completely replace the PSTN, many of the concepts that are in use on VoIP circuits (such as a “phone number”) owe their existence more to history than any technical requirement, and thus we feel it will be helpful to discuss using traditional PSTN circuits with Asterisk before we get into VoIP.

If the system you are installing will use VoIP circuits only, that is not a problem. Go straight to the VoIP section of this chapter,[68] and we’ll take you through what you need to do. We do recommend reading the PSTN sections at your convenience, since there may be general knowledge in them that could be of use to you, but it is not strictly required in order to understand and use Asterisk.

Fundamental Dialplan for Outside Connectivity

In a traditional PBX, external lines are generally accessed by way of an access code that must be dialed before the number.[69] It is common to use the digit 9 for this purpose.

In Asterisk, it is similarly possible to assign 9 for routing of external calls, but since the Asterisk dialplan is so much more intelligent, it is not really necessary to force your users to dial 9 before placing a call. Typically, you will have an extension range for your system (say, 100–199), and a feature code range (*00 to *99). Anything outside those ranges that matches the dialing pattern for your country or region can be treated as an external call.

If you have one carrier providing all of your external routing, you can handle your external dialing through a few simple pattern matches. The example in this section is valid for the North American Numbering Plan (NANP). If your country is not within the NANP (which serves Canada, the US, and several Caribbean countries), you will need a different pattern match.

The [globals] section contains two variables, named LOCAL and TOLL.[70] The purpose of these variables is to simplify management of your dialplan should you ever need to change carriers. They allow you to make one change to the dialplan that will affect all places where the specified channel is referred to:

[globals]
LOCAL=DAHDI/G0           ; assuming you have a PSTN card in your system
TOLL=SIP/YourVoipCarrier ; as defined in sip.conf

The [external] section contains the actual dialplan code that will recognize the numbers dialed and pass them to the Dial() application[71]:

[external]
exten => _NXXNXXXXXX,1,Dial(${LOCAL}/${EXTEN})  ; 10-digit pattern match for NANP
exten => _NXXXXXX,1,Dial(${LOCAL}/${EXTEN})    ; 7-digit pattern match for NANP
exten => _1NXXNXXXXXX,1,Dial(${TOLL}/${EXTEN}) ; Long-distance pattern match for NANP
exten => _011.,1,Dial(${TOLL}/${EXTEN})        ; International pattern match for 
                                               ; calls made from NANP

; This section is functionally the same as the above section. 
; It is for people who like to dial '9' before their calls
exten => _9NXXNXXXXXX,1,Dial(${LOCAL}/${EXTEN:1})
exten => _9NXXXXXX,1,Dial(${LOCAL}/${EXTEN:1})
exten => _91NXXNXXXXXX,1,Dial(${TOLL}/${EXTEN:1})
exten => _9011.,1,Dial(${TOLL}/${EXTEN:1})

In any context that would be used by sets or user devices, you would use an include=> directive to allow access to the external context:

[LocalSets]
include => external

Warning

It is critically important that you do not include access to the external lines in any context that might process an incoming call. The risk here is that a phishing bot could eventually gain access to your outgoing trunks (you’d be surprised at how common these phishing bots are).

We cannot stress enough how important it is that you ensure that no external resource can access your toll lines.

PSTN Circuits

The Public Switched Telephone Network (PSTN) has existed for over a century. It is the precursor to many of the technologies that shape our world today, from the Internet to MP3 players.

Traditional PSTN Trunks

There are two types of fundamental technology that phone carriers use to deliver telephone circuits: analog and digital.

Analog telephony

The first telephone networks were all analog. The audio signal that you generated with your voice was used to generate an electrical signal that was carried to the other end. The electrical signal had the same characteristics as the sound being produced.

Analog circuits have several characteristics that differentiate them from other circuits you might wish to connect to Asterisk:

  • No signaling channel exists—most signaling is electromechanical.

  • Disconnect supervision is usually delayed by several seconds, and is not completely reliable.

  • Far-end supervision is minimal (for example, answer supervision is lacking).

  • Differences in circuits means that audio characteristics will vary from circuit to circuit, and will require tuning.

Analog circuits that you wish to connect to your Asterisk system will need to connect to a Foreign eXchange Office (FXO) port. Since there is no such thing as an FXO port in any standard computer, an FXO card must be purchased and installed in the system in order to connect traditional analog lines.[72]

Analog ports are not generally used in medium to large systems. They are most commonly used in smaller offices (less than 10 lines; less than 30 phones). Your decision to use analog might be based on some of the following factors:

  • Availability of digital trunks in your area

  • Cost (analog is less expensive at smaller densities, but more expensive at higher densities)

  • Logistics (if you already have analog lines installed, you may wish to keep them)

From a technical perspective, you would normally want to have digital rather than analog circuits. Reality does not always accommodate, though, so analog will likely be around for a few more years yet.

Digital telephony

Digital telephony was developed in order to overcome many of the limitations of analog. Some of the benefits of digital circuits include:

  • No loss of amplitude over long distances

  • Reduced noise on circuits (especially long-distance circuits)

  • Ability to carry more than one call per circuit

  • Faster call setup and teardown

  • Richer signaling information (especially if using ISDN)

  • Lower cost for carriers

  • Lower cost for customers (at higher densities)

In an Asterisk system (or any PBX, for that matter), there are several types of digital circuits you might want to connect:

T1 (24 channels)

Used in Canada and the United States (mostly for ISDN-PRI)

E1 (32 channels)

Used in the rest of the world (ISDN-PRI or MFC/R2)

BRI (2 channels)

Used for ISDN-BRI circuits (Euro-ISDN)

Note that the physical circuit can be further defined by the protocol running on the circuit. For example, a T1 could be used for either ISDN-PRI, or CAS, and an E1 could be used for ISDN-PRI, CAS, or MFC/R2. We’ll discuss the different protocols in the next section.

Installing PSTN Trunks

Depending on the hardware you have installed, the process for installing your PSTN cards will vary. We will discuss installation in general terms, which will apply to all Digium PSTN cards. Other manufacturers tend to provide installation scripts with their hardware, which will automate much of this for you.

Downloading and installing DAHDI

The Digium Asterisk Hardware Device Interface, a.k.a. DAHDI (DAW-dee)[73] is the software framework required to enable communication between PSTN cards and Asterisk. Even if you do not have any PSTN hardware, we recommend installing DAHDI since it is a simple, reliable way to get a valid timing source.[74] Complete DAHDI installation instructions can be found in Chapter 3, Installing Asterisk.

Configuring digital circuits

Digital telephony was developed by carriers as a way to reduce the cost of long-distance circuits, as well as improve transmission quality. The entire PSTN backbone has been fully digital for many years now. The essence of a digital circuit is the digitization of the audio, but digital trunks also allow for more complex and reliable signaling. Several standards have been developed and deployed, and for each standard there may be regional differences as well.

Tip

You can use dahdi_hardware and lsdahdi to help you determine what telephony hardware your system contains. You can also use dahdi_genconf modules to build an /etc/asterisk/modules file for you based on the found hardware.

PRI ISDN

Primary Rate Interface ISDN (commonly known as PRI) is a protocol designed to run primarily on a DS1 circuit (a T1 or E1, depending on where you are in the world) between a carrier and a customer. PRI uses one of the DS0 channels as a signaling channel (referred to as the D-channel). A typical PRI circuit is therefore broken down into a group of B-channels (the bearer channels that actually carry the calls), and a D-channel for signaling. Although it is most common to find a PRI circuit being carried across a single physical circuit (such as a T1 or E1), it is possible to have a PRI circuit span multiple DS1s, and even to have multiple D-channels.[75]

While there are many different ways to configure PRI circuits, we are hoping to avoid confusing you with all of the options (many of which are obsolete or at least no longer in common use), and instead provide examples of the more common configurations.

Note

When installing telephony hardware, be sure you update the /etc/dahdi/modules file to enable the appropriate modules for your hardware and then reload DAHDI with the init script (/etc/init.d/dahdi). You can use the dahdi_genconf modules command to generate the modules file for your system as well.

Most PRI circuits in North America will use a T1 with the following characteristics:

  • Line code: B8ZS (bipolar with 8-zeros substitution)

  • Framing: ESF (extended superframe)

You will need to configure two files. The /etc/dahdi/system.conf file should look something like this:

loadzone = us
defaultzone = us

span = 1,1,0,esf,b8zs
bchan = 1-23
echocanceller = mg2,1-23
hardhdlc = 24

And the /etc/asterisk/chan_dahdi.conf file should look like this:

[trunkgroups]

[channels]

usecallerid = yes
hidecallerid = no
callwaiting = yes
usecallingpres = yes
callwaitingcallerid = yes
threewaycalling = yes
transfer = yes
canpark = yes
cancallforward = yes
callreturn = yes
echocancel = yes
echocancelwhenbridged = yes
relaxdtmf = yes
rxgain = 0.0
txgain = 0.0
group = 1
callgroup = 1
pickupgroup = 1
immediate = no

switchtype = national ; commonly referred to as NI2
context = from-pstn
group = 0
echocancel = yes
signalling = pri_cpe
channel => 1-23

Some carriers will use Nortel’s DMS switch, which commonly uses the DMS100 protocol instead of National ISDN 2. In this case you would set the switchtype to DMS100:

switchtype = dms100

Outside of Canada and the US, PRI circuits will be carried on an E1 circuit.

In Europe, an E1 circuit used for PRI will normally have the following characteristics:

  • Line code: CCS

  • Framing: HDB3 (high-density bipolar)

The /etc/dahdi/system.conf file might look something like this:

span = 1,0,0,ccs,hdb3,crc4
bchan = 1-15,17-31
hardhdlc = 16

And the /etc/asterisk/chan_dahdi.conf file should look something like this:

[trunkgroups]

[channels]

usecallerid = yes
hidecallerid = no
callwaiting = yes
usecallingpres = yes
callwaitingcallerid = yes
threewaycalling = yes
transfer = yes
canpark = yes
cancallforward = yes
callreturn = yes
echocancel = yes
echocancelwhenbridged = yes
relaxdtmf = yes
rxgain = 0.0
txgain = 0.0
group = 1
callgroup = 1
pickupgroup = 1
immediate = no

switchtype = qsig
context = pri_incoming
group = 0
signalling = pri_cpe
channel => 1-15,17-31
BRI ISDN

Basic Rate Interface ISDN (commonly known as BRI, or sometimes even just ISDN) was intended to be the smaller sibling to PRI. BRI only provides two 64K B-channels and a 16K D-channel. The use of BRI has been somewhat limited in North America (we don’t recommend using it for any reason), but in some countries in Europe it is widely used and has almost completely replaced analog.

BRI support under Asterisk will be different depending on the BRI card you are installing. The manufacturer of your BRI card will provide specific installation instructions for its hardware.

Note

When installing telephony hardware, be sure you update the /etc/dahdi/modules file to enable the appropriate modules for your hardware and then reload DAHDI with the init script (/etc/init.d/dahdi). You can use the dahdi_genconf modules command to generate the modules file for your system as well.

MFC/R2

The MFC/R2 protocol could be thought of as a precursor to ISDN. It was at first used on analog circuits, but it is now mostly deployed on the same E1 circuits that also carry ISDN-PRI. This protocol is not typically found in Canada, the US, or Western Europe, but it is very popular in some parts of the world (especially Latin America and Asia), mostly because it tends to be a less expensive service offering from the carriers.

There are many different flavors of this protocol, each country having a different regional variant.

The OpenR2 project provides the libopenr2 library, which needs to be installed on your system in order for Asterisk to support your R2 circuits. Before installing libopenr2, however, you need to have DAHDI installed.

The compilation and installation order, therefore, is:

  1. DAHDI

  2. libopenr2

  3. Asterisk

Once OpenR2 has been installed, you can use the r2test application to see a list of variants that are supported:

$ r2test -l
Variant Code        Country                                 
AR                  Argentina                               
BR                  Brazil                                  
CN                  China                                   
CZ                  Czech Republic                          
CO                  Colombia                                
EC                  Ecuador                                 
ITU                 International Telecommunication Union   
MX                  Mexico                                  
PH                  Philippines                             
VE                  Venezuela

For additional information on configuring R2 support in Asterisk, see the configs/chan_dahdi.conf.sample file included in the Asterisk source tree (search for “mfcr2”). Additionally, OpenR2 contains some sample configuration files for connecting Asterisk to networks in various countries. To read information about some of the country variants, search the /doc/asterisk folder and refer to the documents inside the appropriate subdirectory:

$ ls doc/asterisk/
ar  br  ec  mx  ve

As an example, OpenR2 provides a sample configuration for connecting to Telmex or Axtel in Mexico. We’ll step you through this to give you an idea of the process. First, you must configure DAHDI by modifying /etc/dahdi/system.conf as shown here:

loadzone = us
defaultzone = us

span = 1,1,0,cas,hdb3
cas = 1-15:1101
cas = 17-31:1101

span = 2,1,0,cas,hdb3
cas = 32-46:1101
cas = 48-62:1101

Next, you must configure Asterisk by modifying /etc/asterisk/chan_dahdi.conf as follows:

signalling = mfcr2
mfcr2_variant = mx
mfcr2_get_ani_first = no
mfcr2_max_ani = 10
mfcr2_max_dnis = 4
mfcr2_category = national_subscriber
mfcr2_mfback_timeout = -1
mfcr2_metering_pulse_timeout = -1
; this is for debugging purposes
mfcr2_logdir = log
mfcr2_logging = all
; end debugging configuration
channel => 1-15
channel => 17-31

Configuring analog circuits

There are many companies producing PSTN cards for Asterisk. The card will need to have its drivers installed so that Linux can recognize it (DAHDI ships with these drivers for Digium cards). From that point, configuration is handled by the Asterisk module chan_dahdi.

Tip

You can use dahdi_hardware and lsdahdi to determine what telephony hardware your system contains.

Note

When installing telephony hardware, be sure you update the /etc/dahdi/modules file to enable the appropriate modules for your hardware and then reload DAHDI with the init script (/etc/init.d/dahdi). You can use the dahdi_genconf modules command to generate the modules file for your system as well.

In order to configure an FXO card to work with Asterisk, two files are required.

The first is not an Asterisk configuration file, and is thus located in the /etc/dahdi folder on your system.[76] This file, system.conf allows you to define some basic parameters, as well as specify the channels that will be available to your system. Our example assumes a four-port FXO card, but many different combinations are possible, depending on your hardware.

loadzone = us       ; tonezone defines sounds the interface must produce
                    ; (dialtone, busy signal, ringback, etc.)
defaultzone = us    ; define a default tonezone
fxsks = 1-4         ; which channels on the card will have these parameters

Once your card and channels are known to the operating system, you must configure them for Asterisk by means of the file /etc/asterisk/chan_dahdi.conf:

[channels]

;
; To apply other options to these channels, put them before "channel".
;
signalling = fxs_ks  ; in Asterisk, FXO channels use FXS signaling 
                     ; (and yes, FXS channels use FXO signaling)
channel => 1-4       ; apply all the previously defined settings to this channel

In this example, we have told Asterisk that the first four DAHDI channels in the system are FXO ports.

The s extension

If you are connecting to the PSTN using analog channels, we need to explain extension s. When calls enter a context without a specific destination extension (for example, a ringing FXO line from the PSTN), they are passed to the s extension. (The s stands for “start,” as this is where a call will start if no extension information was passed with the call). This extension can also be useful for accepting calls that have been redirected from other parts of the dialplan. For example, if we had a list of DID numbers that were all going to the same place, we might want to point each DID to the s extension, rather than having to code duplicate dialplan logic for each DID.

Since this is exactly what we need for our dialplan, let’s begin to fill in the pieces. We will be performing three actions on the call (answer it, play a sound file, and hang it up), so our s extension will need three priorities. We’ll place the three priorities below [incoming], because we have decided that all incoming calls should start in this context[77]:

[incoming]
exten => s,1,Answer()
   same => n,Playback(tt-weasels)
   same => n,Hangup()

Obviously, you would not normally want to answer a call and then hang up. Typically, an incoming call will either be answered by an automated attendant, or ring directly to a phone (or group of phones).

VoIP

In the world of telecom, VoIP is still a relatively new concept. For the century or so prior to VoIP, the only way to connect your site to the PSTN was through the use of circuits provided for that purpose by your local telephone company. VoIP now allows for connections between endpoints without the PSTN having to be involved at all (although in most VoIP scenarios, there will still be a PSTN component at some point, especially if there is a traditional E.164 phone number involved).

PSTN Termination

Until VoIP totally replaces the PSTN, there will be a need to connect calls from VoIP networks to the public telephone network. This process is referred to as termination. What it means is that at some point a gateway connected to the PSTN needs to accept calls from the VoIP network and connect them to the PSTN network. From the perspective of the PSTN, the call will appear to have originated at the termination point.

Asterisk can be used as a PSTN termination point. In fact, given that Asterisk handles protocol conversion with ease, this can be an excellent use for an Asterisk system.

In order to provide termination, an Asterisk box will need to be able to handle all of the protocols you wish to connect to the PSTN. In general, this means that your Asterisk box will need a PRI circuit to handle the PSTN connection, and SIP channels to handle the calls coming from the VoIP network. The underlying principle is the same regardless of whether you’re running a small system providing PSTN trunks to an office full of VoIP telephones, or a complex network of gateway machines deployed in strategic locations, offering termination to thousands of subscribers.

Calls from the VoIP network will arrive in the dialplan in whatever context you assigned to the incoming SIP channels, and the dialplan will relay the calls out through the PSTN interface. At its very simplest, a portion of a dialplan that supports termination could look like this:

[from-voip-network]
exten => _X.,1,Verbose(2, Call from VoIP network to ${EXTEN})
   same => n,Dial(DAHDI/g0/${EXTEN})

In reality, though, you will often have to handle a more complex routing plan that takes into consideration things like geography, corporate policy, cost, available resources, and so forth.

Warning

Given that most PSTN circuits will allow you to dial any number, anywhere in the world, and given that you will be expected to pay for all incurred charges, we cannot stress enough the importance of security on any gateway machine that is providing PSTN termination. Criminals put a lot of effort into cracking phone systems (especially poorly secured Asterisk systems), and if you do not pay careful attention to all aspects of security, you will be the victim of toll fraud. It’s only a matter of time.

Do not allow any unsecured VoIP connections into any context that contains PSTN termination.

PSTN Origination

Obviously, if you want to pass calls from your VoIP network to the PSTN, you might also want to be able to accept calls from the PSTN into your VoIP network. The process of doing this is commonly referred to as origination. This simply means that the call originated in the PSTN.

In order to provide origination, a phone number is required. You will therefore need to obtain a circuit from your local phone company, which you will connect to your Asterisk system. Depending on where you are in the world, there are several different types of circuits that could provide this functionality, from a basic analog POTS line to a carrier-grade SS7 circuit.

Note

Phone numbers as used for the purpose of origination are commonly called direct inward dialing numbers (DIDs). This is not strictly the case in all situations (for example, the phone number on a traditional analog line would not be considered a DID), but the term is useful enough that it has caught on. Historically, a DID referred to a phone number associated with a trunk connected to customer premise equipment (CPE).

Since phone numbers are controlled by the traditional telecom industry, you will need to obtain the number either from a carrier directly, or from one of the many companies that purchase numbers in bulk and resell them in smaller blocks. If you obtain a circuit such as a PRI circuit, you will normally be able to order DID numbers to be delivered with that circuit.

In order to accept a call from a circuit you are using for origination, you will normally need to handle the passing of the phone number that was called. This is because PSTN trunks can typically handle more than one phone number, and thus the carrier needs to identify which number was called so that your Asterisk system will know how to route the call. The number that was dialed is commonly referred to as the Dialed Number Identification Service (DNIS) number. The DNIS number and the DID do not have to match,[78] but typically they will. If you are ordering a circuit from the carrier, you will want to ask that they send the DNIS (if they don’t understand that, you may want to consider another carrier).

In the dialplan, you associate the incoming circuit with a context that will know how to handle the incoming digits. As an example, it could look something like this:

[from-pstn] 
; This is the context that would be listed in the config file
; for the circuit (i.e. chan_dahdi.conf)

exten => _X.,1,Verbose(2,Incoming call to ${EXTEN})
    same => n,Goto(number-mapping,${EXTEN},1)

[number-mapping] 
; This context is not strictly required, but will make it easier
; to keep track of your DIDs in a single location in your dialplan. 
; From here you can pass the call to another part of the dialplan
; where the actual dialplan work will take place.

exten => 4165551234,1,Dial(SIP/0000FFFF0001)
exten => 4165554321,1,Goto(autoattendant-context,start,1)
exten => 4165559876,1,VoiceMailMain() ; a handy back door for listening
                                      ; to voice messages

exten => i,1,Verbose(2,Incoming call to invalid number)

In the number-mapping context you explicitly list all of the DIDs that you expect to handle, plus an invalid handler for any DIDs that are not listed (you could send invalid numbers to reception, or to an automated attendant, or to some context that plays an invalid prompt).

VoIP to VoIP

Eventually, the need for the PSTN will likely vanish, and most voice communications will take place over network connections.

The original thinking behind the SIP protocol was that it was to be a peer-to-peer protocol. Technically, this is still the case. What has happened, however, is that things have gotten a bit more complicated. Issues such as security, privacy, corporate policies, integration, centralization, and so forth have made things a bit more involved than simply putting a URI into a SIP phone and having a SIP phone somewhere else ring in response.

The SIP protocol has become bloated and complex. Implementing SIP-based systems and networks has arguably become even more complicated than implementing traditional phone PBXs and networks.[79]

We are not going to get into the complexities of designing and implementing VoIP networks in this book, but we will discuss some of the ways you can configure Asterisk to support VoIP connectivity to other VoIP systems.

Configuring VoIP Trunks

In Asterisk, there is no need to explicitly install your VoIP modules (unless for some reason you did not compile Asterisk with the required modules). There are several VoIP protocols that you can choose to use with Asterisk, but we will focus on the two most popular: SIP and IAX.

Configuring SIP trunks between Asterisk systems

SIP is far and away the most popular of the VoIP protocols—so much so that many people would consider other VoIP protocols to be obsolete (they are not, but it cannot be denied that SIP has dominated VoIP for several years now).

The SIP protocol is peer-to-peer and does not really have a formal trunk specification. This means that whether you are connecting a single phone to your server or connecting two servers together, the SIP connections will be similar.

Connecting two Asterisk systems together with SIP

The need to be able to connect two Asterisk systems together to allow calls to be sent between them is a fairly common requirement. Perhaps you have a company with two physical locations and want to have a PBX at each location, or maybe you’re the administrator of the company PBX and you like Asterisk so much that you would also like to install it at home. This section provides a quick guide on configuring two Asterisk servers to be able to pass calls to each other over SIP. In our example, we will creatively refer to the two servers as serverA and serverB.

The first file that must be modified is /etc/asterisk/sip.conf. This is the main configuration file for setting up SIP accounts. First, this entry must be added to sip.conf on serverA. It defines a SIP peer for the other server:

[serverB]

;
; Specify the SIP account type as 'peer'.  This means that incoming
; calls will be matched on IP address and port number.  So, when Asterisk
; receives a call from 192.168.1.102 and the standard SIP port of 5060,
; it will match this entry in sip.conf.  It will then request authentication
; and expect the password to match the 'secret' specified here.
;
type = peer
;
; This is the IP address for the remote box (serverB). This option can also
; be provided a hostname.
;
host = 192.168.1.102
;
; When we send calls to this SIP peer and must provide authentication,
; we use 'serverA' as our username.
;
username = serverA
;
; This is the shared secret with serverB.  It will be used as the password
; when either receiving a call from serverB, or sending a call to serverB.
;
secret = apples
;
; When receiving a call from serverB, match it against extensions
; in the 'incoming' context of extensions.conf.
;
context = incoming
;
; Start by clearing out the list of allowed codecs.
;
disallow = all
;
; Only allow the ulaw codec.
;
allow = ulaw

Note

Be sure to change the host option to match the appropriate IP address for your own setup.

Now put the following entry in /etc/asterisk/sip.conf on serverB. It is nearly identical to the contents of the entry we put on serverA, but the name of the peer and the IP address were changed:

[serverA]

type = peer
host = 192.168.1.101
username = serverB
secret = apples
context = incoming
disallow = all
allow = ulaw

At this point you should be able to verify that the configuration has been successfully loaded into Asterisk using some CLI commands. The first command to try is sip show peers. As the name implies, it will show all SIP peers that have been configured:

*CLI> sip show peers
Name/username       Host             Dyn Forcerport ACL Port     Status     
serverB/serverA     192.168.1.101                       5060     Unmonitored 
1 sip peers [Monitored: 0 online, 0 offline Unmonitored: 1 online, 0 offline]

Note

You can also try sip show peer serverB. That command will show much more detail.

The last step in setting up SIP calls between two Asterisk servers is to modify the dialplan in /etc/asterisk/extensions.conf. For example, if you wanted any calls made on serverA to extensions 6000 through 6999 to be sent over to serverB, you would use this line in the dialplan:

exten => _6XXX,1,Dial(SIP/${EXTEN}@serverB)
Connecting an Asterisk system to a SIP provider

When you sign up for a SIP provider, you may have service for sending and/or receiving phone calls. The configuration will differ slightly depending on your usage of the SIP provider. Further, the configuration will differ between each provider. Ideally, the SIP provider that you sign up with will provide Asterisk configuration examples to help get you connected as quickly as possible. In case they do not, though, we will attempt to give you a common setup that will help you get started.

If you will be receiving calls from your service provider, the service provider will most likely require your server to register with one of its servers. To do so, you must add a registration line to the [general] section of /etc/asterisk/sip.conf:

[general]
...
register => username:password@your.provider.tld
...

Next, you will need to create a peer entry in sip.conf for your service provider. Here is a sample peer entry:

[myprovider]

type = peer
host = your.provider.tld
username = username
secret = password
; Most providers won't authenticate when they send calls to you,
; so you need this line to just accept their calls.
insecure = invite
dtmfmode = rfc2833
disallow = all
allow = ulaw

Now that the account has been defined, you must add some extensions in the dialplan to allow you to send calls to your service provider:

exten => _1NXXNXXXXXX,1,Dial(SIP/${EXTEN}@myprovider)
Encrypting SIP calls

Asterisk supports TLS for encryption of the SIP signaling and SRTP for encryption of the media streams of a phone call. In this section we will set up calls using SIP TLS and SRTP between two Asterisk severs. The first step is to ensure the proper dependencies have been installed. Ensure that you have both OpenSSL and LibSRTP installed. If either one of these was not installed, reinstall Asterisk after installing these dependencies to ensure that support for TLS and SRTP are included. Once complete, make sure that the res_srtp module was compiled and installed. To install OpenSSL, the package is openssl-devel on CentOS and libssl-dev on Ubuntu. To install LibSRTP, the package is libsrtp-devel on CentOS and libsrtp0-dev on Ubuntu.

Next we will configure SIP TLS. You must enable TLS using the global tlsenable option in the [general] section of /etc/asterisk/sip.conf on both servers. You can optionally specify an address to bind to if you would like to limit listening for TLS connections to a single IP address on the system. In this example, we have the IPv6 wildcard address specified to allow TLS connections on all IPv4 and IPv6 addresses on the system:

[general]

tlsenable = yes
tlsbindaddr = ::

The next step is to get certificates in place. For the purposes of demonstrating the configuration and functionality, we are going to generate self-signed certificates using a helper script distributed with Asterisk. If you were setting this up in a production environment, you might not want to use self-signed certificates. However, if you do, there are a number of applications out there that help make it easier to manage your own certificate authority (CA), such as TinyCA.

The script that we are going to use is ast_tls_cert, which is in the contrib/scripts/ directory of the Asterisk source tree. We need to generate a CA certificate and two server certificates. The first invocation of ast_tls_cert will generate the CA cert and the server cert for serverA. The second invocation of ast_tls_cert will generate the server cert for serverB:

$ cd contrib/scripts
$ mkdir certs
$ ./ast_tls_cert -d certs -C serverA -o serverA
$ ./ast_tls_cert -d certs -C serverB -o serverB -c certs/ca.crt -k certs/ca.key
$ ls certs
ca.cfg  ca.crt  ca.key  serverA.crt  serverA.csr  serverA.key  serverA.pem
serverB.crt  serverB.csr  serverB.key  serverB.pem  tmp.cfg

Now that the certificates have been created, they need to be moved to the appropriate locations on serverA and serverB. We will use the /var/lib/asterisk/keys/ directory to hold the certificates. Move the following files to serverA:

  • ca.crt

  • serverA.pem

And move these files to serverB:

  • ca.crt

  • serverB.pem

With the certificates in place, we can complete the Asterisk configuration. We need to point Asterisk to the server certificate that we just created. Since we’re using self-signed certificates, we also need to point to the CA certificate. In the [general] section of /etc/asterisk/sip.conf on serverA, add these options:

[general]

tlscertfile = /var/lib/asterisk/keys/serverA.pem
tlscafile = /var/lib/asterisk/keys/ca.crt

Make the same changes to sip.conf on serverB:

[general]

tlscertfile = /var/lib/asterisk/keys/serverB.pem
tlscafile = /var/lib/asterisk/keys/ca.crt

Warning

When you create the server certificates, the Common Name field must match the hostname of the server. If you use the ast_tls_cert script, this is the value given to the -C option. If there is a problem verifying the server certificate when you make a call, you may need to fix the Common Name field. Alternatively, for the sake of testing you can set the tlsdontverifyserver option to yes in the [general] section of /etc/asterisk/sip.conf, and Asterisk will allow the call to proceed even if it fails verification of the server certificate.

In the section called “Connecting two Asterisk systems together with SIP”, we created the configuration necessary to pass calls between serverA and serverB. We are now going to modify that configuration so that Asterisk knows that the calls between the two servers should be encrypted. The only change required is to add the transport = tls option to the peer entry for the other server.

On serverA:

[serverB]

type = peer
host = 192.168.1.102
username = serverA
secret = apples
context = incoming                                                           
disallow = all                    
allow = ulaw
transport = tls                   

On serverB:

[serverA]

type = peer
host = 192.168.1.101
username = serverB
secret = apples
context = incoming                                                           
disallow = all                    
allow = ulaw
transport = tls   

Now when you make a call using Dial(SIP/serverA) or Dial(SIP/serverB), the SIP signaling will be encrypted. You can modify the dialplan to force outgoing calls to have encrypted signaling by setting the CHANNEL(secure_bridge_signaling) function to 1:

[default]

exten => 1234,1,Set(CHANNEL(secure_bridge_signaling)=1)
    same => n,Dial(SIP/1234@serverB)

On the side receiving the call, you can check whether the signaling on an incoming call is encrypted using the CHANNEL(secure_signaling) dialplan function. Consider the following example dialplan:

[incoming]

exten => _X.,1,Answer()
    same => n,GotoIf($["${CHANNEL(secure_signaling)}" = "1"]?secure:insecure)
    same => n(secure),NoOp(Signaling is encrypted.)
    same => n,Hangup()
    same => n(insecure),NoOp(Signaling is not encrypted.)
    same => n,Hangup()

When a call is sent from serverA to serverB using this configuration, you can see from the output on the Asterisk console that the dialplan determines that the signaling of the incoming call is encrypted:

    -- Executing [1234@incoming:1] Answer("SIP/serverA-00000000", "") in new stack
    -- Executing [1234@incoming:2] GotoIf("SIP/serverA-00000000", 
       "1?secure:insecure") in new stack
    -- Goto (incoming,1234,3)
    -- Executing [1234@incoming:3] NoOp("SIP/serverA-00000000", 
       "Signaling is encrypted.") in new stack
    -- Executing [1234@incoming:4] Hangup("SIP/serverA-00000000", "") in new stack

Now that SIP TLS has been set up for calls between serverA and serverB, we will set up SRTP so that the media streams associated with the call are encrypted as well. Luckily, it is quite easy to configure, compared to what was required to get SIP TLS working. First, make sure that you have the res_srtp module loaded in Asterisk:

*CLI> module show like res_srtp.so 
Module                         Description                              Use Count 
res_srtp.so                    Secure RTP (SRTP)                        0         
1 modules loaded

To enable SRTP, set the CHANNEL(secure_bridge_media) function to 1:

[default]

exten => 1234,1,Set(CHANNEL(secure_bridge_signaling)=1)
    same => n,Set(CHANNEL(secure_bridge_media)=1)
    same => n,Dial(SIP/1234@serverB)

This indicates that encrypted media is required for an outbound call. When the call is sent out via SIP, Asterisk will require that SRTP be used, or the call will fail.

With all of these tools in place, you can ensure that calls between two Asterisk servers are fully encrypted. The same techniques should be applied for encrypting calls between Asterisk and a SIP phone.

The dialplan functions provide a mechanism for verifying the encryption status of an incoming call and forcing encryption on an outgoing call. However, keep in mind that these tools only provide the means for controlling encryption for one hop of the call path. If the call goes through multiple servers, these tools do not guarantee that the call is encrypted through the entire call path. It is important to carefully consider what your requirements are for secure calls and take all of the necessary steps to ensure that those requirements are respected throughout the entire call path. Security is complicated, hard work.

Configuring IAX trunks between Asterisk systems

The Inter-Asterisk eXchange protocol, version 2 (most commonly known as IAX[80]) is Asterisk’s own VoIP protocol. It is different from SIP in that the signaling and media are carried in the same connection. This difference is one of the advantages of the IAX protocol, as it makes getting IAX to work across NAT connections much simpler.

IAX trunking

One of the more unique features of the IAX protocol is IAX trunking. Trunking an IAX connection could be useful on any network link that will often be carrying multiple simultaneous VoIP calls between two systems. By encapsulating multiple audio streams in one packet, IAX trunking cuts down on the overhead on the data connection, which can save bandwidth on a heavily used network link.

IAX encryption

The principal advantage of IAX encryption is that it requires one simple change to the /etc/asterisk/iax.conf file:

[general]
encryption = yes

For extra protection, you can set the following option to ensure that no IAX connection can happen without encryption:

forceencryption = yes

Both of these options can be specified in the [general] section, as well as in peer/user/friend sections in iax.conf.

Emergency Dialing

In North America, people are used to being able to dial 911 in order to reach emergency services. Outside of North America, well-known emergency numbers are 112 and 999. If you make your Asterisk system available to people, you are obligated (in many cases regulated) to ensure that calls can be made to emergency services from any telephone connected to the system (even those phones that otherwise are restricted from making calls).

One of the essential pieces of information the emergency response organization needs to know is where the emergency is (i.e., where to send the fire trucks). In a traditional PSTN trunk this information is already known by the carrier and is subsequently passed along to the Public Safety Answering Point (PSAP). With VoIP circuits things can get a bit more complicated, by virtue of the fact that VoIP circuits are not physically tied to any geographical location.

You need to ensure that your system will properly handle 911 calls from any phone connected to it, and you need to communicate what is available to your users. As an example, if you allow users to register to the system from softphones on their laptops, what happens if they are in a hotel room in another country, and they dial 911?[81]

The dialplan for handling emergency calls does not need to be complicated. In fact, it’s far better to keep it simple. People are often tempted to implement all sorts of fancy functionality in the emergency services portions of their dialplans, but if a bug in one of your fancy features causes an emergency call to fail, lives could be at risk. This is no place for playing around. The [emergency-services] section of your dialplan might look something like this:

[emergency-services]
exten => 911,1,Goto(dialpsap,1)
exten => 9911,1,Goto(dialpsap,1) ; some people will dial '9' because 
                                 ; they're used to doing that from the PBX
exten => 999,1,Goto(dialpsap,1)
exten => 112,1,Goto(dialpsap,1)

exten => dialpsap,1,Verbose(1,Call initiated to PSAP!)
    same => n,Dial(${LOCAL}/911) ; REPLACE 911 HERE WITH WHATEVER 
                                 ; IS APPROPRIATE TO YOUR AREA

[internal]
include => emergency-services   ; you have to have this in any context 
                                ; that has users in it

In contexts where you know the users are not on-site (for example, remote users with their laptops), something like this might be best instead:

[no-emergency-services]
exten => 911,1,Goto(nopsap,1)
exten => 9911,1,Goto(nopsap,1) ; for people who dial '9' before external calls
exten => 999,1,Goto(nopsap,1)
exten => 112,1,Goto(nopsap,1)

exten => nopsap,1,Verbose(1,Call initiated to PSAP!) 
    same => n,Playback(no-emerg-service) ; you'll need to record this prompt

[remote-users]
include => no-emergency-services

In North America, regulations have obligated many VoIP carriers to offer what is popularly known as E911.[82] When you sign up for their services, they will require address information for each DID that you wish to associate with outgoing calls. This address information will then be sent to the PSAP appropriate to that address, and your emergency calls should be handled the same as they would be if they were dialed on a traditional PSTN circuit.

Handling emergency calls does not have to be complicated (in fact, it is best to keep this as simple as possible). The bottom line is that you need to make sure that the phone system you create allows emergency calls.

Conclusion

Eventually, we believe that the PSTN will disappear entirely. Before that happens, however, a distributed mechanism that is widely used and trusted will be needed to allow organizations and individuals to publish addressing information so that they can be found. We’ll explore some of the ways this is already possible in Chapter 12, Internet Call Routing.



[68] But do not collect $200.

[69] In a key system, each line has a corresponding button on each telephone, and lines are accessed by pressing the desired line key.

[70] You can name these anything you wish. The words “local” and “toll” do not have any built-in meaning to the Asterisk dialplan.

[71] For more information on pattern matches, see Chapter 6, Dialplan Basics.

[72] You would use the exact same card if you wanted to connect a traditional home telephone line to your Asterisk system.

[73] Don’t ask.

[74] There are other ways of getting a timing source, and if you want a really tight system it is possible to run Asterisk without DAHDI, but it’s not something we’re going to cover here.

[75] Sometimes circuits are referenced by the number of B- and D-channels they contain, so a single T1 running the PRI protocol in North America might be referred to as 23B+D, and a dual T1 circuit with a backup D-channel would be a 46B+2D. We’ve even seen PRI referenced as nB+nD, although this can get a little bit pedantic.

[76] In theory, these cards could be used for any software that supports DAHDI; therefore, the basic card configuration is not a part of Asterisk.

[77] There is nothing special about any context name. We could have named this context [stuff_that_comes_in], and as long as that was the context assigned in the channel definition in sip.conf, iax.conf, chan_dahdi.conf, et al., the channel would enter the dialplan in that context. Having said that, it is strongly recommended that you give your contexts names that help you to understand their purpose. Some good context names might include [incoming], [local_calls], [long_distance], [sip_telephones], [user_services], [experimental], [remote_locations], and so forth. Always remember that a context determines how a channel enters the dialplan, so name accordingly.

[78] In traditional PBXs, the purpose of DIDs was to allow connection directly to an extension in the office. Many PBXs could not support concepts such as number translation or flexible digit lengths, and thus the carrier had to pass the extension number as the DID digits, rather than the number that was dialed (the DNIS number). For example, the phone number 416-555-1234 might have been mapped to extension 100, and thus the carrier would have sent the digits 100 to the PBX instead of the DNIS of 4165551234. If you ever replace an old PBX with an Asterisk system, you may find this translation in place, and you’ll need to obtain a list of mappings between the numbers that the caller dials and the numbers that are sent to the PBX. It is also common to see the carrier only pass the last four digits of the DNIS number, which the PBX then translates into an internal number.

[79] There are many proprietary PBX systems in the market that have a basic configuration that will work right out of the box. Asterisk deployments are far more flexible, but seldom as simple.

[80] Pronounced “eeks.”

[81] Don’t assume this can’t happen. When somebody calls 911 it’s because they have an emergency, and it’s not safe to assume that they’re going to be in a rational state of mind.

[82] It’s not actually the carrier that’s offering this; rather it’s a capability of the PSAP. E911 is also used on PSTN trunks, but since that happens without any involvement on your part (the PSTN carriers handle the paperwork for you), you are generally not aware that you have E911 on your local lines.

Chapter 8. Voicemail

Just leave a message, maybe I’ll call.

Joe Walsh

Before email and instant messaging became ubiquitous, voicemail was a popular method of electronic messaging. Even though most people prefer text-based messaging systems, voicemail remains an essential component of any PBX.

Comedian Mail

One of the most popular (or, arguably, unpopular) features of any modern telephone system is voicemail. Asterisk has a reasonably flexible voicemail system named Comedian Mail.[83] Some of the features of Asterisk’s voicemail system include:

  • Unlimited password-protected voicemail boxes, each containing mailbox folders for organizing voicemail

  • Different greetings for busy and unavailable states

  • Default and custom greetings

  • The ability to associate phones with more than one mailbox and mailboxes with more than one phone

  • Email notification of voicemail, with the voicemail optionally attached as a sound file[84]

  • Voicemail forwarding and broadcasts

  • Message-waiting indicator (flashing light or stuttered dialtone) on many types of phones

  • Company directory of employees, based on voicemail boxes

And that’s just the tip of the iceberg!

The default version of the /etc/asterisk/voicemail.conf file requires a few tweaks in order to provide a configuration that will be suitable to most situations.

We’ll begin by going through the various options you can define in voicemail.conf, and then we’ll provide a sample configuration file with the settings we recommend for most deployments.

The voicemail.conf file contains several sections where parameters can be defined. The following sections detail all the options that are available.

The [general] Section

The first section, [general], allows you to define global settings for your voicemail system. The available options are listed in Table 8.1, “[general] section options for voicemail.conf”.

Table 8.1. [general] section options for voicemail.conf

OptionValue/ExampleNotes
format

wav49|gsm|wav

For each format listed, Asterisk will create a separate recording in that format whenever a message is left. The benefit of this is that some transcoding steps may be saved if the stored format is the same as the codec used on the channel. We like wav because it is the highest quality, and wav49 because it is nicely compressed and easy to email. We don’t like gsm due to it’s scratchy sound, but it enjoys some popularity.[a]
serveremailuser@domainWhen an email is sent from Asterisk, this is the email address that it will appear to come from.[b]
attachyes,noIf an email address is specified for a mailbox, this determines whether the messages is attached to the email (if not, a simple message notification is sent).
maxmsg9999By default Asterisk will only allow a maximum of 100 messages to be stored per user. For users who delete messages, this is no problem. For people who like to save their messages, this space can get eaten up quickly. With the size of hard drives these days, you could easily store thousands of messages for each user, so our current thinking is to set this to the maximum and let the users manage things from there.
maxsecs0This type of setting was useful back in the days when a large voicemail system might have only 40 MB[c] of storage: it was necessary to limit the system because it was easy to fill up the hard drive. This setting can be annoying to callers (although it does force them to get to the point, so some people like it). Nowadays, with terabyte drives becoming common, there is no reason not to set this to a high value. Two considerations are: 1) if a channel gets hung in a mailbox, it’s good to set some sort of value so it doesn’t stay there for days, but 2) if a user wants to use her mailbox to record notes to herself, she won’t appreciate it if you cut her off after three minutes. A setting somewhere between 600 seconds (10 minutes) and 3600 seconds (1 hour) will probably be about right.
minsecs4Many folks will hang up instead of leaving a message when they call somebody and get voicemail. Sometimes this hangup happens after recording has started, so the mailbox owner gets an annoying two-second message of somebody hanging up. This setting ensures that Asterisk will ignore messages that are shorter than the configured minimum length. You should take care not to set this to a value that is too high, though, because then a message like “Hey it’s me give me a call” (which can be said in less than one second) will get lost, and you’ll get complaints of messages disappearing. Three seconds seems to be about right. To discourage people from leaving ultra-short messages that might be discarded, you can request callers to identify themselves and leave some information about why they called.
maxgreet1800You can define the maximum greeting length if you want. Again, since storage is not a problem and setting this too low will annoy your more verbose users, we suggest setting this to a high value and letting your users figure it out an appropriate length for themselves.
skipms3000When listening to messages, users can skip ahead or backwards by pressing (by default) * and #. This setting indicates the length of the jump (in milliseconds).
maxsilence5This setting defines the maximum time for which the caller can remain silent before the recording is stopped. We like to set this setting to one second longer than minsecs (if you set it equal to or greater than minsecs, you will get a warning).
silencethreshold128You can fine-tune the silence sensitivity of Asterisk to better define what qualifies as silence. In practice, this is seldom a good idea, since you cannot control the volumes of all the calls you’ll be getting from different places. It’s best to leave this at the default.
maxlogins3This little security feature is intended to make brute-force attacks on your mailbox passwords more time-consuming. If a bad password is received this many times, voicemail will hang up and you’ll have to call back in to try again. Note that this will not lock up the mailbox. Patient snoopers can continue to try to log into your mailbox as many times as they like, they’ll just have to call back every third attempt. If you have a lot of ham-fingered users, you can set this to something like 5.
moveheardyesThis setting will move listened-to messages to the Old folder. We recommend leaving this at the default.
forward _ urgent _ autonoSetting this to yes will preserve the original urgency setting of any messages the user receives and then forwards on. If you leave it at no, users can set the urgency level themselves on messages that they forward.
userscontextdefaultIf you use the users.conf file (we don’t), you can define here the context where entries are registered.
externnotify/path/to/scriptIf you wish to run an external app whenever a message is left, you can define it here.
smdienablenoIf you are using Asterisk as a voicemail server on a PBX that supports SMDI, you can enable it here.
smdiport/dev/ttyS0Here is where you would define the SMDI port that messages between Asterisk and the external PBX would pass across.
externpass/path/to/scriptAny time the password on a mailbox is changed, the script you define here will be notified of the context, mailbox, and new password. The script will then be responsible for updating voicemail.conf (the Asterisk voicemail app will not update the password if this parameter is defined).
externpassnotify/path/to/scriptAny time the password on a mailbox is changed, the script you define here will be notified of the context, mailbox, and new password. Asterisk will handle updating the password in voicemail.conf. If you have defined externpass, this option will be ignored.
externpasscheck/usr/local/bin/voicemailpwcheck.pySee the sidebar following this table for a description of this option.
directoryintrodir-introThe Directory() dialplan application uses the voicemail.conf file to search by name from an auto attendant. There is a default prompt that plays, called dir-intro. If you want, you can specify a different file to play instead.
charsetISO-8859-1If you need a character set other than ISO-8859-1 (a.k.a Latin 1) to be supported, you can specify it here.
adsifdn0000000FUse this option to configure the Feature Descriptor Number.[d]
adsisec9BDBF7ACUse this option to configure the security lock code.
adsiver1This specifies the ADSI voicemail application version number.
pbxskipyesIf you do not want emails from your voicemail to have the string [PBX] added to the subject, you can set this to yes.
fromstringThe Asterisk PBXYou can use this setting to configure the From: name that will appear in emails from your PBX.
usedirectoryyesThis option allows users composing messages from their mailboxes to take advantage of the Directory.
odbcstorage <item from res_odbc.conf> If you want to store voice messages in a database, you can do that using the Asterisk res_odbc connector. Here, you would set the name of the item in the res_odbc file. For details, see Chapter 22, Clustering.
odbctable <table name> This setting specifies the table name in the database that the odbcstorage setting refers to. For details, see Chapter 22, Clustering.
emailsubject[PBX]: New message ${VM_MSGNUM} in mailbox ${VM_MAILBOX}When Asterisk sends an email, you can use this setting to define what the Subject: line of the email will look like. See the voicemail.conf.sample file for more details.
emailbodyDear ${VM_NAME}:\n\n\tjust wanted to let you know you were just left a ${VM_DUR} long message (number ${VM_MSGNUM})\nin mailbox ${VM_MAILBOX u might\nwant to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n When Asterisk sends an email, you can use this setting to define what the body of the email will look like. See the voicemail.conf.sample file for more details.
pagerfromstringThe Asterisk PBXWe don’t actually know anybody who uses pagers anymore (nor can we recall having seen one in many years), but if you have one of these historical oddities and you want to customize what Asterisk sends with its pager notification, presumably you can do that with this. A very practical usage of this feature for short message voicemail notifications is to send a message to an email to SMS gateway.
pagersubjectNew VMAs above.
pagerbodyNew ${VM_DUR} long msg in box ${VM_MAILBOX}\nfrom ${VM_CALLERID}, on ${VM_DATE}The formatting for this uses the same rules as emailbody.
emaildateformat%A, %d %B %Y at %H:%M:%SThis option allows you to specify the date format in emails. Uses the same rules as the C function STRFTIME.
pagerdateformat%A, %d %B %Y at %H:%M:%SThis option allows you to specify the date format in pager. Uses the same rules as the C function STRFTIME.
mailcmd/usr/sbin/sendmail -tIf you want to override the default operating system application for sending mail, you can specify it here.
pollmailboxesno, yesIf the contents of mailboxes are changed by anything other than app_voicemail (such as external applications or another Asterisk system), setting this to yes will cause app_voicemail to poll all the mailboxes for changes, which will trigger proper message waiting indication (MWI) updates.
pollfreq30Used in concert with pollmailboxes, this option specifies the number of seconds to wait between mailbox polls.
imapgreetingsno, yesThis enables/disables remote storage of greetings in the IMAP folder. For more details, see Chapter 18, External Services.
greetingsfolderINBOXIf you’ve enabled imapgreetings, this parameter allows you to define the folder your greetings will be stored in (defaults to INBOX).
imapparentfolderINBOXIMAP servers can handle parent folders in different ways. This field allows you to specify the parent folder for your mailboxes. For more details, see Chapter 7, Outside Connectivity.

[a] The separator that is used for each format option must be the pipe (|) character.

[b] Sending email from Asterisk can require some careful configuration, because many spam filters will find Asterisk messages suspicious and will simply ignore them. We talk more about how to set email for Asterisk in Chapter 18, External Services.

[c] Yes, you read that correctly: megabytes.

[d] The Analog Display Services Interface is a standard that allows for more complex feature interactions through the use of the phone display and menus. With the advent of VoIP telephones, ADSI’s popularity has decreased in recent years.


Part of the [general] section is an area that is referred to as advanced options. These options (listed in Table 8.2, “Advanced options for voicemail.conf”) are defined in the same way as the other options in the [general] section, but they can also be defined on a per-mailbox basis, overriding whatever is defined under [general] for that particular setting.

Table 8.2. Advanced options for voicemail.conf

OptionValue/ExampleNotes
tzeastern, european, etc.Specifies the zonemessages name, as defined in the [zonemessages] section, discussed in the next section.
localede_DE.utf8, es_US.utf8, etc.Used to define how Asterisk generates date/time strings in different locales. To determine the locales that are valid on your Linux system, type locale -a at the shell.
attachyes, noIf an email address is specified for a mailbox, this determines whether the messages are attached to the email notifications (otherwise, a simple message notification is sent).
attachfmtwav49, wav, etc.If attach is enabled and messages are stored in different formats, this defines which format is sent with the email notifications. Often wav49 is a good choice, as it uses a better compression algorithm and thus will use less bandwidth.
saycidyes, noThis command will state the caller ID of the person who left the message.
cidinternalcontexts<context>, <another context>Any dialplan contexts listed here will be searched in an attempt to locate the mailbox context, so that the name associated with the mailbox number can be spoken. The voicemail box number needs to match the extension number that the call came from, and the voicemail context needs to match the dialplan context.[a]
saydurationyes, noThis command will state the length of the message.
saydurationm2Use this to specify the minimum duration of a message to qualify for its length being played back. For example, if you set this to 2, any message less than 2 minutes in length will not have its length stated.
dialout <context> If allowed, users can dial out from their mailboxes. This is considered a very dangerous feature in a phone system (mainly because many voicemail users like to use 1234 as their password), and is therefore not recommended. If you insist on allowing this, make sure you have a second level of password in the dialplan where another password is specified. Even so, this is not a safe practice.
sendvoicemailyes, noThis allows users to compose messages to other users from within their mailboxes.
searchcontextsyes, noThis allows voicemail applications in the dialplan to not have to specify the voicemail context, since all contexts will be searched. This is not recommended.
callback <context> This specifies which dialplan context to use to call back to the sender of a message. The specified context will need to be able to handle dialing of numbers in the format in which they are received (for example, the country code may not be received with the caller ID, but might be required for the outgoing call).
exitcontext <context> There are options that allow the callers to exit the voicemail system when they are in the process of leaving a message (for example, pressing 0 to get an operator). By default, the context the caller came from will be used as the exit context. If desired, this setting will define a different context for callers exiting the voicemail system.
reviewyes, noThis should almost always be set to yes (even though it defaults to no). People get upset if your voicemail system does not allow them to review their messages prior to delivering them.
operatoryes, noBest practice dictates that you should allow your callers to “zero out” from a mailbox, should they not wish to leave a message. Note that an o extension (not “zero,” “oh”) is required in the exitcontext in order to handle these calls.
envelopeno, yesYou can have voicemail play back the details of the message before it plays the actual message. Since this information can also be accessed by pressing 5, we generally set this to no.
deleteno, yesAfter an email message notification is sent (which could include the message itself), the message will be deleted. This option is risky, because even though a message was emailed, it is no guarantee that it was received (spam filters seem to love to delete Asterisk voicemail messages). Point being: on a new system, leave this at no until you are certain that no messages are being lost due to spam filters.
volgain0.0This setting allows you to increase the volume of received messages. Volume used to be a problem in older releases of Asterisk, but has not been an issue for many years. We recommend leaving this at the default. The sox utility is required for this to work.
nextaftercmdyes, noThis handy little setting will save you some time, as it takes you directly to the next message once you’ve finished dealing with the current message.
forcenameyes, noThis strange little setting will check if the mailbox password is the same as the mailbox number. If it is, it will force the user to change his voicemail password and record his name.
forcegreetingsyes, noAs above, but for greetings.
hidefromdirno, yesIf you wish, you can hide specific mailboxes from the Directory() application using this setting.
tempgreetwarnyes, noSetting this to yes will warn the mailbox owner that she has a temporary greeting set. This can be a useful reminder when people return from trips or vacations.
passwordlocationspooldirIf you want, you can have mailbox passwords stored in the spool folder for each mailbox.[b]
messagewrapno, yesIf this is set to yes, when the user has listened to the last message, pressing next (6) will take him to the first message. Also, pressing previous (4) when at the first message will take the user to the last message.
minpassword6This option enforces a minimum password length. Note that this does not prevent the users from setting their passwords to something that’s easy to guess (such as 123456).
vm-passwordcustom_soundIf you want, you can specify a custom sound here to use for the password prompt in voicemail.
vm-newpasswordcustom_soundIf you want, you can specify a custom sound here to use for the “Please enter your new password followed by the pound key” prompt in voicemail.
vm-passchangedcustom_soundIf you want, you can specify a custom sound here to use for the “Your password has been changed” prompt in voicemail.
vm-reenterpasswordcustom_soundIf you want, you can specify a custom sound here to use for the “Please reenter your password followed by the pound key” prompt in voicemail.
vm-mismatchcustom_soundIf you want, you can specify a custom sound here to use for the “The passwords you entered and reentered did not match” prompt in voicemail.
vm-invalid-passwordcustom_soundIf you want, you can specify a custom sound here to use for the “That is not a valid password. Please try again” prompt in voicemail.
vm-pls-try-againcustom_soundIf you want, you can specify a custom sound here to use for the “Please try again” prompt in voicemail.
listen-control-forward-key#You can use this setting to customize the fast forward key.
listen-control-reverse-key*You can use this setting to customize the rewind key.
listen-control-pause-key0You can use this setting to customize the pause/unpause key.
listen-control-restart-key2You can use this setting to customize the replay key.
listen-control-stop-key13456789You can use this setting to customize the interrupt playback key.
backupdeleted0This setting will allow you to specify how many deleted messages are automatically stored by the system. This is similar to a recycle bin. Setting this to 0 disables this feature. Up to 9999 messages can be stored, after which the oldest message will be erased each time another message is deleted.

[a] Yes, we found this a bit confusing too.

[b] Typically the spool folder is /var/spool/asterisk/, and it can be defined in /etc/asterisk/asterisk.conf.


The [zonemessages] Section

The next section of the voicemail.conf file is the [zonemessages] section. The purpose of this section is to allow time zone–specific handling of messages, so you can play back to the user messages with the correct timestamps. You can set the name of the zone to whatever you need. Following the zone name, you can define which time zone you want the name to refer to, as well as some options that define how timestamps are played back. You can look at the ~/src/asterisk-complete/asterisk/1.8/configs/voicemail.conf.sample file for syntax details. Asterisk includes the examples shown in Table 8.3, “[zonemessages] section options for voicemail.conf”.

Table 8.3. [zonemessages] section options for voicemail.conf

Zone nameValue/ExampleNotes
easternAmerica/New_York|'vm-received' Q 'digits/at' IMpThis value would be suitable for the eastern time zone (EST/EDT).
centralAmerica/Chicago|'vm-received' Q 'digits/at' IMpThis value would be suitable for the central time zone (CST/CDT).
central24America/Chicago|'vm-received' q 'digits/at' H N 'hours'This value would also be suitable for CST/CDT, but would play back the time in 24-hour format.
militaryZulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'This value would be suitable for Universal Time Coordinated (Zulu time, formerly GMT).
europeanEurope/Copenhagen|'vm-received' a d b 'digits/at' HMThis value would be suitable for Central European time (CEST).

The Contexts Section

All the remaining sections in the voicemail.conf file will be the voicemail contexts, which allow you to segregate groups of mailboxes.

In many cases, you will only need one voicemail context, commonly named [default]. This is worth noting, as it will make things simpler in the dialplan: all the voicemail-related applications assume the context default if no context is specified. In other words, if you don’t require separation of your voicemail users, use default as your one and only voicemail context.

The format for the mailboxes is as follows:

mailbox => password[,FirstName LastName[,email addr[,pager addr[,options[|options]]]]]

Note

The pipe character (|) used to be more popular in Asterisk. For the first few years, it was used as the standard delimiter. More recently, it has almost completely been replaced by the comma; however, there are still a few places where the pipe is used. One of them is in voicemail.conf: for example, as a separator for any mailbox-specific options, and also as the separator character in the format= declarative. You’ll see this in our upcoming example, as well as in the voicemail.conf.sample file.

The parts of the mailbox definition are:

mailbox

This is the mailbox number. It usually corresponds with the extension number of the associated set.

password

This is the numeric password that the mailbox owner will use to access her voicemail. If the user changes her password, the system will update this field in the voicemail.conf file.

FirstName LastName

This is the name of the mailbox owner. The company directory uses the text in this field to allow callers to spell usernames.

email address

This is the email address of the mailbox owner. Asterisk can send voicemail notifications (including the voicemail message itself, as an attachment) to the specified email box.

pager address

This is the email address of the mailbox owner’s pager or cell phone. Asterisk can send a short voicemail notification message to the specified email address.

options

This field is a list of options for setting the mailbox owner’s time zone and overriding the global voicemail settings. There are nine valid options: attach, serveremail, tz, saycid, review, operator, callback, dialout, and exitcontext. These options should be in option = value pairs, separated by the pipe character (|). The tz option sets the user’s time zone to a time zone previously defined in the [zonemessages] section of voicemail.conf, and the other eight options override the global voicemail settings with the same names.

The mailboxes you define in your voicemail.conf file might look like the following examples:

[default]
100 => 5542,Mike Loukides,mike@shifteight.org
101 => 67674,Tim OReilly,tim@shifteight.org
102 => 36217,Mary JonesSmith,mary.jones-smith@shifteight.org

; *** This needs to all be on the same line
103 => 5426,Some Guy,,,dialout=fromvm|callback=fromvm
|review=yes|operator=yes|envelope=yes

[shifteight]
100 => 0107,Leif Madsen,leif@shifteight.org
101 => 0523,Jim VanMeggelen,jim@shifteight.org,,attach=no|maxmsg=100
102 => 11042,Tilghman Lesher,,,attach=no|tz=central

Warning

The Asterisk directory cannot handle the concept of a family name that is anything other than a simple word. This means that family names such as O’Reilly, Jones-Smith, and yes, even Van Meggelen must have any punctuation characters and spaces removed before being added to voicemail.conf.

The contexts in voicemail.conf are an excellent and powerful concept, but you will likely find that the default context will be all that you need in normal use.

An Initial voicemail.conf File

We recommend the following sample as a starting point. You can refer to ~/asterisk-complete/asterisk/1.8/configs/voicemail.conf.sample for details on the various settings:

; Voicemail Configuration

[general]
format=wav49|wav
serveremail=voicemail@shifteight.org
attach=yes
skipms=3000
maxsilence=10
silencethreshold=128
maxlogins=3
emaildateformat=%A, %B %d, %Y at %r
pagerdateformat=%A, %B %d, %Y at %r
sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside

[zonemessages]
eastern=America/New_York|'vm-received' Q 'digits/at' IMp
central=America/Chicago|'vm-received' Q 'digits/at' IMp
central24=America/Chicago|'vm-received' q 'digits/at' H N 'hours'
military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'
european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM

[shifteight.org]
100 => 1234,Leif Madsen,leif@shifteight.org
101 => 1234,Jim Van Meggelen,jim@shifteight.org
102 => 1234,Russell Bryant,russell@shifteight.org
103 => 1234,Jared Smith,jared@shifteight.org

Note

Setting up a Linux server to handle the sending of email is a Linux administration task that is beyond the scope of this book. You will need to test your voicemail to email service to ensure that the email is being handled appropriately by the Mail Transfer Agent (MTA),[85] and that downstream spam filters are not rejecting the messages (one reason this might happen is if your Asterisk server is using a hostname in the email body that does not in fact resolve to it).

Dialplan Integration

There are two primary dialplan applications that are provided by the app_voicemail.so module in Asterisk. The first, simply named VoiceMail(), does exactly what you would expect it to, which is to record a message in a mailbox. The second one, VoiceMailMain(), allows a caller to log into a mailbox to retrieve messages.

The VoiceMail() Dialplan Application

When you want to pass a call to voicemail, you need to provide two arguments: the mailbox (or mailboxes) in which the message should be left, and any options relating to this, such as which greeting to play or whether to mark the message as urgent. The structure of the VoiceMail() command is this:

VoiceMail(mailbox[@context][&mailbox[@context][&...]][,options])

The options you can pass to VoiceMail() to provide a higher level of control are detailed in Table 8.4, “VoiceMail() optional arguments”.

Table 8.4. VoiceMail() optional arguments

ArgumentPurpose
bInstructs Asterisk to play the busy greeting for the mailbox (if no busy greeting is found, the unavailable greeting will be played).
d([c])Accepts digits to be processed by context c. If the context is not specified, it will default to the current context.
g(#)Applies the specified amount of gain (in decibels) to the recording. Only works on DAHDI channels.
sSuppresses playback of instructions to the callers after playing the greeting.
uInstructs Asterisk to play the unavailable greeting for the mailbox (this is the default behavior).
UIndicates that this message is to be marked as urgent. The most notable effect this has is when voicemail is stored on an IMAP server. In that case, the email will be marked as urgent. When the mailbox owner calls in to the Asterisk voicemail system, he should also be informed that the message is urgent.
PIndicates that this message is to be marked as priority.

The VoiceMail() application sends the caller to the specified mailbox, so that he can leave a message. The mailbox should be specified as mailbox@context, where context is the name of the voicemail context. The option letters b or u can be added to request the type of greeting. If the letter b is used, the caller will hear the mailbox owner’s busy message. If the letter u is used, the caller will hear the mailbox owner’s unavailable message (if one exists).

Consider this simple example extension 101, which allows people to call John:

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

Let’s add an unavailable message that the caller will be played if John doesn’t answer the phone. Remember, the second argument to the Dial() application is a timeout. If the call is not answered before the timeout expires, the call is sent to the next priority. Let’s add a 10-second timeout, and a priority to send the caller to voicemail if John doesn’t answer in time:

exten => 101,1,Dial(${JOHN},10)
exten => 101,n,VoiceMail(101@default,u)      

Now, let’s change it so that if John is busy (on another call), the caller will be sent to his voicemail, where he will hear John’s busy message. To do this, we will make use of the ${DIALSTATUS} variable, which contains one of several status values (type core show application dial at the Asterisk console for a listing of all the possible values):

exten => 101,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

Now callers will get John’s voicemail (with the appropriate greeting) if John is either busy or unavailable. A slight problem remains, however, in that John has no way of retrieving his messages. We will remedy that in the next section.

The VoiceMailMain() Dialplan Application

Users can retrieve their voicemail messages, change their voicemail options, and record their voicemail greetings using the VoiceMailMain() application. VoiceMailMain() accepts two arguments: the mailbox number (and optionally the context) to be accessed, and some options. Both arguments are optional.

The structure of the VoiceMailMain() application looks like this:

VoiceMailMain([mailbox][@context][,options])

If you do not pass any arguments to VoiceMailMain(), it will play a prompt asking the caller to provide her mailbox number. The options that can be supplied are listed in Table 8.5, “VoiceMailMain() optional arguments”.

Table 8.5. VoiceMailMain() optional arguments

ArgumentPurpose
pAllows you to treat the <mailbox> parameter as a prefix to the mailbox number.
g(#)Increases the gain by # decibels when playing back messages.
sSkips the password check.
a(folder)Starts the session in one of the following voicemail folders (defaults to 0): 0 - INBOX, 1 - Old, 2 - Work, 3 - Family, 4 - Friends, 5 - Cust1, 6 - Cust2, 7 - Cust3, 8 - Cust4, 9 - Cust5

To allow users to dial an extension to check their voicemail, you could add an extension to the dialplan like this:

[Services]

exten => *98,1,VoiceMailMain()

Creating a Dial-by-Name Directory

One last feature of the Asterisk voicemail system that we should cover is the dial-by-name directory. This is created with the Directory() application. This application uses the names defined in the mailboxes in voicemail.conf to present the caller with a dial-by-name directory of the users.

Directory() takes up to three arguments: the voicemail context from which to read the names, the optional dialplan context in which to dial the user, and an option string (which is also optional). By default, Directory() searches for the user by last name, but passing the f option forces it to search by first name instead. Let’s add two dial-by-name directories to the incoming context of our sample dialplan, so that callers can search by either first or last name:

exten => 8,1,Directory(default,incoming,f)
exten => 9,1,Directory(default,incoming)

If callers press 8, they’ll get a directory by first name. If they dial 9, they’ll get the directory by last name.

Using a Jitterbuffer

When using Asterisk as a voicemail server,[86] you may want to add a jitterbuffer in between voicemail and the caller. The purpose of a jitterbuffer is to help deal with the fact that when a call traverses an IP network, the traffic may not arrive with perfect timing and in perfect order. If packets occasionally arrive with a bit of delay (jitter) or if they arrive out of order, a jitterbuffer can fix it so that the voicemail system receives the voice stream on time and in order. If the jitterbuffer detects that a packet was lost (or may arrive so late that it will no longer matter), it can perform packet loss concealment. That is, it will attempt to make up a frame of audio to put in place of the lost audio to make it harder to hear that audio was lost.

In Asterisk, jitterbuffer support can only be enabled on a bridge between two channels. In the case of voicemail, there is generally only a single channel connected to one of the voicemail applications. To enable the use of a jitterbuffer in front of voicemail, we create a bridge between two channels by using a Local channel and specifying the j option. Specifying the n option for the Local channel additionally ensures that the Local channel is not optimized out of the call path in Asterisk:

[Services]

exten => *98,1,Dial(Local/vmm@Services/nj)

exten => vmm,1,VoiceMailMain()

Storage Backends

The storage of messages on a traditional voicemail system has always tended to be overly complicated.[87] Asterisk, on the other hand, not only provides you with a simple, logical, filesystem-based storage mechanism, but also offers a few extra message storage options.

Linux Filesystem

By default, Asterisk will store voice messages in the spool folder, at /var/spool/asterisk/voicemail/<context>/<mailbox>. The messages can be stored in multiple formats (such as WAV and GSM), depending on what you specified as the format in the [general] section of your voicemail.conf file. Your greetings will also be stored in this folder.

Note

Asterisk will not create a folder for any mailboxes that do not have any recordings yet (as would be the case with a new mailbox), so this folder cannot be used as a reliable method of determining which mailboxes exist on the system.

Here’s an example of what might be in a mailbox folder. This mailbox has no new messages in the INBOX, has two saved messages in the Old folder, and has busy and unavailable greetings recorded:

/var/spool/asterisk/voicemail/default
./INBOX
./Old
./Old/msg0000.WAV
./Old/msg0000.txt
./Old/msg0001.WAV
./Old/msg0001.txt
./Urgent
./busy.WAV
./unavail
./unavail.WAV

Note

For each message, there is a matching msg####.txt file, which contains the envelope information for the message. The msg####.txt file is also critically important for message waiting indication (MWI), as this is the file that Asterisk looks for in the INBOX to determine whether the message light for a user should be on or off.

ODBC

In a centralized or distributed system, you may find it desirable to store messages as binary objects in a database, instead of as files on the filesystem. We’ll discuss this in detail in the section called “ODBC Voicemail”.

IMAP

Many people would prefer to manage their voicemail as part of their email. This has been called unified messaging by the telecom industry, and its implementation has traditionally been expensive and complex. Asterisk allows for a fairly simple integration between voicemail and email, either through its built-in voicemail to email handler, or through a relationship with an IMAP server. We’ll discuss IMAP integration in detail in the section called “VoiceMail IMAP Integration”.

Using Asterisk As a Standalone Voicemail Server

In a traditional telecom environment, the voicemail server was typically a standalone unit (provided either as a separate server altogether, or as an add-in card to the system). Very few PBXs had fully integrated voicemail (in the sense that voicemail was an integral part of the PBX rather than a peripheral device).

Asterisk is quite capable of serving as a standalone voicemail system. The two most common reasons one might want to do this are:

  1. If you are building a large, centralized system and have several servers each providing a specific function (proxy server, media gateway, voicemail, conferencing, etc.)

  2. If you wish to replace the voicemail system on a traditional PBX with an Asterisk voicemail

Asterisk can serve in either of these roles.

Integrating Asterisk into a SIP Environment As a Standalone Voicemail Server

If you want to have Asterisk act as a dedicated voicemail server (i.e., with no sets registered to it and no other types of calls passing through it), the process from the dialplan perspective is quite simple. Getting message waiting to work can be a bit more difficult, though.

Let’s start with a quick diagram. Figure 8.1, “Simplified SIP enterprise environment” shows an overly simplified example of a typical SIP enterprise environment. We don’t even have an Asterisk server in there (other than for the voicemail), in order to give you a generic representation of how Asterisk could serve as a standalone voicemail server in an otherwise non-Asterisk environment.

Unfortunately, Asterisk cannot send message notification to an endpoint if it doesn’t know where that endpoint is. In a typical Asterisk system, where set registration and voicemail are handled on the same machine, this is never a problem, since Asterisk knows where the sets are. But in an environment where the sets are not registered to Asterisk, this can become a complex problem.

There are several solutions on the Internet that recommend using the externnotify option in voicemail.conf, triggering an external script whenever a message is left in a mailbox (or deleted). While we can’t say that’s a bad approach, we find it a bit kludgy, and it requires the administrator to understand how to write an external script or program to handle the actual passing of the message.

Figure 8.1. Simplified SIP enterprise environment

Simplified SIP enterprise environment

Instead you can statically define an entry for each mailbox in the voicemail server’s sip.conf file, indicating where the message notifications are to be sent. Rather than defining the address of each endpoint, however, you can have the voicemail server send all messages to the proxy, which will handle the relay of the message notifications to the appropriate endpoints.

The voicemail server still needs to know about the SIP endpoints, even though the devices are not registered directly to it. This can be done either through a sip.conf file that identifies each SIP endpoint, or through a static real-time database that does the same thing. Whether you use sip.conf or the Asterisk Realtime Architecture (ARA), each endpoint will require an entry similar to this:

[messagewaiting](!)            ; a template to handle the settings common 
                               ; to all mailboxes
type=peer
subscribecontext=voicemailbox  ; the dialplan context on the voicemail server
context=voicemailbox           ; the dialplan context on the voicemail server
host=192.168.1.1               ; ip address of presence server

[0000FFFF0001](messagewaiting) ; this will need to match the subscriber 
                               ; name on the proxy
mailbox=0000FFFF0001@DIR1      ; this has to be in the form mailbox@mailboxcontext
defaultuser=0000FFFF0001       ; this will need to match the subscriber 
                               ; name on the proxy

Note

Note that Asterisk’s dynamic realtime will not work with this configuration, as a peer’s information is only loaded into memory when there is an actual call involving that peer. Since message notification is not a call as far as Asterisk is concerned, using dynamic realtime will not allow message waiting to happen for any peers not registered to Asterisk.

You will not want to implement this unless you have prototyped the basic operation of the solution. Although we all agree that SIP is a protocol, not everyone agrees as to the correct way to implement the protocol. As a result, there are many interoperability challenges that need to be addressed in a solution like this. We have provided a basic introduction to this concept in this book, but the implementation details will depend on other factors external to Asterisk, such as the capabilities of the proxy.

The fact that no device has to register with Asterisk will significantly reduce the load on the Asterisk server, and as a result this design should allow for a voicemail server that can support several thousand subscribers.

Dialplan requirements

The dialplan of the voicemail server can be fairly simple. Two needs must be satisfied:

  1. Receive incoming calls and direct them to the appropriate mailbox

  2. Handle incoming calls from users wishing to check their messages

The system that is passing calls to the voicemail server should set some SIP headers in order to pass additional information to the voicemail server. Typically, this information would include the mailbox/username that is relevant to the call. In our example, we are going to set the headers X-Voicemail-Mailbox and X-Voicemail-Context, which will contain information we wish to pass to the voicemail server.[88]

Note

If the source system is also an Asterisk system, you might set the headers using the SIPAddHeader() voicemail application, in a manner similar to this:

exten => sendtovoicemail,1,Verbose(2,Set SIP headers for voicemail)
    same => n,SipAddHeader(X-Voicemail-Mailbox: <mailbox number>)
    same => n,SipAddHeader(X-Voicemail-Context: voicemailbox)

Note that this dialplan does not go on the voicemail server. It would only be useful if one of the other servers in your environment was also an Asterisk server. If you were using a different kind of server, you would need to find out how to set custom headers in that platform, or find out if it already uses specific headers for this sort of thing, and possibly modify the dialplan on the voicemail server to handle those headers.

The voicemail server will need an extensions.conf file containing the following:

[voicemailbox]
; direct incoming calls to a mailbox
exten =>  Deliver,1,NoOp()
    same =>  n,Set(Mailbox=${SIP_HEADER(X-Voicemail-Mailbox)})
    same =>  n,Set(MailboxContext=${SIP_HEADER(X-Voicemail-Context)})
    same =>  n,VoiceMail(${Mailbox}@${MailboxContext})
    same =>  n,Hangup()

; connect users to their mailbox so that they can retrieve messages exten =>  
Retrieve,1,NoOp()
    same =>  n,Set(Mailbox=${SIP_HEADER(X-Voicemail-Mailbox)})
    same =>  n,Set(MailboxContext=${SIP_HEADER(X-Voicemail-Context)})
    same =>  n,VoiceMailMain(${Mailbox}@${MailboxContext})
    same =>  n,Hangup()

sip.conf requirements

In the sip.conf file on the voicemail server, not only are entries required for all the mailboxes for message waiting notification, but some sort of entry is required to define the connection between the voicemail server and the rest of the SIP environment:

[VOICEMAILTRUNK]
type=peer
defaultuser=voicemail
fromuser=voicemail
secret=s0m3th1ngs3cur3
canreinvite=no
host=<address of proxy/registrar server>
disallow=all
allow=ulaw
dtmfmode=rfc2833
context=voicemailbox

The other end of the connection (probably your proxy server) must be configured to pass voicemail connections to the voicemail server.

Running Asterisk as a standalone voicemail server requires some knowledge of clustering and integration, but you can’t beat the price.

SMDI (Simplified Message Desk Interface)

The Simplified Message Desk Interface (SMDI) protocol is intended to allow communication of basic message information between telephone systems and voicemail systems.

Asterisk supports SMDI, but given that this is an old protocol that runs across a serial connection, there are likely to be integration challenges. Support in various PBXs and other devices may be spotty. Still, it’s a fairly simple protocol, so for sure it’s worth testing out if you are considering using Asterisk as a voicemail replacement.

The following is not a detailed explanation of how to configure SMDI for Asterisk, but rather an introduction to the concepts, with some basic examples. If you are planning on implementing SMDI, you will need to write some complex dialplan logic and have a good understanding of how to interconnect systems via serial connections.

SMDI is enabled in Asterisk by the use of two options in the [general] section of the voicemail.conf file:

smdienable=yes
smdiport=/dev/ttyS0; or whatever serial port you are connecting your SMDI service to

Additionally, you will need an smdi.conf file in your /etc/asterisk folder to define the details of your SMDI configuration. It should look something like this (see the smdi.conf.sample file for more information on the available options):

[interfaces]
charsize=7
paritybit=even
baudrate=1200           ; hopefully a higher bitrate is supported
smdiport=/dev/ttyS0     ; or whatever serial port you'll be using to handle 
                        ; SMDI messages on asterisk

[mailboxes]             ; map incoming digit strings (typically DID numbers) 
                        ; to a valid mailbox@context in voicemail.conf
smdiport=/dev/ttyS0     ; first declare which SMDI port the following mailboxes 
                        ; will use
4169671111=1234@default
4165551212=9999@default

In the dialplan there are two functions that will be wanted in an SMDI configuration. The SMDI_MSG_RETRIEVE() function pulls the relevant message from the SMDI message queue. You need to pass the function a search key (typically the DID that is referred to in the message), and it will pass back an ID number that can be referenced by the SMDI_MSG() function:

SMDI_MSG_RETRIEVE(<smdi port>,<search key>[,timeout[,options]])

Once you have the SMDI message ID, you can use the SMDI_MSG() function to access various details about the message, such as the station, callerID, and type (the SMDI message type):

SMDI_MSG(<message_id>,<component>)

In your dialplan, you will need to handle the lookup of the SMDI messages that come in, in order to ensure that calls are handled correctly. For example, if an incoming call is intended for delivery to a mailbox, the message type might be one of B (for busy) or N (for unanswered calls). If, on the other hand, the call is intended to go to VoiceMailMain() because the caller wants to retrieve his messages, the SMDI message type would be D, and that would have to be handled.

Conclusion

While the Asterisk voicemail system is quite old in terms of Asterisk code, it is nevertheless a powerful application that can (and does) compete quite successfully with expensive, proprietary voicemail systems.



[83] This name was a play on words, inspired in part by Nortel’s voicemail system Meridian Mail.

[84] No, you really don’t have to pay for this—and yes, it really does work.

[85] Also sometimes called a Message Transfer Agent.

[86] This advice applies to any situation where Asterisk is the endpoint of a call. Another example would be when using the MeetMe() or ConfBridge() applications for conferencing.

[87] Nortel used to store its messages in a sort of special partition, in a proprietary format, which made it pretty much impossible to extract messages from the system, or email them, or archive them, or really do anything with them.

[88] As far as we know, there aren’t any specific SIP headers that are standardized for this sort of thing, so you should be able to name the headers whatever you want. We chose these header names simply because they make some sort of sense. You may find that other headers would suit your needs better.

Chapter 9. Internationalization

David Duffett

I traveled a good deal all over the world, and I got along pretty good in all these foreign countries, for I have a theory that it’s their country and they got a right to run it like they want to.

Will Rogers

Telephony is one of those areas of life where, whether at home or at work, people do not like surprises. When people use phones, anything outside of the norm is an expectation not met, and as someone who is probably in the business of supplying telephone systems, you will know that expectations going unmet can lead to untold misery in terms of the extra work, lost money, and so forth that are associated with customer dissatisfaction.

In addition to ensuring that the user experience is in keeping with what users expect, there is also the need to make your Asterisk feel “at home.” For example, if an outbound call is placed over an analog line (FXO), Asterisk will need to interpret the tones that it “hears” on the line (busy, ringing, etc.).

By default (and maybe as one might expect since it was “born in the USA”), Asterisk is configured to work within North America. However, since Asterisk gets deployed in many places and (thankfully) people from all over the world make contributions to it, it is quite possible to tune Asterisk for correct operation just about anywhere you choose to deploy it.

If you have been reading this book from the beginning, chapter by chapter, you will have already made some choices during the process of installation and initial configuration that will have set up your Asterisk to work in your local area (and live up to your customers’ expectations).

Quite a few of the chapters in this book contain information that will help you internationalize[89] or (perhaps more properly) localize your Asterisk implementation. The purpose of this chapter is to provide a single place where all aspects of the changes that need to be made to your Asterisk-based telephone system in this context can be referenced, discussed, and explained. The reason for using the phrase “Asterisk-based telephone system” rather than just “Asterisk” is that some of the changes will need to be made in other parts of the system (IP phones, ATAs, etc.), while other changes will be implemented within Asterisk and DAHDI configuration files.

Let’s start by getting a list together (in no particular order) of the things that may need to be changed in order to optimise your Asterisk-based telephone system for a given location outside of North America. You can shout some out if you like…

  • Language/accent of the prompts

  • Physical connectorization for PSTN interfaces (FXO, BRI, PRI)

  • Tones heard by users of IP phones and/or ATAs

  • Caller ID format sent and/or received by analog interfaces

  • Tones for analog interfaces to be supplied or detected by Asterisk

  • Format of time/date stamps for voicemail

  • The way the above time/date stamps are announced by Asterisk

  • Patterns within the dialplan (of IP phones, ATAs, and Asterisk itself if you are using the sample dialplan)

  • The way to indicate to an analog device that voicemail is waiting (MWI)

  • Tones supplied to callers by Asterisk (these come into play once a user is “inside” the system; e.g., the tones heard during a call transfer)

We’ll cover everything in this list, adopting a strategy of working from the outer edge of the system toward the very core (Asterisk itself). We will conclude with a handy checklist of what you may need to change and where to change it.

Although the principles discussed in this chapter will allow you to adapt your Asterisk specifically for your region (or that of your customer), for the sake of consistency all of our examples will focus on how to adapt Asterisk for one region: the United Kingdom.

Devices External to the Asterisk Server

There are massive differences between a good old fashioned analog telephone and any one of the large number of IP phones out there, and we need to pick up on one of the really fundamental differences in order to throw light on the next explanation, which covers the settings we might need to change on devices external to Asterisk, such as IP phones.

Have you ever considered the fact that an analog phone is a totally dumb device (we know that a basic model is very, very cheap) that needs to connect to an intelligent network (the PSTN), whereas an IP phone (e.g., SIP or IAX2) is a very intelligent device that connects to a dumb network (the Internet, or any regular IP network)? Figures 9.1 and 9.2 illustrate the difference.

Figure 9.1. The old days: dumb devices connect to a smart network

The old days: dumb devices connect to a smart network

Figure 9.2. The situation today: smart devices connect through a dumb network

The situation today: smart devices connect through a dumb network

Could we take two analog phones, connect them directly to each other and have the functionality we would normally associate with a regular phone? No, of course not, because the network supplies everything: the actual power to the phone, the dialtone (from the local exchange or CO), the caller ID information, the ringing tone (from the remote [closest to the destination phone] exchange or CO), all the signaling required, and so on.

Conversely, could we take two IP phones, connect them directly to each other, and get some sensible functionality? Sure we could, because all the intelligence is inside the IP phones themselves—they provide the tones we hear (dialtone, ringing, busy) and run the protocol that does all the required signaling (usually SIP). In fact, you can try this for yourself—most mid-price IP phones have a built-in Ethernet switch, so you can actually connect the two IP phones directly to each other with a regular (straight-through) Ethernet patch cable, or just connect them through a regular switch. They will need to have fixed IP addresses in the absence of a DHCP server, and you can usually dial the IP address of the other phone just by using the * key for the dots in the address.

Figure 9.2, “The situation today: smart devices connect through a dumb network” points to the fact that on an IP phone, we are responsible for setting all of the tones that the network would have provided in the old days. This can be done in one of (at least) two ways. The first is to configure the tones provided by the IP phone on the device’s own web GUI. This is done by browsing to the IP address of the phone (the IP address can usually be obtained by a menu option on the phone) and then selecting the appropriate options. For example, on a Yealink IP phone, the tones are set on the Phone page of the web GUI, under the Tones tab (where you’ll find a list of the different types of tone that can be changed—in the case of the Yealink, these are Dial, Ring Back, Busy, Congestion, Call Waiting, Dial Recall, Record, Info, Stutter, Message, and Auto Answer).

The other way that this configuration can be applied is to auto-provision the phone with these settings. A full explanation of the mechanism for auto-provisioning is beyond the scope of this book, but you can usually set up the tones in the appropriate attributes of the relevant elements in the XML file.

While we are changing settings on the IP phones, there are two other things that may need to be changed in order for the phones to look right and to function correctly as part of the system.

Most phones display the time when idle and, since many people find it particularly annoying when their phones show the wrong time, we need to ensure that the correct local time is displayed. It should be fairly easy to find the appropriate page of the web GUI (or XML attributes) to specify the time server. You will also find that there are settings for daylight saving time and other relevant stuff nearby.

The last thing to change is a potential show-stopper as far as the making of a phone call is concerned—the dialplan. We’re not talking about the dialplan we find in /etc/asterisk/extensions.conf, but the dialplan of the phone. Not everyone realizes that IP phones have dialplans too—although these dialplans are more concerned with which dial strings are permitted than with what to do on a given dial.

The general rule seems to be that if you dial on-hook the built-in dialplan is bypassed, but if you pick up the handset the dialplan comes into play, and it just might happen that the dialplan will not allow the dial string you need to be dialed. Although this problem can manifest itself with a refusal by the phone to pass certain types of numbers through to Asterisk, it can also affect any feature codes you plan to use. This can easily be remedied by Googling the model number of the phone along with “UK dialplan” (or the particular region you need), or you can go to the appropriate page on the web GUI and either manually adjust the dialplan or pick the country you need from a drop-down box (depending on the type of phone you are working with).

The prior discussion of IP phone configuration also applies to any analog telephone adaptors (ATAs) you plan to use—specifically, to those supporting an FXS interface. In addition, you may need to specify some of the electrical characteristics of the telephony interface, like line voltage and impedance, together with the caller ID format that will work with local phones. All that differs is the way you obtain the IP address for the web GUI—this is usually done by dialing a specific code on the attached analog phone, which results in the IP address being read back to the caller.

Of course, an ATA may also feature an FXO interface, which will also need to be configured to properly interact with the analog line provided in your region. The types of things that need to be changed are similar to the FXS interface.

What if you are connecting your analog phone or line to a Digium card? We’ll cover this next.

PSTN Connectivity, DAHDI, Digium Cards, and Analog Phones

Before we get to DAHDI and Asterisk configuration, we need to physically connect to the PSTN. Unfortunately, there are no worldwide standards for these connections; in fact, there are often variations from one part of a given country to another.

PRI connections are generally terminated in an RJ45 connection these days, although the impedance of the connections can vary. In some countries (notably in South America), it is still possible to find PRIs terminated in two BNC connectors, one for transmit and one for receive.

Generally speaking, a PRI terminated in an RJ45 will be an ISDN connection, and if you find the connection is made by a pair of BNC connectors (push-and-twist coaxial connectors), the likelihood is that you are dealing with a CAS-based protocol (like R2).

Figure 9.3, “A balun” shows the adaptor required if your telco has supplied BNC connectors (the Digium cards require an RJ45 connection). It is called a balun, as it converts from a balanced connection (RJ45) to an unbalanced connection (the BNCs), in addition to changing the connection impedance.

Note

Basic Rate Interfaces (BRIs) are common in continental Europe and are almost always supplied via an RJ45 connection.

Figure 9.3. A balun

A balun

Analog connections vary massively from place to place—you will know what kind of connector is used in your locality. The important thing to remember is that the analog line is only two wires, and these need to connect to the middle two pins of the RJ11 plug that goes into the Digium card—the other end is the local one. Figure 9.4, “The BT plug used for analog PSTN connections in the UK (note only pins 2–5 are present)” shows the plug used in the UK, where the two wires are connected to pins 2 and 5.

Figure 9.4. The BT plug used for analog PSTN connections in the UK (note only pins 2–5 are present)

The BT plug used for analog PSTN connections in the UK (note only pins 2–5 are present)

The Digium Asterisk Hardware Device Interface, or DAHDI, actually covers a number of things. It contains the kernel drivers for telephony adaptor cards that work within the DAHDI framework, as well as automatic configuration utilities and test tools. These parts are contained in two separate packages (dahdi-linux and dahdi-tools), but we can also use one complete package, called dahdi-linux-complete. All three packages are available at http://downloads.digium.com/pub/telephony/. The installation of DAHDI was covered in Chapter 3, Installing Asterisk.

Chapter 7, Outside Connectivity covered the use of analog and digital PSTN connections, and we will not reiterate those details here. If you are using digital PSTN connections, your job is to find out what sort of connection the telco is giving you. Generally, if you have requested a primary rate interface (PRI), this will be a T1 in North America, a J1 in Japan, or an E1 in pretty much the rest of the world.

Once you have established the type of PRI connection the telco has given you, there are some further details that you will require in order to properly configure DAHDI and Asterisk (e.g., whether the connection is ISDN or a CAS-based protocol). Again, you will find these in Chapter 7, Outside Connectivity.

DAHDI Drivers

The connections where some real localization will need to take place are those of analog interfaces. For the purposes of configuring your Asterisk-based telephone system to work best in a given locality, you will first need to specifically configure some low-level aspects of the way the Digium card interacts with the connected device or line. This is done through the DAHDI kernel driver(s), in a file called /etc/dahdi/system.conf.

In the following lines (taken from the sample configuration that you get with a fresh install of DAHDI), you will find both the loadzone and defaultzone settings. The loadzone setting allows you to choose which tone set(s) the card will both generate (to feed to analog telephones) and recognize (on the connected analog telephone lines):

# Tone Zone Data
# ^^^^^^^^^^^^^^
# Finally, you can preload some tone zones, to prevent them from getting
# overwritten by other users (if you allow non-root users to open /dev/dahdi/*
# interfaces anyway). Also this means they won't have to be loaded at runtime.
# The format is "loadzone=<zone>" where the zone is a two letter country code.
#
# You may also specify a default zone with "defaultzone=<zone>" where zone
# is a two letter country code.
#
# An up-to-date list of the zones can be found in the file zonedata.c
#
loadzone = us
#loadzone = us-old
#loadzone=gr
#loadzone=it
#loadzone=fr
#loadzone=de
#loadzone=uk
#loadzone=fi
#loadzone=jp
#loadzone=sp
#loadzone=no
#loadzone=hu
#loadzone=lt
#loadzone=pl
defaultzone=us
#

Tip

The /etc/dahdi/system.conf file uses the hash symbol (#) to indicate a comment instead of a semicolon (;) like the files in /etc/asterisk/.

Although it is possible to load a number of different tone sets (you can see all the sets of tones in detail in zonedata.c) and to switch between them, in most practical situations you will only need:

loadzone=uk     # to load the tone set
defaultzone=uk  # to default DAHDI to using that set

…or whichever tones you need for your region.

If you perform a dahdi_genconf to automatically (or should that be auto-magically?) configure your DAHDI adaptors, you will notice that the newly generated /etc/dahdi/system.conf will have defaulted both loadzone and defaultzone to being us. Despite the warnings not to hand-edit the file, it is fine to change these settings to what you need.

In case you were wondering how we tell whether there are any voicemails in the mailbox associated with the channel an analog phone is plugged into, it is done with a stuttered dialtone. The format of this stuttered dialtone is decided by the loadzone/defaultzone combination you have used.

As a quick aside, analog phones that have a message waiting indicator (e.g., an LED or lamp that flashes to indicate there is new voicemail) achieve this by automatically going off-hook periodically and listening for the stuttered dialtone. You can witness this by watching the Asterisk command line to see the DAHDI channel go active (if you have nothing better to do!).

That’s it at the DAHDI level. We chose the protocol(s) for PRI or BRI connections, the type of signaling for the analog channels (all covered in Chapter 7, Outside Connectivity), and the tones for the analog connections that have just been discussed.

Tip

Once you have completed your configuration at the DAHDI level (in /etc/dahdi/system.conf), you need to perform a dahdi_cfg -vvv to have DAHDI reread the configuration. This is also a good time to use dahdi_tool to check that everything appears to be in order at the Linux level.

This way, if things do not work properly after you have configured Asterisk to work with the DAHDI adaptors, you can be sure that the problem is confined to chan_dahdi.conf (or an #included dahdi-channels.conf if you are using this part of the dahdi_genconf output).

The relationship between Linux, DAHDI, and Asterisk (and therefore /etc/dahdi/system.conf and /etc/asterisk/chan_dahdi.conf) is shown in Figure 9.5, “The relationship between Linux, DAHDI, and Asterisk”.

Figure 9.5. The relationship between Linux, DAHDI, and Asterisk

The relationship between Linux, DAHDI, and Asterisk

Asterisk

With everything set at the Linux level, we now only need to configure Asterisk to make use of the channels we just enabled at the Linux level and to customize the way that Asterisk interprets and generates information that comes in from, or goes out over, these channels. This work is done in /etc/asterisk/chan_dahdi.conf.

In this file we will not only tell Asterisk what sort of channels we have (these settings will fit with what we already did in DAHDI), but also configure a number of things that will ensure Asterisk is well suited to its new home.

Caller ID

A key component of this change is caller ID. While caller ID delivery methods are pretty much standard within the BRI and PRI world, they vary widely in the analog world; thus, if you plugged an American analog phone into the UK telephone network, it would actually work as a phone, but caller ID information would not be displayed. This is because that information is transmitted in different ways in different places around the world, and an American phone would be looking for caller ID signaling in the US format, while the UK telephone network would be supplying it (if it is enabled—it is not standard in the UK; you have to pay for caller ID!) in the UK format.

Not only is the format different, but the method of telling a telephone (or Asterisk) to look out for the caller ID may vary from place to place too. This is important, as we do not want Asterisk to waste time looking for caller ID information if it is not being presented on the line.

Again, Asterisk defaults to the North American caller ID format (no entries in /etc/asterisk/chan_dahdi.conf describe this, it’s just the default), and in order to change it we will need to make some entries that describe the technical details of the caller ID system. In the case of the UK, the delivery of caller ID information is signaled by a polarity reversal on the telephone line (in other words, the A and B legs of the pair of telephone wires are temporarily switched over), and the actual caller ID information is delivered in a format known as V.23 (frequency shift keying, or FSK). So, the entries in chan_dahdi.conf to receive UK-style caller ID on any FXO interfaces will look like this:

cidstart=polarity   ; the delivery of caller ID will be 
                    ; signaled by a polarity reversal
cidsignalling=v23   ; the delivery of the called ID information 
                    ; will be in V23 format

Of course, you may also need to send caller ID using the same local signaling information to any analog phones that are connected to FXS interfaces, and one more entry may be needed as in some locations the caller ID information is sent after a specified number of rings. If this is the case, you can use this entry:

sendcalleridafter=2

Before you can make these entries, you will need to establish the details of your local caller ID system (someone from your local telco or Google could be your friend here, but there is also some good information in the sample /etc/asterisk/chan_dahdi.conf file).

Language and/or Accent of Prompts

As you may know, the prompts (or recordings) that Asterisk will use are stored in /var/lib/asterisk/sounds/. In older versions of Asterisk all the sounds were in this actual directory, but these days you will find a number of subdirectories that allow the use of different languages or accents. The names of these subdirectories are arbitrary; you can call them whatever you want.

Note that the filenames in these directories must be what Asterisk is expecting—for example, in /var/lib/asterisk/sound/en/ the file hello.gsm would contain the word “Hello” (spoken by the lovely Allison), whereas hello.gsm in /var/lib/asterisk/sounds/es/ (for Spanish in this case) would contain the word “Hola” (spoken by the Spanish equivalent of the lovely Allison[90]).

The default directory used is /var/lib/asterisk/sounds/en, so how do you change that?

There are two ways. One is to set the language in the channel configuration file that calls are arriving through using the language directive. For example, the line:

language=en_UK

placed in chan_dahdi.conf, sip.conf, and so on (to apply generally, or for just a given channel or profile) will tell Asterisk to use sound files found in /var/lib/asterisk/sounds/en_UK (which could contain British-accented prompts) for all calls that come in through those channels.

The other way is to change the language during a phone call through the dialplan. This (along with many attributes of an individual call) can be set using the CHANNEL() dialplan function. See Chapter 10, Deeper into the Dialplan for a full treatment of dialplan functions.

The following example would allow the caller to choose one of three languages in which to continue the call:

; gives the choice of (1) French, (2) Spanish, or (3) German
exten => s,1,Background(choose-language)
   same => n,WaitExten(5)

exten => 1,1,Set(CHANNEL(language)=fr)

exten => 2,1,Set(CHANNEL(language)=es)

exten => 3,1,Set(CHANNEL(language)=de)

; the next priority for extensions 1, 2, or 3 would be handled here
exten => _[123],n,Goto(menu,s,1)

If the caller pressed 1 sounds would be played from /var/lib/asterisk/sounds/fr, if he pressed 2 the sounds would come from /var/lib/asterisk/sounds/es, and so on.

As already mentioned, the names of these directories are arbitrary and do not need to be only two characters long—the main thing is that you match the name of the subdirectory you have created in the language directive in the channel configuration, or when you set the CHANNEL(language) argument in the dialplan.

Time/Date Stamps and Pronunciation

Asterisk uses the Linux system time from the host server, as you would expect, but we may have users of the system who are in different time zones, or even in different countries. Voicemail is where the rubber hits the road, as this is where users come into contact with time/date stamp information.

Consider a scenario where some users of the system are based in the US, while others are in the UK.

As well as the time difference, another thing to consider is the way people in the two locations are used to hearing date and time information—in the US, dates are usually ordered month, day, year and times are specified in 12-hour clock format (e.g., 2:54 P.M.).

In contrast, in the UK, dates are ordered day, month, year and times are often specified in 24-hour clock format (14:54 hrs)—although some people in the UK prefer 12-hour clock format, so we will cover that too.

Since all these things are connected to voicemail, you would be right to guess that we configure it in /etc/asterisk/voicemail.conf—specifically, in the [zonemessages] section of the file.

Here is the [zonemessages] part of the sample voicemail.conf file that comes with Asterisk, with UK24 (for UK people that like 24-hour clock format times) and UK12 (for UK people that prefer 12-hour clock format) zones added:

[zonemessages]
; Users may be located in different timezones, or may have different
; message announcements for their introductory message when they enter
; the voicemail system. Set the message and the timezone each user
; hears here. Set the user into one of these zones with the tz=attribute
; in the options field of the mailbox. Of course, language substitution
; still applies here so you may have several directory trees that have
; alternate language choices.
;
; Look in /usr/share/zoneinfo/ for names of timezones.
; Look at the manual page for strftime for a quick tutorial on how the
; variable substitution is done on the values below.
;
; Supported values:
; 'filename' filename of a soundfile (single ticks around the filename
; required)
; ${VAR} variable substitution
; A or a Day of week (Saturday, Sunday, ...)
; B or b or h Month name (January, February, ...)
; d or e numeric day of month (first, second, ... thirty-first)
; Y Year
; I or l Hour, 12 hour clock
; H Hour, 24 hour clock (single digit hours preceded by "oh")
; k Hour, 24 hour clock (single digit hours NOT preceded by "oh")
; M Minute, with 00 pronounced as "o'clock"
; N Minute, with 00 pronounced as "hundred" (US military time)
; P or p AM or PM
; Q "today", "yesterday" or ABdY
; (*note: not standard strftime value)
; q " (for today), "yesterday", weekday, or ABdY
; (*note: not standard strftime value)
; R 24 hour time, including minute
;
eastern=America/New_York|'vm-received' Q 'digits/at' IMp
central=America/Chicago|'vm-received' Q 'digits/at' IMp
central24=America/Chicago|'vm-received' q 'digits/at' H N 'hours'
military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'
european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM
    
UK24=Europe/London|'vm-received' q 'digits/at' H N 'hours'
UK12=Europe/London|'vm-received' Q 'digits/at' IMp    

These zones not only specify a time, but also dictate the way times and dates are ordered and read out.

Having created these zones, we can go to the voicemail context part of voicemail.conf to associate the appropriate mailboxes with the correct zones:

[default]
4001 => 1234,Russell Bryant,rb@shifteight.org,,|tz=central
4002 => 4444,David Duffett,dd@shifteight.org,,|tz=UK24
4003 => 4450,Mary Poppins,mp@shifteight.org,,|tz=UK12|attach=yes

As you can see, when we declare a mailbox, we also (optionally) associate it with a particular zone. Full details on voicemail can be found in Chapter 8, Voicemail.

The last thing to localize in our Asterisk configuration is the tones played to callers by Asterisk once they are inside the system (e.g., the tones a caller hears during a transfer).

As identified earlier in this chapter, the initial tones that people hear when they are calling into the system will come from the IP phone, or from DAHDI for analog channels.

These tones are set in /etc/asterisk/indications.conf. Here is a part of the sample file, where you can see a given region specified by the country directive. We just need to change the country code as appropriate:

;
; indications.conf
;
; Configuration file for location specific tone indications
;
; NOTE:
; When adding countries to this file, please keep them in alphabetical
; order according to the 2-character country codes!
;
; The [general] category is for certain global variables.
; All other categories are interpreted as location specific indications
;
[general]
country=uk   ; default is US, so we have changed it to UK

Your dialplan will need to reflect the numbering scheme for your region. If you do not already know the scheme for your area, your local telecoms regulator will usually be able to supply details of the plan. Also, the example dialplan in /etc/asterisk/extensions.conf is, of course, packed with North American numbers and patterns.

Conclusion—Easy Reference Cheat Sheet

As you can now see, there are quite a few things to change in order to fully localize your Asterisk-based telephone system, and not all of them are in the Asterisk, or even DAHDI, configuration—some things need to be changed on the connected IP phones or ATAs themselves.

Before we leave the chapter, have a look at Table 9.1, “Internationalization cheat sheet”: a cheat sheet for what to change and where to change it, for your future reference.

Table 9.1. Internationalization cheat sheet

What to changeWhere to change it
Call progress tones
  • IP phones—on the phone itself

  • ATAs—on the ATA itself

  • Analog phones—DAHDI (/etc/dahdi/system.conf)

Type of PRI/BRI and protocolDAHDI—/etc/dahdi/system.conf and /etc/asterisk/chan_dahdi.conf
Physical PSTN connections
  • Balun if required for PRI

  • Get the analog pair to middle 2 pins of the RJ11 connecting to the Digium card

Caller ID on analog circuitsAsterisk—/etc/asterisk/chan_dahdi.conf
Prompt language and/or accent
  • Channel—/etc/asterisk/sip.conf, /etc/asterisk/iax.conf, /etc/asterisk/chan_dahdi.conf, etc.

  • Dialplan—CHANNEL(language) function

Voicemail time/date stamps and pronunciationAsterisk—/etc/asterisk/voicemail.conf
Tones delivered by AsteriskAsterisk—/etc/asterisk/indications.conf

May all your Asterisk deployments feel at home…



[89] i18n is a term used to abbreviate the word internationalization, due to its length. The format is <first_letter><number><last_letter>, where <number> is the number of letters between the first and last letters. Other words, such as localization (L10n), modularization (m12n), etc. have also found a home with this scheme, which Leif finds a little bit ridiculous. More information can be found here: http://www.w3.org/2001/12/Glossary#I18N.

[90] Who is, in fact, the same Allison who does the English prompts; June Wallack does the French prompts. The male Australian-accented prompts are done by Cameron Twomey. All voiceover talent are available to record additional prompts as well. See http://www.digium.com/en/products/ivr/ for more information.

Chapter 10. Deeper into the Dialplan

For a list of all the ways technology has failed to improve the quality of life, please press three.

Alice Kahn

Alrighty. You’ve got the basics of dialplans down, but you know there’s more to come. If you don’t have Chapter 6, Dialplan Basics sorted out yet, please go back and give it another read. We’re about to get into more advanced topics.

Expressions and Variable Manipulation

As we begin our dive into the deeper aspects of dialplans, it is time to introduce you to a few tools that will greatly add to the power you can exercise in your dialplan. These constructs add incredible intelligence to your dialplan by enabling it to make decisions based on different criteria you define. Put on your thinking cap, and let’s get started.

Basic Expressions

Expressions are combinations of variables, operators, and values that you string together to produce a result. An expression can test values, alter strings, or perform mathematical calculations. Let’s say we have a variable called COUNT. In plain English, two expressions using that variable might be “COUNT plus 1” and “COUNT divided by 2.” Each of these expressions has a particular result or value, depending on the value of the given variable.

In Asterisk, expressions always begin with a dollar sign and an opening square bracket and end with a closing square bracket, as shown here:

$[expression]

Thus, we would write our two examples like this:

$[${COUNT} + 1]
$[${COUNT} / 2]

When Asterisk encounters an expression in a dialplan, it replaces the entire expression with the resulting value. It is important to note that this takes place after variable substitution. To demonstrate, let’s look at the following code[91]:

exten => 321,1,Set(COUNT=3)
    same => n,Set(NEWCOUNT=$[${COUNT} + 1])
    same => n,SayNumber(${NEWCOUNT})

In the first priority, we assign the value of 3 to the variable named COUNT.

In the second priority, only one application—Set()—is involved, but three things actually happen:

  1. Asterisk substitutes ${COUNT} with the number 3 in the expression. The expression effectively becomes this:

    exten => 321,n,Set(NEWCOUNT=$[3 + 1])
  2. Asterisk evaluates the expression, adding 1 to 3, and replaces it with its computed value of 4:

    exten => 321,n,Set(NEWCOUNT=4)
  3. The Set() application assigns the value 4 to the NEWCOUNT variable

The third priority simply invokes the SayNumber() application, which speaks the current value of the variable ${NEWCOUNT} (set to the value 4 in priority two).

Try it out in your own dialplan.

Operators

When you create an Asterisk dialplan, you’re really writing code in a specialized scripting language. This means that the Asterisk dialplan—like any programming language—recognizes symbols called operators that allow you to manipulate variables. Let’s look at the types of operators that are available in Asterisk:

Boolean operators

These operators evaluate the “truth” of a statement. In computing terms, that essentially refers to whether the statement is something or nothing (nonzero or zero, true or false, on or off, and so on). The Boolean operators are:

expr1 | expr2

This operator (called the “or” operator, or “pipe”) returns the evaluation of expr1 if it is true (neither an empty string nor zero). Otherwise, it returns the evaluation of expr2.

expr1 & expr2

This operator (called “and”) returns the evaluation of expr1 if both expressions are true (i.e., neither expression evaluates to an empty string or zero). Otherwise, it returns zero.

expr1 {=, >, >=, <, <=, !=} expr2

These operators return the results of an integer comparison if both arguments are integers; otherwise, they return the results of a string comparison. The result of each comparison is 1 if the specified relation is true, or 0 if the relation is false. (If you are doing string comparisons, they will be done in a manner that’s consistent with the current local settings of your operating system.)

Mathematical operators

Want to perform a calculation? You’ll want one of these:

expr1 {+, -} expr2

These operators return the results of the addition or subtraction of integer-valued arguments.

expr1 {*, /, %} expr2

These return, respectively, the results of the multiplication, integer division, or remainder of integer-valued arguments.

Regular expression operator

You can also use the regular expression operator in Asterisk:

expr1 : expr2

This operator matches expr1 against expr2, where expr2 must be a regular expression.[92] The regular expression is anchored to the beginning of the string with an implicit ^.[93]

If the match succeeds and the pattern contains at least one regular expression subexpression—\( ... \)—the string corresponding to \1 is returned; otherwise, the matching operator returns the number of characters matched. If the match fails and the pattern contains a regular expression subexpression, the null string is returned; otherwise, 0 is returned.

In Asterisk version 1.0 the parser was quite simple, so it required that you put at least one space between the operator and any other values. Consequently, the following might not have worked as expected:

exten => 123,1,Set(TEST=$[2+1])

This would have assigned the variable TEST to the string “2+1”, instead of the value 3. In order to remedy that, we would put spaces around the operator, like so:

exten => 234,1,Set(TEST=$[2 + 1])

This is no longer necessary in current versions of Asterisk, as the expression parser has been made more forgiving in these types of scenarios. However, for readability’s sake, we still recommend including the spaces around your operators.

To concatenate text onto the beginning or end of a variable, simply place them together, like this:

exten => 234,1,Set(NEWTEST=blah${TEST})

Dialplan Functions

Dialplan functions allow you to add more power to your expressions; you can think of them as intelligent variables. Dialplan functions allow you to calculate string lengths, dates and times, MD5 checksums, and so on, all from within a dialplan expression.

Syntax

Dialplan functions have the following basic syntax:

FUNCTION_NAME(argument)

You reference a function’s name the same way as a variable’s name, but you reference a function’s value with the addition of a dollar sign, an opening curly brace, and a closing curly brace:

${FUNCTION_NAME(argument)}

Functions can also encapsulate other functions, like so:

${FUNCTION_NAME(${FUNCTION_NAME(argument)})}
 ^             ^ ^             ^        ^^^^
 1             2 3             4        4321

As you’ve probably already figured out, you must be very careful about making sure you have matching parentheses and braces. In the preceding example, we have labeled the opening parentheses and curly braces with numbers and their corresponding closing counterparts with the same numbers.

Examples of Dialplan Functions

Functions are often used in conjunction with the Set() application to either get or set the value of a variable. As a simple example, let’s look at the LEN() function. This function calculates the string length of its argument. Let’s calculate the string length of a variable and read back the length to the caller:

exten => 123,1,Set(TEST=example)
    same => n,SayNumber(${LEN(${TEST})})

This example will first evaluate $TEST as example. The string “example” is then given to the LEN() function, which will evaluate as the length of the string, 7. Finally, 7 is passed as an argument to the SayNumber() application.

Let’s look at another simple example. If we wanted to set one of the various channel timeouts, we could use the TIMEOUT() function. The TIMEOUT() function accepts one of three arguments: absolute, digit, and response. To set the digit timeout with the TIMEOUT() function, we could use the Set() application, like so:

exten => s,1,Set(TIMEOUT(digit)=30)

Notice the lack of ${ } surrounding the function. Just as if we were assigning a value to a variable, we assign a value to a function without the use of the ${ } encapsulation.

A complete list of available functions can be found by typing core show functions at the Asterisk command-line interface.

Conditional Branching

Now that you’ve learned a bit about expressions and functions, it’s time to put them to use. By using expressions and functions, you can add even more advanced logic to your dialplan. To allow your dialplan to make decisions, you’ll use conditional branching. Let’s take a closer look.

The GotoIf() Application

The key to conditional branching is the GotoIf() application. GotoIf() evaluates an expression and sends the caller to a specific destination based on whether the expression evaluates to true or false.

GotoIf() uses a special syntax, often called the conditional syntax:

GotoIf(expression?destination1:destination2)

If the expression evaluates to true, the caller is sent to destination1. If the expression evaluates to false, the caller is sent to the second destination. So, what is true and what is false? An empty string and the number 0 evaluate as false. Anything else evaluates as true.

The destinations can each be one of the following:

  • A priority label within the same extension, such as weasels

  • An extension and a priority label within the same context, such as 123,weasels

  • A context, extension, and priority label, such as incoming,123,weasels

Either of the destinations may be omitted, but not both. If the omitted destination is to be followed, Asterisk simply goes on to the next priority in the current extension.

Let’s use GotoIf() in an example:

exten => 345,1,Set(TEST=1)
   same => n,GotoIf($[${TEST} = 1]?weasels:iguanas)
   same => n(weasels),Playback(weasels-eaten-phonesys)
   same => n,Hangup()
   same => n(iguanas),Playback(office-iguanas)
   same => n,Hangup()

Note

You will notice that we have used the Hangup() application following each use of the Playback() application. This is done so that when we jump to the weasels label, the call stops before execution gets to the office-iguanas sound file. It is becoming increasingly common to see extensions broken up into multiple components (protected from each other by the Hangup() command), each one a distinct sequence of steps executed following a GotoIf().

Typically, when you have this type of layout where you end up wanting to prevent Asterisk from falling through to the next priority after you’ve performed that jump, it’s probably better to jump to separate extensions instead of priority labels. If anything, it makes it a bit more clear when reading the dialplan. We could rewrite the previous bit of dialplan like this:

exten => 345,1,Set(TEST=1)
   same => n,GotoIf($[${TEST} = 1]?weasels,1:iguanas,1) ; now we're going to
                                                        ; extension,priority

exten => weasels,1,Playback(weasels-eaten-phonesys)     ; this is NOT a label.
                                                        ; It is a different extension
   same => n,Hangup()

exten => iguanas,1,Playback(office-iguanas)
   same => n,Hangup()

By changing the value assigned to TEST in the first line, you should be able to have your Asterisk server play a different greeting.

Let’s look at another example of conditional branching. This time, we’ll use both Goto() and GotoIf() to count down from 10 and then hang up:

exten => 123,1,Set(COUNT=10)
   same => n(start),GotoIf($[${COUNT} > 0]?:goodbye)
   same => n,SayNumber(${COUNT})
   same => n,Set(COUNT=$[${COUNT} - 1])
   same => n,Goto(start)
   same => n(goodbye),Hangup()

Let’s analyze this example. In the first priority, we set the variable COUNT to 10. Next, we check to see if COUNT is greater than 0. If it is, we move on to the next priority. (Don’t forget that if we omit a destination in the GotoIf() application, control goes to the next priority.) From there, we speak the number, subtract 1 from COUNT, and go back to priority label start. If COUNT is less than or equal to 0, control goes to priority label goodbye, and the call is hung up.

The classic example of conditional branching is affectionately known as the anti-girlfriend logic. If the caller ID number of the incoming call matches the phone number of the recipient’s ex-girlfriend, Asterisk gives a different message than it ordinarily would to any other caller. While somewhat simple and primitive, it’s a good example for learning about conditional branching within the Asterisk dialplan.

This example uses the CALLERID function, which allows us to retrieve the caller ID information on the inbound call. Let’s assume for the sake of this example that the victim’s phone number is 888-555-1212:

exten => 123,1,GotoIf($[${CALLERID(num)} = 8885551212]?reject:allow)
   same => n(allow),Dial(DAHDI/4)
   same => n,Hangup()
   same => n(reject),Playback(abandon-all-hope)
   same => n,Hangup()

In priority 1, we call the GotoIf() application. It tells Asterisk to go to priority label reject if the caller ID number matches 8885551212, and otherwise to go to priority label allow (we could have simply omitted the label name, causing the GotoIf() to fall through). If the caller ID number matches, control of the call goes to priority label reject, which plays back an uninspiring message to the undesired caller. Otherwise, the call attempts to dial the recipient on channel DAHDI/4.

Time-Based Conditional Branching with GotoIfTime()

Another way to use conditional branching in your dialplan is with the GotoIfTime() application. Whereas GotoIf() evaluates an expression to decide what to do, GotoIfTime() looks at the current system time and uses that to decide whether or not to follow a different branch in the dialplan.

The most obvious use of this application is to give your callers a different greeting before and after normal business hours.

The syntax for the GotoIfTime() application looks like this:

GotoIfTime(times,days_of_week,days_of_month,months?label)

In short, GotoIfTime() sends the call to the specified label if the current date and time match the criteria specified by times, days_of_week, days_of_month, and months. Let’s look at each argument in more detail:

times

This is a list of one or more time ranges, in a 24-hour format. As an example, 9:00 A.M. through 5:00 P.M. would be specified as 09:00-17:00. The day starts at 0:00 and ends at 23:59.

Note

It is worth noting that times will properly wrap around. So, if you wish to specify the times your office is closed, you might write 18:00-9:00 in the times parameter, and it will perform as expected. Note that this technique works as well for the other components of GotoIfTime(). For example, you can write sat-sun to specify the weekend days.

days_of_week

This is a list of one or more days of the week. The days should be specified as mon, tue, wed, thu, fri, sat, and/or sun. Monday through Friday would be expressed as mon-fri. Tuesday and Thursday would be expressed as tue&thu.

Note

Note that you can specify a combination of ranges and single days, as in: sun-mon&wed&fri-sat, or, more simply: wed&fri-mon.

days_of_month

This is a list of the numerical days of the month. Days are specified by the numbers 1 through 31. The 7th through the 12th would be expressed as 7-12, and the 15th and 30th of the month would be written as 15&30.

months

This is a list of one or more months of the year. The months should be written as jan-apr for a range, and separated with ampersands when wanting to include nonsequential months, such as jan&mar&jun. You can also combine them like so: jan-apr&jun&oct-dec.

If you wish to match on all possible values for any of these arguments, simply put an * in for that argument.

The label argument can be any of the following:

  • A priority label within the same extension, such as time_has_passed

  • An extension and a priority within the same context, such as 123,time_has_passed

  • A context, extension, and priority, such as incoming,123,time_has_passed

Now that we’ve covered the syntax, let’s look at a couple of examples. The following example would match from 9:00 A.M. to 5:59 P.M., on Monday through Friday, on any day of the month, in any month of the year:

exten => s,1,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)

If the caller calls during these hours, the call will be sent to the first priority of the s extension in the context named open. If the call is made outside of the specified times, it will be sent to the next priority of the current extension. This allows you to easily branch on multiple times, as shown in the next example (note that you should always put your most specific time matches before the least specific ones):

; If it's any hour of the day, on any day of the week,
; during the fourth day of the month, in the month of July,
; we're closed
exten => s,1,GotoIfTime(*,*,4,jul?closed,s,1)

; During business hours, send calls to the open context
   same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)
   same => n,GotoIfTime(09:00-11:59,sat,*,*?open,s,1)

; Otherwise, we're closed
   same => n,Goto(closed,s,1)

Tip

If you run into the situation where you ask the question, “But I specified 17:58 and it’s now 17:59. Why is it still doing the same thing?” it should be noted that the granularity of the GotoIfTime() application is only to a two-minute period. So, if you specify 18:00 as the ending time of a period, the system will continue to perform the same way until 18:01:59.

Macros

Macros[94] are a very useful construct designed to avoid repetition in the dialplan. They also help in making changes to the dialplan. To illustrate this point, let’s look at our sample dialplan again. If you remember the changes we made for voicemail, we ended up with the following for John’s extension:

exten => 101,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

Now imagine you have a hundred users on your Asterisk system—setting up the extensions would involve a lot of copying and pasting. Then imagine that you need to make a change to the way your extensions work. That would involve a lot of editing, and you’d be almost certain to have errors.

Instead, you can define a macro that contains a list of steps to take, and then have all of the phone extensions refer to that macro. All you need to change is the macro, and everything in the dialplan that references that macro will change as well.

Tip

If you’re familiar with computer programming, you’ll recognize that macros are similar to subroutines in many modern programming languages. If you’re not familiar with computer programming, don’t worry—we’ll walk you through creating a macro.

The best way to appreciate macros is to see one in action, so let’s move right along.

Defining Macros

Let’s take the dialplan logic we used to set up voicemail for John and turn it into a macro. Then we’ll use the macro to give John and Jane (and the rest of their coworkers) the same functionality.

Macro definitions look a lot like contexts. (In fact, you could argue that they really are small, limited contexts.) You define a macro by placing macro- and the name of your macro in square brackets, like this:

[macro-voicemail]

Macro names must start with macro-. This distinguishes them from regular contexts. The commands within the macro are built almost identically to anything else in the dialplan; the only limiting factor is that macros use only the s extension. Let’s add our voicemail logic to the macro, changing the extension to s as we go:

[macro-voicemail]
exten => s,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

That’s a start, but it’s not perfect, as it’s still specific to John and his mailbox number. To make the macro generic so that it will work not only for John but also for all of his coworkers, we’ll take advantage of another property of macros: arguments. But first, let’s see how we call macros in our dialplan.

Calling Macros from the Dialplan

To use a macro in our dialplan, we use the Macro() application. This application calls the specified macro and passes it any arguments. For example, to call our voicemail macro from our dialplan, we can do the following:

exten => 101,1,Macro(voicemail)

The Macro() application also defines several special variables for our use. They include:

${MACRO_CONTEXT}

The original context in which the macro was called.

${MACRO_EXTEN}

The original extension in which the macro was called.

${MACRO_PRIORITY}

The original priority in which the macro was called.

${ARG n }

The nth argument passed to the macro. For example, the first argument would be ${ARG1}, the second ${ARG2}, and so on.

As we explained earlier, the way we initially defined our macro was hardcoded for John, instead of being generic. Let’s change our macro to use ${MACRO_EXTEN} instead of 101 for the mailbox number. That way, if we call the macro from extension 101 the voicemail messages will go to mailbox 101, if we call the macro from extension 102 messages will go to mailbox 102, and so on:

[macro-voicemail]
exten => s,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(${MACRO_EXTEN}@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
   same => n,Hangup()

Using Arguments in Macros

Okay, now we’re getting closer to having the macro the way we want it, but we still have one thing left to change: we need to pass in the channel to dial, as it’s currently still hardcoded for ${JOHN} (remember that we defined the variable JOHN as the channel to call when we want to reach John). Let’s pass in the channel as an argument, and then our first macro will be complete:

[macro-voicemail]
exten => s,1,Dial(${ARG1},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(${MACRO_EXTEN}@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
   same => n,Hangup()

Now that our macro is done, we can use it in our dialplan. Here’s how we can call our macro to provide voicemail to John, Jane, and Jack:

exten => 101,1,Macro(voicemail,${JOHN})
exten => 102,1,Macro(voicemail,${JANE})
exten => 103,1,Macro(voicemail,${JACK})

With 50 or more users, this dialplan will still look neat and organized; we’ll simply have one line per user, referencing a macro that can be as complicated as required. We could even have a few different macros for various user types, such as executives, courtesy_phones, call_center_agents, analog_sets, sales_department, and so on.

A more advanced version of the macro might look something like this:

[macro-voicemail]
exten => s,1,Dial(${ARG1},20)
   same => n,Goto(s-${DIALSTATUS},1)

exten => s-NOANSWER,1,VoiceMail(${MACRO_EXTEN},u)
   same => n,Goto(incoming,s,1)

exten => s-BUSY,1,VoiceMail(${MACRO_EXTEN},b)
   same => n,Goto(incoming,s,1)

exten => _s-.,1,Goto(s-NOANSWER,1)

Tip

Since we know how to use dialplan functions now as well, here is another way of controlling which voicemail prompt (unavailable vs. busy) is played to the caller. In the following example, we’ll be using the IF() dialplan function:

[macro-voicemail]
exten => s,1,Dial(${ARG1},20)
   same => n,VoiceMail(${MACRO_EXTEN},${IF($[${DIALSTATUS} = BUSY]?b:u)})

This macro depends on a nice side effect of the Dial() application: when you use the Dial() application, it sets the DIALSTATUS variable to indicate whether the call was successful or not. In this case, we’re handling the NOANSWER and BUSY cases, and treating all other result codes as a NOANSWER.

GoSub()

The GoSub() dialplan application is similar to the Macro() application, in that the purpose is to allow you to call a block of dialplan functionality, pass information to that block, and return from it (optionally with a return value). GoSub() works in a different manner from Macro(), though, in that it doesn’t have the stack space requirements, so it nests effectively. Essentially, GoSub() acts like Goto() with a memory of where it came from.

In this section we’re going to reimplement what we learned in the section called “Macros”. If necessary, you might want to review that section: it explains why we might use a subroutine, and the goal we’re trying to accomplish.

Defining Subroutines

Unlike with Macro(), there are no special naming requirements when using GoSub() in the dialplan. In fact, you can use GoSub() within the same context and extension if you want to. In most cases, however, GoSub() is used in a similar fashion to Macro(), so defining a new context is common. When creating the context, we like to prepend the name with sub so we know the context is typically called from the GoSub() application (of course, there is no requirement that you do so, but it seems a sensible convention).

Here is a simple example of how we might define a subroutine in Asterisk:

[subVoicemail]

Let’s take our example from the section called “Macros” and convert it to a subroutine. Here is how it is defined for use with Macro():

[macro-voicemail]
exten => s,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

If we were going to convert this to be used for a subroutine, it might look like this:

[subVoicemail]
exten => start,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

Not much of a change, right? All we’ve altered in this example is the context name, from [macro-voicemail] to [subVoicemail], and the extension, from s to start (since there is no requirement that the extension be called anything in particular, unlike with Macro(), which expects the extension to be s).

Of course, as in the example in the section the section called “Macros”, we haven’t passed any arguments to the subroutine, so whenever we call [subVoicemail], ${JOHN} will always be called, and the voicemail box 101 will get used. In the following sections, we’ll dig a little deeper. First we’ll look at how we would call a subroutine, and then we’ll learn how to pass arguments.

Calling Subroutines from the Dialplan

Subroutines are called from the dialplan using the GoSub() application. The arguments to GoSub() differ slightly than those for Macro(), because GoSub() has no naming requirements for the context or extension (or priority) that gets used. Additionally, no special channel variables are set when calling a subroutine, other than the passed arguments, which are saved to ${ARGn} (where the first argument is ${ARG1}, the second argument is ${ARG2}, and so forth).

Now that we’ve updated our voicemail macro to be called as a subroutine, lets take a look at how we call it using GoSub():

exten => 101,1,GoSub(subVoicemail,start,1())

Note

You’ll notice that we’ve placed a set of opening and closing parentheses within our GoSub() application. These are the placeholders for any arguments we might pass to the subroutine, and while it is optional for them to exist, it’s a programming style we prefer to use.

Next, let’s look at how we can pass arguments to our subroutine in order to make it more general.

Using Arguments in Subroutines

The ability to use arguments is one of the major features of using Macro() or GoSub(), because it allows you to abstract out code that would otherwise be duplicated across your dialplan. Without the need to duplicate the code, we can better manage it, and we can easily add functionality to large numbers of users by modifying a single location. You are encouraged to move code into this form whenever you find yourself creating duplicate code.

Before we start using our subroutine, we need to update it to accept arguments so that it is generic enough to be used by multiple users:

[subVoicemail]
exten => start,1,Dial(${ARG1},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(${ARG2}@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(${ARG2}@default,b)
   same => n,Hangup()

Recall that previously we had hardcoded the channel variable ${JOHN} as the location to dial, and mailbox 101 as the voicemail box to be used if ${JOHN} wasn’t available. In this code, we’ve replaced ${JOHN} and 101 with ${ARG1} and ${ARG2}, respectively. In more complex subroutines we might even assign the variables ${ARG1} and ${ARG2} to something like ${DESTINATION} and ${VMBOX}, to make it clear what the ${ARG1} and ${ARG2} represent.

Now that we’ve updated our subroutine, we can use it for several extensions:

[LocalSets]
exten => 101,1,GoSub(subVoicemail,start,1(${JOHN},${EXTEN}))
exten => 102,1,GoSub(subVoicemail,start,1(${JANE},${EXTEN}))
exten => 103,1,GoSub(subVoicemail,start,1(${JACK},${EXTEN}))

Again, our dialplan is nice and neat. We could even modify our subroutine down to just three lines:

[subVoicemail]
exten => start,1,Dial(${ARG1},10)
   same => n,VoiceMail(${ARG2}@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
   same => n,Hangup()

One difference to note between GoSub() and Macro(), however, is that if we left our subroutine like this, we’d never return. In this particular example that’s not a problem, since after the voicemail is left, we would expect the caller to hang up anyway. In situations where we want to do more after the subroutine has executed, though, we need to implement the Return() application.

Returning from a Subroutine

Unlike Macro(), the GoSub() dialplan application does not return automatically once it is done executing. In order to return from whence we came, we need to use the Return() application. Now that we know how to call a subroutine and pass arguments, we can look at an example where we might need to return from the subroutine.

Using our previous example, we could break out the dialing portion and the voicemail portion into separate subroutines:

[subDialer]
exten => start,1,Dial(${ARG1},${ARG2})
   same => n,Return()

[subVoicemail]
exten => start,1,VoiceMail(${ARG1}@${ARG2},${ARG3})
   same => n,Hangup()

The [subDialer] context created here takes two arguments: ${ARG1}, which contains the destination to dial; and ${ARG2}, which contains the ring cycle, defined in seconds. We conclude the [subDialer] context with the dialplan application Return(), which will return to the priority following the one that called GoSub() (the next line of the dialplan).

The [subVoicemail] context contains the VoiceMail() application, which is using three arguments passed to it: ${ARG1} contains the mailbox number, ${ARG2} contains the voicemail context, and ${ARG3} contains a value to indicate which voicemail message (unavailable or busy) to play to the caller.

Calling these subroutines might look like this:

exten => 101,1,GoSub(subDialer,start,1(${JOHN},30))
   same => n,GoSub(subVoicemail,start,1(${EXTEN},default,u))

Here we’ve used the subDialer subroutine, which attempts to call ${JOHN}, ringing him for 30 seconds. If the Dial() application returns (e.g., if the line was busy, or there was no answer for 30 seconds), we Return() from the subroutine and execute the next line of our dialplan, which calls the subVoicemail subroutine. From there, we pass the extension that was dialed (e.g., 101) as the mailbox number, and pass the values default for the voicemail context and the letter u to play the unavailable message.

Our example has been hardcoded to play the unavailable voicemail message, but we can modify the Return() application to return the ${DIALSTATUS} so that we can play the busy message if its value is BUSY. To do this, we’ll use the ${GOSUB_RETVAL} channel variable, which is set whenever we pass a value to the Return() application:

[subDialer]
exten => start,1,Dial(${ARG1},${ARG2})
   same => n,Return(${DIALSTATUS})

[subVoicemail]
exten => start,1,VoiceMail(${ARG1}@${ARG2},${ARG3})
   same => n,Hangup()

In this version we’ve made just the one change: Return() to Return(${DIALSTATUS}).

Now we can modify extension 101 to use the ${GOSUB_RETVAL} channel variable, which will be set by Return():

exten => 101,1,GoSub(subDialer,start,1(${JOHN},30))
   same => n,Set(VoicemailMessage=${IF($[${GOSUB_RETVAL} = BUSY]?b:u)})
   same => n,GoSub(subVoicemail,start,1(${EXTEN},default,${VoicemailMessage}))

Our dialplan now has a new line that sets the ${VoicemailMessage} channel variable to a value of u or b, using the IF() dialplan function and the value of ${GOSUB_RETVAL}. We then pass the value of ${VoicemailMessage} as the third argument to our subVoicemail subroutine.

Before moving on, you might want to go back and review the section called “Macros” andthe section called “GoSub()”. We’ve given you a lot to digest here, but these concepts will save you a lot of work as you start building your dialplans.

Local Channels

Local channels are a method of executing dialplans from the Dial() application. They may seem like a bit of a strange concept when you first start using them, but believe us when we tell you they are a glorious and extremely useful feature that you will almost certainly want to make use of when you start writing advanced dialplans. The best way to illustrate the use of Local channels is through an example. Let’s suppose we have a situation where we need to ring multiple people, but we need to provide delays of different lengths before dialing each of the members. The use of Local channels is the only solution to the problem.

With the Dial() application, you can certainly ring multiple endpoints, but all three channels will ring at the same time, and for the same length of time. Dialing multiple channels at the same time is done like so:

[LocalSets]
exten => 107,1,Verbose(2,Dialing multiple locations simultaneously)
   same => n,Dial(SIP/0000FFFF0001&DAHDI/g0/14165551212&SIP/MyITSP/12565551212,30)
   same => n,Hangup()

This example dials three destinations for a period of 30 seconds. If none of those locations answers the call within 30 seconds, the dialplan continues to the next line and the call is hung up.

However, let’s say we want to introduce some delays, and stop ringing locations at different times. Using Local channels gives us independent control over each of the channels we want to dial, so we can introduce delays and control the period of time for which each channel rings independently. We’re going to show you how this is done in the dialplan, both within a table that shows the delays visually, and all together in a box, like we’ve done for other portions of the dialplan. We’ll be building the dialplan to match the time starts and stops described in Figure 10.1, “Time delayed dialing with local channels”.

Figure 10.1. Time delayed dialing with local channels

Time delayed dialing with local channels

First we need to call three Local channels, which will all execute different parts of the dialplan. We do this with the Dial() application, like so:

[LocalSets]
exten => 107,1,Verbose(2,Dialing multiple locations with time delay)

; *** This all needs to be on a single line
   same => n,Dial(Local/channel_1@TimeDelay&Local/channel_2@TimeDelay
&Local/channel_3@TimeDelay,40)
   same => n,Hangup()

Now our Dial() application will dial three Local channels. The destinations will be the channel_1, channel_2, and channel_3 extensions located within the TimeDelay dialplan context. Remember that Local channels are a way of executing the dialplan from within the Dial() application. Our master timeout for all the channels is 40 seconds, which means any Local channel that does not have a shorter timeout configured will be hung up if it does not answer the call within that period of time.

As promised, Table 10.1, “Delayed dialing using Local channels” illustrates the delay configurations.

Table 10.1. Delayed dialing using Local channels

Time period (in seconds)channel_1channel_2channel_3
0 Dial(SIP/0000FFFF0001,20) Wait(10) Wait(15)
5   
10  Dial(DAHDI/g0/14165551212)  
15   Dial(SIP/MyITSP/12565551212,15)
20 Hangup()   
25   
30   Hangup()
35   
40   

In this table, we can see that channel_1 started dialing location SIP/0000FFFF0001