Monday 9 February 2009

Asterisk: A Bare-Bones VoIP Example p:1

Open source software (OSS) has achieved a dominant role in the delivery of IP-based content such as web data (Apache) and email (sendmail), and is making serious headway in streaming media (icecast). As processors become less expensive and more powerful, even jobs that were once relegated to specific hardware (such as routing and load sharing) are now becoming possible on low-cost OSS platforms running Linux or BSD-based operating systems. The last bastion of hardware-specific functionality in the office environment has been the phone system, or PBX (Private Branch Exchange). PBX installations range from key systems with a few lines to large platforms fed by Primary Rate Interface ISDN (PRI) that are complex and expensive to deploy, with hundreds or thousands of extensions spanning several states or continents.

Until now, open source telephony applications have been at the periphery of the PBX, and even then, they have not been PBX-specific: fax modem software, simple voicemail software, and caller-identification software all work in conjunction with standard phone lines, but rarely together in concert as a unified platform.

Asterisk is both an open source toolkit for telephony applications and a full-featured call-processing server in itself. It can be a standalone system, or used as an adjunct to a previously existing PBX or Voice Over IP (VoIP) implementation. It can be software only, moving calls around via IP, or it can have a variety of hardware interfaces to directly tie in with existing TDM (Time Division Multiplexing) equipment. Asterisk is not a VoIP platform; it is a Computerized Telephony Integration platform, which just happens to have a number of very useful input/output channels through VoIP. Asterisk can just as easily be a server that has no Internet connectivity, but uses PCI-card-based analog or digital trunks to process calls -- an important distinction between Asterisk and many other systems.

It is difficult to describe the full feature set of Asterisk due to the number of fairly complex topics that are incorporated into the system: multiple VOIP channel types, hardware interfaces, a scripting language, an API, modules, and more features than can be addressed in this short article. To provide a brief introduction to Asterisk's capabilities, I will show an example that creates a very simple PBX with two extensions and voicemail on each. There will be no external connectivity to this PBX; we will simply be able to call from one line to the other. This would allow, as an example, two users to be in separate parts of the country but they could ring each other's desk phones. If the called party was unavailable, voicemail could be left.


Voice Over IP (VoIP)

VoIP has been around for a while, but has been fairly restricted to high-end users such as phone companies and large enterprise phone networks; only recently has VoIP gained momentum with end users and smaller shops. There have been a small handful of proprietary long-distance solutions for some time, but these were closed-source systems that did not lend themselves to any extensions by the OSS community. The push of VoIP technology closer to the grasp of the Linux/*BSD end user or administrator can be attributed to a combination of low-cost, high-speed bandwidth and a recent agreement to standardize on open protocols for call delivery.

Within the last eighteen months, it has become evident that the protocol that will be leading the industry for VoIP deployments is Session Initiation Protocol (SIP) -- see RFC3265. SIP is a simple, text-based description protocol that uses interactions similar to HTTP and SMTP in order for two systems to describe a media stream (in our case, voice traffic) that needs to get from point A to point B. The description includes authentication, caller ID information, media stream parameters, and a variety of other header information that is needed to fully qualify a call between two endpoints.

While there are other VoIP protocols supported by Asterisk (such as H323 and MGCP) I will only describe SIP, as there are a growing number of phones and software stacks that support SIP as a method for call description, and for the beginner, SIP is easier to debug due to its use of plaintext headers.

Asterisk Theory

See the Configuration section below for samples of the files that are referenced here.

Call Flow: Starting Out

A call comes in on one of several channels (SIP in our case) and is "destined" for a dialed number. The Asterisk process first deals with the call via whatever channel it came in on, and learns what to do with it in that manner, and into what context to send the call in extensions.conf. In our example, calls inbound from both of our SIP phones are sent to the context from-sip, which is where we are going to start matching the dialed numbers. The called number is translated into a variable called ${EXTEN}, and we'll refer to this variable from now on when talking about the number being dialed. It is implicitly used in any matching statements, so you don't have to worry about specifying it elsewhere. However, for ease of reference, we will use it in this article whenever we talk about the number that has been called.

Contexts

Now that sip.conf has told our call what context to go to, the control is handed over to the definitions created by the file extensions.conf. The extensions.conf file works by defining various "contexts," which are clusters of dialed-number matching statements. The context is the central building block of Asterisk, and, loosely, is used as one might use a subroutine. Within a context are a number of matching statements that perform match tests against the number being processed. The call is passed through the comparison list until a match is found.

A context can have "special" extensions, which are pre-defined and are reserved for special behavior. The most commonly used extension is h, which means hangup, and allows your dial plan to execute certain routines at the completion of a call. See the manual for a more complete listing of special extensions. None of the special extensions are used in our example.

Extension Matching

Each context has a set of extension matches, which determine what applications should be triggered by the call, and how the call should be routed. Matching is performed in numerically ascending order, which can be tricky if you have many matches that are similar; in our example we have a very simple match list. The matching examination is done on the digits following the => up until the next comma. Each match definition has at least one "priority," which simply is a number that tells the server in what order to execute the applications when a match for the matching string is found. Priorities must be sequential whole numbers, which sometimes leads to headaches if you discover you need to insert an application at the top of a priority list.

Each line is in the format:

exten => extension,priority,application

Here's an example:

exten => 3334,1,Answer
exten => 3334,2,Playback(welcome-to-foo-inc)
exten => 3334,3,Wait(1)
exten => 3334,4,Playback(the-date-and-time-is)
exten => 3334,5,DateTime

The above example will match any inbound calls sent to extension 3334 and play back a short welcome followed by a verbalization of the date and time. As long as the caller hasn't hung up, the next application will be run and the results played into the channel.

To give an idea of how this works in our mini-phone system, imagine an inbound SIP call is headed towards extension 2001 from extension 2000. Thus, ${EXTEN} would be equal to 2001. Using our example sip.conf file (see below), it shows that any calls coming from extension 2000 should be passed into the context from-sip. When the call is passed into from-sip, the first match statement compares ${EXTEN} against the string "2000". That isn't a match, so the matching process jumps to the next numeric extension definition, which is "2001". In this comparison, it is true that ${EXTEN} equals "2001" -- we have a match! At this point, the priority 1 application is executed, which is "Dial".

If the calling channel still exists and has not been terminated at the end of priority 1, then priority 2 is executed, and so on. If there are no matches for ${EXTEN}, then the user will be sent an "Invalid Extension" result, and most likely will hear a re-order tone (fast busy) that would be generated from their phone.

Wildcards can be used in extension mapping, and match strings beginning with the underscore character (_), meaning that the following portions of the match string include wildcard characters. Commonly used wildcards are N (digits 2-9), X (any digit), . (any number of digits), and a variety of regular-expression matching methods. See the handbook for more detailed explanations of wildcards for matching. A valid example of a wildcarded matching string might be exten => _301.,1,Dial(Zap/1/${EXTEN}), which would match any of the following: 3013, 3015551212, 301543*999.

Much more extensive comparisons can be applied to the matching behaviors: caller ID of calling party, time of day, detection of fax modems, string matching, and more can all be used to determine call flow.

Also, for a quick description of some system variables and conditional expressions, take a look at the file README.variables, which is in the main Asterisk source directory.

No comments: