You've probably heard of Asterisk before. It's one of those buzzed-about open source projects that keeps popping up on O'Reilly and Slashdot. Take our word for it: it's fun stuff. At EchoDitto we run our office phone system on it, have built client applications around it, and even made a version of Tetris for our lobby monitors that runs on it (more on that later).
But getting into Asterisk can seem more intimidating than it really is. There's plenty of documentation around, but a lot of it seems to assume that the reader has just come home from his or her job managing AT&T's fiberoptic backbone and is now hoping to screw around with some open-source fun. In other words, it's written for an audience of VoIP engineers.
Well, none of us are VoIP engineers. If you're like us, you're a general technologist who builds stuff on the web, knows that in five years your toaster will have Ruby bindings, and realizes that There Is No Spoon. You've used Skype and heard of Vonage, but you don't know much about VoIP besides that. And now you'd like to use Asterisk to recreate the final scene in The Lawnmower Man (the director's cut) — or maybe just have your website talk to people over the phone.
We can do that! In fact, it's probably easier than you think. In this post I'll outline how to get up and running with Asterisk, how to connect it to the Plain Ol' Telephone System (POTS) and how to connect it to your programs. From there it's up to you.
Let's start slow. Asterisk is an open source project that works as a Private Branch Exchange, or PBX. A PBX is to the phone system as a LAN is to the internet. You probably already have one in your office for routing calls to different extensions and handling voicemail. It might also provide conferencing capabilities, or provide an IVR system — "press 1 for your balance, press 2 if you lost your card" — that sort of thing. Asterisk can perform all of these functions (and many others).
If you're interested in setting up a PBX for your home or office, you may want to check out the trixbox project, which adds a bunch of useful tools and scripts to an Asterisk installation, including a web frontend for configuring the system. It's what we use for our office PBX here at EchoDitto, and is available as a liveCD so that you can try it out before committing to it.
But the extra stuff that comes with trixbox can make developing Asterisk applications confusing, and (if memory serves) its installer kind of wants the target machine to itself. If you're reading this you're probably just getting started; you want to keep things simple and don't want to commit to anything too drastic. So let's just install a vanilla version of Asterisk.
You can download Asterisk from here. It's been a little while, but my recollection is that it's a very easy installation. Read the docs, but I believe that ./configure && make && sudo make install will pretty well handle things. There weren't any missing dependencies on the Red Hat boxes I've installed it on.
Make sure Asterisk is set to start automatically in /etc/inittab (make sure your runlevels are properly configured):
# Asterisk as:345:respawn:/usr/sbin/asterisk -f
then #/sbin/telinit q to get it started. You should now be able to connect to the Asterisk console from the command line like so:
#/usr/sbin/asterisk -r
If that works, then everything's probably A-OK.
So you've got an Asterisk server. How do you actually connect it to things? Well, first let's figure out what sorts of things you can connect to the server:
Let's test things out a little further — and take this opportunity to enter the exciting world of Asterisk config files (woo!). But first, a note of warning: VoIP does not play nicely with NAT. Is there a router in between you and the Asterisk server? If so, you've got more work ahead of you. Forwarding the port for the SIP protocol (5060) will let command controls move freely between your softphone and Asterisk, but the actual audio is carried via separate RTSP streams. And, to be honest, it can be a nasty business to open the necessary ports properly. For simplicity's sake, my best advice is to either use an Asterisk server on the same LAN as you, or to make your home machine your router's DMZ host — only temporarily, of course, for security reasons. The rest of this tutorial assumes that there isn't any port-opening business to be attended to. If there is, consult portforward.com.
Okay! The first thing to do is to create a new SIP user. It's pretty easy to do: open up /etc/asterisk/sip.conf in a text editor and add this to the bottom:
[test] type=friend allow=all context=demo username=test authname=test secret=test host=dynamic canreinvite=no
This isn't very secure, but for now it'll do. This creates a new user called "test" with password "test" and a default context of "demo", which happens to be a context included with asterisk by default (more on this shortly). We're going to need to tell Asterisk to reexamine the sip.conf file, though. To do this, go to the Asterisk console (#/usr/sbin/asterisk -rvvv) and type "sip reload". Keep an eye out for any parsing errors — if there are some, double-check that you edited sip.conf properly.
Now let's configure a softphone. I'm a fan of SJPhone, since it crashes less on my Intel Mac than X-Lite seems to. But use whatever you'd like — the settings will be similar:
Alright! Hopefully SJPhone will say something like "SIP: registered" in its status window. Enter "s" into the textbox at the top and hit "Dial".
If all is well you should hear a burst of fake-dialing, then a welcome message from Asterisk. We've just dialed the "s" extension in the "demo" context. The extension was defined by entering it in the text box; your user's default context was set in the stuff we added to sip.conf. Feel free to navigate the demo context to see what's available.
You're probably familiar with the idea of an extension. At work, mine's 117. It's probably something similar for you. But what's a context?
Well, there are only so many numbers on a telephone keypad. That's the obvious way to navigate the flow of the dialplan. But in some places you might want, say, the "2" button to mean something different than in another place. For instance, at the start of the call it might mean you want to hear menus in Spanish. Later on in the call it might mean you want to check your balance.
This is where contexts come in. Each line in the dial plan must have a unique combination of context, extension and priority. Think of it like a street address: the context is the town, the extension is the street and the priority is the house number. Here's the "s" extension we just played, straight from /etc/asterisk/extensions.conf:
[demo] ; ; We start with what to do when a call first comes in. ; exten => s,1,Wait,1 ; Wait a second, just for fun exten => s,n,Answer ; Answer the line exten => s,n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message exten => s,n(instruct),BackGround(demo-instruct) ; Play some instructions exten => s,n,WaitExten ; Wait for an extension to be dialed.
There's quite a bit of stuff to unpack here. Let's jump right in:
Here we get to the meat of it. s,1,Wait,1 — what does that mean?
I should also point out that "s" isn't usually defined as a dialable extension. There's no "s" key on the standard telephone, after all. Instead, "s" is frequently used in Asterisk dialplans as the starting extension in a context. There are other special extension names, too: "h" is executed when a call is hung up, "t" fires when the dialplan times out while waiting for input, and so on. You can find a complete list of these special extensions here. You can also use patterns to match ranges of input. You can find more detail on that here.
Hopefully this makes sense. It's possible to include multiple files in your dialplan by placing references to them in /etc/asterisk/extensions.conf. But extensions.conf is where you'll probably want to do your initial exploration. Just as with sip.conf, you need to go to the Asterisk console and type "extensions reload" to get Asterisk to notice your changes.
Have a look around the list of application commands and see what's possible. You might want to try defining some new extensions in a new context and playing around with them. Be sure to change the user's default context in sip.conf to the new one! Naturally, you can also use application commands to jump between contexts and extensions. Hopefully this will all seem familiar to anyone who's programmed in BASIC.
Perhaps the most interesting application command is the one called AGI. This stands for Asterisk Gateway Interface and, like CGI technology, it provides a way to handle Asterisk calls using your favorite scripting language. There are AGI bindings for Perl, Python, Ruby and PHP, to name a few (check out the preceding link to find these projects). Most, if not all of the Asterisk application commands are available in an AGI session, and it's possible to pass Asterisk variables such as the phone number of the caller to the script.
The possibilities opened up by this are enormous. You could make incoming calls send people IM messages. You could connect your Asterisk server to an X10 controller and adjust your lights and thermostat over the phone. You could hit a database and update statistics on a website. The only real limits are your imagination, available hardware, and the phone's admittedly clumsy interface.
The downside to this is that each time you hit an AGI command a new interpreter for your scripting language is spawned, which consumes system resources. If enough of them are spawned it can negatively affect the Asterisk server's performance. This is why you should resist the temptation to simply write off the dialplan and throw every incoming call to a scripting language.
But you still might run into AGI overhead problems if your application includes some AGI and is heavily used. If you do, consider FastAGI, which lets you run those sessions on a separate machine over the network. Projects like Adhearsion aim to make the process even more efficient.
But we're getting ahead of ourselves. We haven't even connected Asterisk to the plain ol' telephone system yet! Let's find a vendor and connect to the POTS.
Actually, I'm going to outsource most of this work. That's because vendors' configurations differ, and most of them will provide customized configuration directives to copy and paste into Asterisk's config files.
As for specific vendors, I like Broadvoice and Vitelity, both of which are very Asterisk-friendly. Broadvoice is aimed at home users. It has extensive Asterisk documentation, but imposes a limit on the number of concurrent channels that can be used (in other words, the number of simultaneous inbound and outbound calls). For that reason I prefer Vitelity, which is oriented toward large VoIP projects that will be making or receiving a lot of simultaneous calls — it's nice to have that freedom. Both vendors offer very low-cost startup options, and will provide you with customized configs to place in sip.conf and extensions.conf.
I believe that Broadvoice will set you up with an inbound number, but with Vitelity you'll have to order one. In VoIP-speak inbound numbers are called "DIDs". They'll run you an additional dollar or two per month, in addition to the traffic that goes to them (which generally costs between 1 and 3 cents per minute). You can make outbound POTS calls without a DID, but not inbound.
So I'll go ahead and assume that you signed up with Vitelity. You updated your configuration files, did a "sip reload" and "extensions reload", and Asterisk's console isn't complaining about any registration errors. When you type "sip show registry" in the Asterisk console you should see something like this:
Host Username Refresh State inbound1.vitelity.net:5060 your_username 45 Registered
"Registered" being the most important part, of course. Additionally, when you dial the DID number on your phone, you should start to see messages scroll past in the Asterisk console. If you alter the context for the vitel-inbound SIP registration (in sip.conf) to point to "demo", you should be able to dial the DID number and get Asterisk's welcoming spiel.
The sound quality of the call is much too large a topic to cover here. But if you experience problems, you'll probably need to ensure that your connection has sufficient bandwidth, low latency and low jitter. Googling around for these terms should help you figure out how to diagnose your problem. You may ultimately need to install a traffic-shaping firewall that prioritizes VoIP packets. Finally, note that Asterisk can use a variety of codecs to encode audio. There's generally a tradeoff between bandwidth, sound quality and processor use that needs to be considered.
But for now you can probably ignore all of that. So congratulations! You're now connected to the public telephone network, with all the rights and privileges that entails.
Okay. You can receive inbound calls. If you've pored over the application command documentation, you've probably even figured out how to make calls to an outside number from an extension (hint: exten => s,n,Dial(SIP/15551234567@vitel-outbound,30,rg)). But what about making your system initiate the call?
It's pleasantly simple, actually. The secret is .call files. These simple text files are placed into a spool directory. Asterisk picks them up, reads them, deletes them, and initiates the call that they specify. Here are the complete contents of a sample .call file:
Channel: SIP/15551234567@vitel-outbound MaxRetries: 0 RetryTime: 300 WaitTime: 15 Context: demo Extension: s Priority: 1 Set: USERID=12345
Let's go line-by-line:
So you place this into a file with a .call extension — temp.call, let's say. You should do this outside the spool directory (/var/spool/asterisk/outgoing), then move the file into it. Asterisk doesn't have systems in place to keep it from trying to read from a half-written file.
Here's some sample PHP code to make a call using Asterisk:
<?php
$handle = fopen("/tmp/temp.call","w");
$contents = "Channel: SIP/" . $_POST['phone_number_to_call'] . "@vitel-outbound
MaxRetries: 0
RetryTime: 300
WaitTime: 15
Context: demo
Extension: s
Priority: 1
Set: USERID=" . $_SESSION['user_id'] . "
";
fwrite($handle,$contents);
fclose($handle);
exec("mv /tmp/temp.call /var/spool/asterisk/outgoing");
?>
Naturally, you might have some filesystem permissions to deal with. But this is the basic shape of it. Define your SIP registrations. Define your dialplan contexts and the extensions that flow through them. Perform fancy integration with AGI. Process incoming calls to your DID by setting its context, extension and priority to the right portion of the dialplan. Make outgoing calls with .call files.
One of the first things you'll likely find yourself wanting to do is play customized audio to the user. This can be easily accomplished with the Playback application command (there are a few other relevant ones, too). But getting the audio files into a readily-usable format can be harder. This page provides a good starting point. The short version: you're going to want to convert your WAV files into .gsm or (preferably) .sln files using the sox utility.
As for voice synthesis: there are a few text-to-speech libraries that can be plugged into Asterisk, such as Flite. I've had a hell of a time getting them configured, though (except under Trixbox, which comes with them built-in). If you run into the same trouble I did, you can always use AGI to generate and convert the audio you need on-the-fly using command-line tools like text2wave and sox. You'll need to be wary of efficiency problems, and will want to cache whenever possible. It also may sound abysmal. But it'll work in a pinch.
Finally, let me recommend Nerdvittles.com, an Asterisk-heavy tech blog. Phil turned me on to it, and it's really got a lot of excellent Asterisk-related content. You may also want to check out the various Asterisk-related channels on irc.freenode.net.
Whew... I think that's it! My sincere apologies for any errors, misunderstandings or gross oversimplifications above — as I said, I'm just an generalist web guy who's muddled his way through this stuff. But with the techniques outlined above and a little time in the documentation, odds are good that you'll be able to hack together something cool. The barrier to entry is very low: a Linux box, an internet connection and $10 are about all you'll need. Happy hacking, and let me know if you put together anything particularly neat.
I'll try to install the
I'll try to install the asterisk too and for that I will use this steps.
Post new comment