Saturday, April 3, 2010

Asterisk vs. FreeSWITCH - This Again? Really?

Sigh. Yet another blogger who thinks that there's some sort of knock-down, drag-out fight between Asterisk and FreeSWITCH. I'll get to that in a minute. First, though, let me give you the quick version of my background so that my biases are clearly enumerated before I give my opinion.

As some of you may know, I work with the FreeSWITCH team. I've been working officially with them for about 18 months. Prior to that I was a relatively active volunteer member of the community for at least another 18 months. Prior to that I had been watching both FreeSWITCH and Asterisk since 2006. That's roughly four years of watching both projects, with using Asterisk heavily at first and then a gradual shift over to FreeSWITCH. When I first heard of Asterisk, I thought, "Awesome! An open source PBX!" (I was an NEC PBX technician for five years in the 1990's and then went to work for a call center for nearly 10 years as the IT and "phone guy" and key/PBX systems are a passion of mine.) I didn't actually try it out until I happened to see the starfish book - TFOT as it's come to be known. I bought it immediately and jumped right in. I'm like many OSS supporters: when someone goes through the trouble of producing "dead tree" documentation for an OSS project then that project must be gaining traction. (Shameless plug: I am writing a FreeSWITCH book with Anthony Minessale and Darren Schreiber for Packt Publishing - watch for it later this year.)

I played a lot with it, joined the Asterisk mailing list and even convinced my then boss to let me buy a four-port T1 card so that I could experiment with PRI lines and connecting to our NEC 2400 PBX. It was a lot of fun, until... CDRs. At that time, Asterisk CDRs were the stuff of nightmares. (Are they still? I don't know - I'll leave that to those who use it in production.) It was about this time that someone - Douglas Garstang, IIRC - was ranting pretty heavily about his own woes with Asterisk. Of course, he was doing this on the Asterisk mailing list and more than a few feathers were ruffled. Trollish behavior aside, he mentioned two syllables that would eventually change my life: FreeSWITCH. I had never heard of it. Of course, this was right around the time with the drama of the OpenPBX/CallWeaver fork. I was new to Asterisk and VoIP and I found this all very confusing. Asterisk seemed so awesome! Why were there those who forked it and those who abandoned it? I didn't know, but I kept learning as much as I could. I checked out FreeSWITCH in the very early days, long before people were using it in production. My impression was simple: it's going to be an awesome project someday, but I can't use it right now. I couldn't use it for the projects I was working on because they all required TDM hardware support. Still, I couldn't help but think that the FreeSWITCH guys were on to something, so I signed up for the mailing list and decided to check in every now and then. In the meantime I kept on tinkering with Asterisk.

Fast-forward to May, 2007. The FreeSWITCH guys created OpenZAP - a TDM hardware abstraction layer. Excellent! Now I could try out FreeSWITCH with my projects. I jumped in with both feet and this is where I really began to learn about the differences between the two projects. I guess I was among the first persons to try using FreeSWITCH with a PRI carrier. I thought I was driving Anthony and Mike Jerris nuts with all of my questions but not only were they patient with me, they expressed appreciation for my efforts to get TDM working with FreeSWITCH and my efforts to document everything that I learned. And learn I did! It was crazy and fun learning all about FreeSWITCH and diving into Q.931 spec docs from AT&T and the ITU. The next year was very educational. The next thing I knew I was at ClueCon 2008 meeting all of these guys in person! I also met Allison Smith, "the voice" of Asterisk. I met Jim van Meggelen. It was a bit overwhelming at first, but everyone was down-to-earth and friendly. Brian K. West has especially helpful, taking me under his wing and showing me around. (He still does, and I love every minute of it! Thanks, Brian! You are an awesome guy who knows more about VoIP and networking than pretty much anyone I've ever met.) By the end of 2008 I was working with the very same guys whom I thought of as rock stars: Anthony, Brian, Mike. I am still working with those great guys today. Too cool.

Pardon the tangent, but that puts this post in perspective. I've spent a lot of time over the past few years with the core FreeSWITCH team. I think my viewpoint of their feelings on the matter of "Asterisk vs. FreeSWITCH" is pretty accurate. That's why I feel it is necessary to comment on the aforementioned blog post by "kallaje" over at simplymentos.wordpress.com. I'll restrict my comments here to the information he presents as factual. I'll do my best to present "our" side's viewpoint. I can't be unbiased but I will do my best to be reasonable. Here goes.

This is the most sought after topic in the history of Telecom industry I suppose.


I have to assume this is hyperbole. If it isn't then the rest of his post really is just the rantings of an uninformed lunatic.


These 2 factions for some reason, I cant understand, are dividing the telecom world.

Wow. We're factions and we're "dividing the telecom world"? I didn't realize that our respective projects were so incredibly important! I'd like to find out what, exactly, precipitated this comment. (More hyperbole perhaps?)


One claiming superiority over the other.

I don't know that either side has ever "claimed superiority" over the other. I do know that many FreeSWITCH users are Asterisk "refugees" who simply wanted or needed a different solution to meet their VoIP needs. As you'll find out in the upcoming FreeSWITCH book, Anthony lobbied for the creation of "Asterisk 2.0" but was met with a range of reactions ranging from ambivalence to hostility. I suppose you could say Anthony Minessale is "Asterisk refugee zero." He started FreeSWITCH, not because he hated Asterisk, but because he wanted Asterisk to be able to do much more than what was available in 2005. We're now in 2010. FreeSWITCH 1.0.5 is about to be released and it is incredible. Is it "superior" to Asterisk? That's a ridiculously subjective question, and an irrelevant one as well. No one on the FreeSWITCH team is out there claiming that FreeSWITCH is "better" or "superior" to Asterisk. What they are saying is that there are many things that FreeSWITCH can do that Asterisk cannot. (Examples: multiple UAs, mix calls to/from any codec and sampling rate, supports sampling rates of 8k, 12k, 16k, 24k, 32k, and 48kHz.) FreeSWITCH being able to do something that Asterisk cannot (or vice versa) is not a claim of superiority. Also, I still subscribe to the Asterisk mailing list. I haven't seen or heard anyone from Digium making any claims about Asterisk being "superior" to FreeSWITCH. I have no idea where this crazy statement came from.


I think both are equally good but differ in the purpose they serve and whom they serve.


Ah, finally a statement that doesn't have me pulling my hair out. The expression "equally good" is very subjective, but that's not the important part of this sentence. Rather, the statement that the projects "differ in the purpose they serve and whom they serve" is key. It is 100% correct. Oh, and kudos for using "whom" correctly and not "who." I wish the blog post consisted of only this sentence because it is the high point of the entire post.


The differentiation is in the number of concurrent call handling and that makes all the difference for choosing one over the other!!!

Yes and no. Yes, FreeSWITCH can ostensibly "handle more calls" than Asterisk. However, Asterisk has been making strides in this area. Olle E Johansson reports that there is a large Asterisk installation that is surpassing 10,000 concurrent calls. Anthony and Brian have experimented with a FreeSWITCH server handling 20,000 calls, but at some point you have to ask, "Why?" and just move on to a different problem. Just because you can put 10K calls on a single box doesn't mean you should. The bottom line is that FreeSWITCH is a soft-switch and Asterisk is an IPPBX. They have lots and lots of overlapping functionality. They each do things the other doesn't. No big deal there. My take on this is simple: use what works for you, regardles of how many calls you need to handle on a single machine.


...but SMB’s must not invest in Windows…


I'm no Windows fan but I don't know that SMB's "must" avoid Windows no matter what. I came from a place that had 100+ Windows XP machines and they worked really well for us. That being said, I do prefer Linux for pretty much all of my server needs. However, many others out there use Windows 2003 and 2008 Server edition with FreeSWITCH and report good success. Like we said before: use what works for you.


Freeswitch [sic] is not simple.


That's a bit of a straw man. Of course, FreeSWITCH isn't "simple." Why? BECAUSE VOIP IS NOT SIMPLE!!! Hello? Have you read all the SIP RFC's out there? Have you seen all the crazy NAT devices and evil SIP ALG's in various products? On the other hand, I suppose you could say that the power of a platform is inversely proportional to it's simplicity. Translation: FreeSWITCH is really powerful.


It’s [sic] SIP Stack is too robust to debug or understand.

Huh? How can a SIP stack be too robust? FreeSWITCH currently uses the Sofia SIP library from Nokia. It's pretty robust. As for not being able to be understood or debugged - what full-featured SIP stack is non-robust enough to debug or understand? Is this person really saying that chan_sip.c is easy to debug or understand? Has he seen the bug reports in Mantis?


Its 407 authentication always nullifies your Avaya trunk.

Perhaps Avaya should actually follow the RFC's and not bastardize SIP the way so many others do. SIP is complicated enough without all of the vendors making their own goofy little quirks and additions.


Its [sic] not a good test platform.


Wrong. It's a great test platform! The FreeSWITCH devs don't pander to those wanting dirty hacks in order to gain interoperability with vendors who choose to cut corners or play fast and loose with the RFCs. If your stuff works with FreeSWITCH then chances are that your stuff really does follow the RFCs. There are some exceptions, of course. Classic example is Sonus and their DTMFs. If you want the sordid details then check this out.


It is too scalable to be handled by a single person.


Except for the hundreds of single persons who use it and administer FreeSWITCH-based VoIP systems every day. I don't have any clue where that statement came from.


Freeswitch [sic] is superb for programmers who really like doing something on the cloud, with Vitelity or Amazon EC2. Great return on investment guaranteed.


I'd have to agree with this. We have many users who like to do stuff in the cloud.


The best part? Its MPL license…. What more do we need as application integrators and designers…. All in a single product.


I generally agree with these statements as well. However, I don't agree that FreeSWITCH doesn't scale down very well. It scales down really well, so well, in fact, that there is a new soft-phone project that will use FreeSWITCH as the telephony engine.


Freeswitch [sic] can never even be managed for a small SMB...If you want to scale Freeswitch [sic] to SMB scenario, then it only means, you need hire someone.


We have hundreds of happy users who would completely disagree with these assertions. However, we don't discourage enterprises from hiring in-house talent to take care of their telecommunications infrastructure. VoIP and FreeSWITCH take time to learn. Frankly, so does Asterisk. The mere presence of voip-info.org is no panacea for curing all the ills one faces when deploying Asterisk. All VoIP systems have some level of complexity and a learning curve. FreeSWITCH is at the high end: lots of power, lots of options, lots of time and effort needed to learn the ins and outs. However, if you download and build FreeSWITCH with its default configuration you will have a simple soft PBX that "just works." In an hour you can be using and learning FreeSWITCH.


When I say, Freeswitch [sic] is difficult to use, I am taking into account the number of resources, help available in the web to do it as well. Its [sic] really really poor.


I would have to disagree with this. FreeSWITCH has a vibrant online community, including an IRC channel and several mailing lists. The three main developers answer questions on both email and IRC pretty much every day. When was the last time Mark Spencer answered a question on email or hung out in #Asterisk to help new users? As far as other resources, yes I understand the challenges. That's why we're writing a book as well as revamping the wiki. I am doing much of this work on my own so it is going slowly, but it definitely is going. The FreeSWITCH wiki does have lots of information, however some of it is really hard to find. We are aware of that and are working on it. (Volunteers welcome, BTW!)


Freeswitch [sic] must remove their big Advertising on Asterisk v/s Freeswitch and focus more on what they are good at.


I just googled "Asterisk vs FreeSWITCH" and mostly everything I found was written by other people. The only thing that we have is "node 117" which is a post that Anthony wrote in response to repeated requests from people who wanted to know the differences between Asterisk and FreeSWITCH. Although the link on the main page (upper left corner) for node 117 says "FreeSWITCH vs. Asterisk" that does not mean the two projects are in some sort of cage match. It simply means, "How does FreeSWITCH compare to Asterisk?" As for this "big advertising" campaign about Asterisk vs. FreeSWITCH - I simply can't find any evidence that it even exists.


They might have been good in blaming before, but its [sic] time to move on and grow up
.

I don't know who was being "blamed" by the FreeSWITCH dev team nor have I heard them "blame" anyone. I don't know what the author is really trying to say. Perhaps he could explain this statement because it seems just plain wrong to me.

Well, those are the comments he made that I wanted to address. As for the state of "us vs. them" here are my personal thoughts. Is there hatred, animosity, and bad blood between the two projects? Absolutely not. Is there some good-natured ribbing going on? Of course! What about the disagreement between Anthony and some of the core Digium guys? Isn't there some bad blood there? Perhaps. But even if there is, does it really matter? Just because two guys have a disagreement doesn't mean that their two projects represent "two factions that are dividing the telecom world." They are simply two different OSS telephony projects with some overlapping functionality.

The bottom line is rather uncomplicated. The FreeSWITCH developers have a very simple motto: use what works, be it FreeSWITCH, Asterisk, YATE, OpenSIPS, Kamailio, or some combination thereof. That's one of the beautiful things about FOSS - you can try them all and pick the one that works for your scenario. Your choice may be different than mine, and I have no problem with that. You may love Asterisk and I may love FreeSWITCH but that doesn't mean we have to be adversaries. So please, no more "Asterisk vs. FreeSWITCH" diatribes. We've all got better things to do.

Wednesday, October 28, 2009

Using mod_xml_curl In FreeSWITCH - How Hard Can It Be? (Part 2)

In my previous post I talked about my desire to go through the exercise of setting up xml_curl to pull user directory information out of a database. I left off having just verified that I was receiving proper CGI parameters. I first tested a dialplan call using portaudio to call the MOH extension:

pa call 9999

This yielded good results: my Perl script dumped the CGI params to a text file and I got a good feel for what data looks like coming from an xml_curl request.

Next I needed a way to send information back to xml_curl/FreeSWITCH. I recalled some talk about sending a generic "no found" response. Sure enough, the wiki confirms it. I added a simple function to my perl script that would reply to xml_curl and would dump the "no found" message to my log file also:


sub return_not_found() {
print "Content-Type: text/xml\n
<?xml version=\"1.0\"?>
<document type=\"freeswitch/xml\">
<section name=\"result\">
<result status=\"not found\" />
</section>
</document>
";

## dump to file for checking
print FILEOUT "Content-Type: text/xml\n
<?xml version=\"1.0\"?>
<document type=\"freeswitch/xml\">
<section name=\"result\">
<result status=\"not found\" />
</section>
</document>
";
}


A simple call to &return_not_found() will gracefully handle the situation where my CGI script has no useful information to send back. At this point I did a quick test and had the CGI script send the no found info back on any xml_curl request just to make sure it was working. It did.

Next up: having a phone register so that I could see what a 'directory' request looks like. In this case you could use any SIP device that tries to REGISTER, even another FS box with a gateway defined. I found a Snom 300 that I have in production and added a second identity. (The first identity is being used in production so I didn't want to mess with it.) I added "Tony Romo" as the second identity on the phone, with the account and auth. user as "1100" and the appropriate password from my database file. I watched on the FS CLI to make sure that the phone tried to register, then I went to my script's log file to see what the request looked like. It was a bit shorter than the 'dialplan' request but it definitely had useful information:


bless({
".charset" => "ISO-8859-1",
".fieldnames" => {},
".parameters" => [
"hostname",
"section",
"tag_name",
"key_name",
"key_value",
"Event-Name",
"Core-UUID",
"FreeSWITCH-Hostname",
"FreeSWITCH-IPv4",
"FreeSWITCH-IPv6",
"Event-Date-Local",
"Event-Date-GMT",
"Event-Date-Timestamp",
"Event-Calling-File",
"Event-Calling-Function",
"Event-Calling-Line-Number",
"action",
"key",
"user",
"domain",
],
"Core-UUID" => ["9b4e5fe9-9bc9-4bed-915a-3c277cbd760b"],
"Event-Calling-File" => ["mod_voicemail.c"],
"Event-Calling-Function" => ["resolve_id"],
"Event-Calling-Line-Number" => [1278],
"Event-Date-GMT" => ["Thu, 29 Oct 2009 17:00:15 GMT"],
"Event-Date-Local" => ["2009-10-29 10:00:15"],
"Event-Date-Timestamp" => ["1256835615546212"],
"Event-Name" => ["GENERAL"],
"FreeSWITCH-Hostname" => ["michael-collinss-macbook-pro.local"],
"FreeSWITCH-IPv4" => ["10.15.0.136"],
"FreeSWITCH-IPv6" => ["::1"],
action => ["message-count"],
domain => ["10.15.0.136"],
escape => 1,
hostname => ["michael-collinss-macbook-pro.local"],
key => ["id"],
key_name => ["name"],
key_value => ["10.15.0.136"],
section => ["directory"],
tag_name => ["domain"],
user => [1100],
}, "CGI")


The values I was particularly interested in were 'section' and 'user' which had "directory" and "1100" as their respective values. I knew I was in business! I added a little bit of logic to my script so that I could differentiate between a 'dialplan' and 'directory' request. The relevant tidbits look like this:

my $q = CGI->new;
my $section = $q->{'section'}->[0];

if ( $section eq 'directory' ) {
SNIP
} elsif ( $section eq 'dialplan' ) {
SNIP
} else {
## We don't anything other than dialplan or directory, so if we're here then return a no found
open(FILEOUT,'>','/tftpboot/cgidat.txt');
print FILEOUT "\n\n--- UNKNOWN REQUEST ---\n";
print FILEOUT "\nSection: $section\n\n";
print FILEOUT dump($q);
print FILEOUT "\n = = = = = = = = = = = = = = = = = = = = = = =\n";
&return_not_found();
close(FILEOUT);
}

Okay, so at this point I have a basic script that knows the difference between a 'directory' and a 'dialplan' request and can return a no found message if need be. Now I needed to tackle the database stuff.

DBI: Perl's Handy Dandy DataBase Interface
When you have a Perl question there's always one place you can go: the CPAN. I had used DBI before, although I can't recall exactly when/where/how. But I did remember that it wasn't really all that difficult for simple stuff. After some digging around I found this code:


use DBI;
my $dbh;
$dbh = DBI->connect('dbi:Pg:dbname=xml_curl_test;host=127.0.0.1', 'xmlcurl', 'freeswitch',
{ RaiseError => 1, AutoCommit => 1});


In short, this creates a db handler object ($dbh) upon which you can do SQL operations. Let's take a quick look at part of the connection string:

DBI->connect('dbi:Pg:dbname=xml_curl;host=127.0.1','xmlcurl','freeswitch'

The connect uses the format of DSN, user, password. My DSN is for 'Pg' (PostgreSQL) with a dbname of xml_curl and the local host. My user is 'xmlcurl' with a password of 'freeswitch'. The other stuff - { RaiseError => 1, AutoCommit => 1} - is recommended in the DBI docs so I roll with it.

My SQL call looks like this:

my $sql = "SELECT lastname, firstname, mailbox, password, context FROM users WHERE username = '$user'";
my $row = $dbh->selectrow_hashref($sql);


This makes the SQL query and puts a single row of results into a hash reference $row. From here I can access the results like this:

$row->{'context'};
$row->{'password'};


I like this because I don't have to remember what column number each field is, instead I simply reference the name of the column. In my case I'm assuming that I have only a single row of results; you probably want to do some error checking on a production system.

The last order of business is to format some XML and give it back. Since I'm just doing a POC I decided to cheat and use a string with some placeholders and then swap them out. Here's my template definition:


## User template variable; replace the ALL CAPS VALUES with stuff pulled from database
use constant USER_TEMPLATE =>
' <user id="USER_ID">
<params>
<param name="password" value="USER_PASS"/>
<param name="vm-password" value="USER_PASS"/>
</params>
<variables>
<variable name="toll_allow" value="domestic,international,local"/>
<variable name="accountcode" value="USER_ID"/>
<variable name="user_context" value="USER_CONTEXT"/>
<variable name="effective_caller_id_name" value="USER_FIRSTNAME USER_LASTNAME"/>
<variable name="effective_caller_id_number" value="USER_ID"/>
<variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/>
<variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/>
<variable name="callgroup" value="techsupport"/>
</variables>
</user>
';


The items in all caps will get replaced with some simple regular expressions. Stay tuned for Part 3 where I show you the entire script. It's not pretty but it is functional and it took me all of an hour to get everything together. It's taken much longer to blog it all and figure out how to format XML code so that it looks right. ;)

Using mod_xml_curl In FreeSWITCH - How Hard Can It Be? (Part 1)

I've been playing with FreeSWITCH for more than three years. In all that time I've never really had a good reason to use mod_xml_curl. Until now, that is. The good reason is nothing more than my own edification. I like to answer questions on the mailing list and finally I got sick of telling people to use xml_curl without having used it my self.

MOD_XML_CURL: The Magic Module For Dynamic FreeSWITCH Configuration
Okay, here's a quick overview of mod_xml_curl: it's a module in FreeSWITCH that allows parts of the FreeSWITCH configuration to be fetched from a web server that can, in turn, grab the configuration information from a database (or anywhere else for that matter). The primary ways to use xml_curl are for the dialplan and the user directory, but you can also use it for configuration options and for phrase macros. The specific question on the mailing list was about pulling user information from a database, so that's where I decided to start.

NOW WHAT?
I've read about it, I've heard people talk about it, I know lots of people who use it, but I've never done it myself, so the first question I had to answer is this: what do I do first? Well, the specific question was about pulling user information from a database, so I decided the first thing to do would be to look at the sample XML files in the default configuration to get an idea of what kind of XML config stuff I would need to generate and send back to FreeSWITCH. I also poked around in the contrib folder to see what others had done. Finally, I consulted the oft-maligned but generally underappreciated FreeSWITCH wiki. Amazingly, with just these meager resources I was able to get a POC working in just a few hours. Now mind you, I did this in my spare time while avoiding my wife and kids, and with limited resources. (I don't have a stack of VoIP phones on my home LAN like some of you people do.)

BTW, I'm not a Web-programming guru, nor am I a database admin. I'm familiar with these from having tinkered with some LAMP setups. I'm decent with Linux, decent with Apache, decent with MySQL, and somewhat advanced with Perl. Small problem: I don't have MySQL on my laptop which is where I needed to run everything. However, I had installed PostgreSQL version 8.3 for another project. I know almost nothing about PG. Fortunately, I had Mr. William King (quentusrex on IRC - #freeswitch on irc.freenode.net) around and he gave me a few pointers. ("In MySQL I did it this way, how do I do that in PG?") A tip o' the cap to him. So at this point I was all set.

My configuration at the start looked like this:
MacBook Pro with OS X Leopard
Latest SVN of FreeSWITCH
Apache 2.2
Perl 5.8.8
PostgreSQL 8.3

So the first thing I decided to do was create a new database in PG, then create a users table. With William's help and the handy pgadmin3 program I was in business. For kicks, I went back to my table and added an extra column: context. I didn't need this column but I thought it would be a nice little exercise to add this value for each user even though I would usually just want "default" for the context. My table ended up looking like this:

CREATE TABLE users (
uid bigserial NOT NULL,

lastname character varying(15),
firstname character varying(15),
username character varying(11) NOT NULL,
mailbox character varying(11) NOT NULL,
"password" character varying(11) NOT NULL,
context character varying(11) DEFAULT 'default'::character varying,
CONSTRAINT users_pk PRIMARY KEY (uid)
)

Here's a nice little pic of the data I put in there thanks to the "edit data" widget in pgadmin3:

I put first and last names in separate fields because I figured that would be common in a real world scenario. I have the username field which is what I'm kinda using for everything: userid, auth. username and username. (Yeah, I'm cheating, get over it.) I have also a password and a context field. That's it. At this point I was feeling confident. I had the database, a users table, a login role for accessing the database, and a little momentum on my side.

Now I needed to decide which task to handle next: handling the CGI call or figuring out how to query the database. I decided to tackle what I felt was the tougher of the two: handling the xml_curl call and returning information that FreeSWITCH could use. It turns out that it wasn't actually all that tough: I opened up conf/autoload_configs/xml_curl.conf.xml and found this near the top:

<!-- The url to a gateway cgi that can generate xml similar to what's in this file only on-the-fly (leave it commented if you dont need it) -->
<!-- one or more |-delim of configuration|directory|dialplan -->
<!-- <param name="gateway-url" value="http://www.freeswitch.org/gateway.xml" bindings="dialplan"/> -->


I'm no genius but to me that's pretty clear information: I needed a 'binding' for directory. For kicks I left in the 'directory' binding as well. I ended up with this:

<param name="gateway-url" value="http://127.0.0.1/cgi-bin/xmlcurl_sample.pl" bindings="directory|dialplan"/>

I saved everything, started up FS and promptly realized that I didn't actually build mod_xml_curl. No worries. A quick trip to the FS source directory did the trick:

cd /usr/src/freeswitch.trunk
make mod_xml_curl-install

Gotta love FreeSWITCH - way easy. (I added mod_xml_curl to modules.conf and modules.conf.xml so that it would auto build and auto load, respectively.) I loaded up mod_xml_curl and saw no errors or warnings. I saw that it added a new app named "xml_curl" so I looked at the syntax. (Just type 'xml_curl help' to see the syntax.) Basically it just allows you to turn on debug for xml_curl, which dumps a copy of the information returned from the webserver when xml_curl makes a call. The FS CLI shows the file name and path when it creates this debug file.

The next order of business was to observe what my CGI script would see in terms of information coming from xml_curl. Ah Perl, my lovely Swiss-army chainsaw. That was easy:

#!/usr/bin/perl
#
# xmlcurl_sample.pl
#
use strict;
use warnings;
use Data::Dump qw(dump); # I prefer this to Data::Dumper
use CGI.

my $q = CGI->new;
open(FILEOUT,'>','/tmp/cgidump.txt'); ## look in this file to see what's up
print FILEOUT dump($q);
close(FILEOUT);

But where to put this lovely file? I poked around to find my default Apache configs and it turns out that there's an alias for "cgi-bin" so that's where I put my Perl script to handle the CGI call. That's it. Now I can see what's coming in. All I need to do is make a phone call or have a user try to register to FS. (Recall that I set up an xml_curl binding for both 'directory' and 'dialplan'.) Dialing out was easier since I didn't have a phone handy. Naturally since my script didn't return anything useful there were errors on the FS CLI, but I was more interested in what was in my cgidump.txt file:

bless({
".charset" => "ISO-8859-1",
".fieldnames" => {},
".parameters" => [
"hostname",
"section",
"tag_name",
"key_name",
"key_value",
"Event-Name",
"Core-UUID",
"FreeSWITCH-Hostname",
"FreeSWITCH-IPv4",
"FreeSWITCH-IPv6",
"Event-Date-Local",
"Event-Date-GMT",
"Event-Date-Timestamp",
"Event-Calling-File",
"Event-Calling-Function",
"Event-Calling-Line-Number",
"Channel-State",
"Channel-State-Number",
"Channel-Name",
"Unique-ID",
"Call-Direction",
"Presence-Call-Direction",
"Answer-State",
"Channel-Read-Codec-Name",
"Channel-Read-Codec-Rate",
"Channel-Write-Codec-Name",
"Channel-Write-Codec-Rate",
"Caller-Dialplan",
"Caller-Caller-ID-Name",
"Caller-Caller-ID-Number",
"Caller-Network-Addr",
"Caller-Destination-Number",
"Caller-Unique-ID",
"Caller-Source",
"Caller-Context",
"Caller-Channel-Name",
"Caller-Screen-Bit",
"Caller-Privacy-Hide-Name",
"Caller-Privacy-Hide-Number",
"variable_channel_name",
"variable_endpoint_disposition",
"variable_read_codec",
"variable_read_rate",
"variable_write_codec",
"variable_write_rate",
"variable_zrtp_secure_media",
"variable_playback_seconds",
"variable_playback_ms",
"variable_playback_samples",
"variable_current_application_data",
"variable_current_application",
"Hunt-Dialplan",
"Hunt-Caller-ID-Name",
"Hunt-Caller-ID-Number",
"Hunt-Network-Addr",
"Hunt-Destination-Number",
"Hunt-Unique-ID",
"Hunt-Source",
"Hunt-Context",
"Hunt-Channel-Name",
"Hunt-Screen-Bit",
"Hunt-Privacy-Hide-Name",
"Hunt-Privacy-Hide-Number",
],
"Answer-State" => ["answered"],
"Call-Direction" => ["inbound"],
"Caller-Caller-ID-Name" => ["FreeSWITCH"],
"Caller-Caller-ID-Number" => ["0000000000"],
"Caller-Channel-Name" => ["portaudio/9999"],
"Caller-Context" => ["features"],
"Caller-Destination-Number" => ["is_zrtp_secure"],
"Caller-Dialplan" => ["XML"],
"Caller-Network-Addr" => ["192.168.1.110"],
"Caller-Privacy-Hide-Name" => ["false"],
"Caller-Privacy-Hide-Number" => ["false"],
"Caller-Screen-Bit" => ["true"],
"Caller-Source" => ["mod_portaudio"],
"Caller-Unique-ID" => ["718c69cd-48cf-4701-90b1-ab2e471cfb6d"],
"Channel-Name" => ["portaudio/9999"],
"Channel-Read-Codec-Name" => ["L16"],
"Channel-Read-Codec-Rate" => [8000],
"Channel-State" => ["CS_EXECUTE"],
"Channel-State-Number" => [4],
"Channel-Write-Codec-Name" => ["L16"],
"Channel-Write-Codec-Rate" => [8000],
"Core-UUID" => ["9b4e5fe9-9bc9-4bed-915a-3c277cbd760b"],
"Event-Calling-File" => ["mod_dialplan_xml.c"],
"Event-Calling-Function" => ["dialplan_xml_locate"],
"Event-Calling-Line-Number" => [368],
"Event-Date-GMT" => ["Thu, 29 Oct 2009 05:18:05 GMT"],
"Event-Date-Local" => ["2009-10-28 22:18:05"],
"Event-Date-Timestamp" => ["1256793485008872"],
"Event-Name" => ["REQUEST_PARAMS"],
"FreeSWITCH-Hostname" => ["michael-collinss-macbook-pro.local"],
"FreeSWITCH-IPv4" => ["10.15.0.136"],
"FreeSWITCH-IPv6" => ["::1"],
"Hunt-Caller-ID-Name" => ["FreeSWITCH"],
"Hunt-Caller-ID-Number" => ["0000000000"],
"Hunt-Channel-Name" => ["portaudio/9999"],
"Hunt-Context" => ["features"],
"Hunt-Destination-Number" => ["is_zrtp_secure"],
"Hunt-Dialplan" => ["XML"],
"Hunt-Network-Addr" => ["192.168.1.110"],
"Hunt-Privacy-Hide-Name" => ["false"],
"Hunt-Privacy-Hide-Number" => ["false"],
"Hunt-Screen-Bit" => ["true"],
"Hunt-Source" => ["mod_portaudio"],
"Hunt-Unique-ID" => ["718c69cd-48cf-4701-90b1-ab2e471cfb6d"],
"Presence-Call-Direction" => ["inbound"],
"Unique-ID" => ["718c69cd-48cf-4701-90b1-ab2e471cfb6d"],
escape => 1,
hostname => ["michael-collinss-macbook-pro.local"],
key_name => [""],
key_value => [""],
section => ["dialplan"],
tag_name => [""],
"variable_channel_name" => ["portaudio/9999"],
"variable_current_application" => ["execute_extension"],
"variable_current_application_data" => ["is_zrtp_secure XML features"],
"variable_endpoint_disposition" => ["ANSWER"],
variable_playback_ms => [0],
"variable_playback_samples" => [0],
"variable_playback_seconds" => [0],
variable_read_codec => ["L16"],
variable_read_rate => [8000],
variable_write_codec => ["L16"],
variable_write_rate => [8000],
"variable_zrtp_secure_media" => ["true"],
}, "CGI")


Looking closely you can probably guess that I just used the pa (portaudio) command to dial 9999. I was in business! That's all for part 1 of this subject.

To recap: I thought I would try setting up a proof-of-concept script for using mod_xml_curl in FreeSWITCH. I already had Apache, Perl, and PostgreSQL installed on my laptop, and the latest FreeSWITCH SVN. I configured xml_curl.conf.xml to call my CGI script: xmlcurl_sample.pl. I did a very simple data dump of the params sent into the script from xml_curl. This allowed me to verify that communications from xml_curl to my CGI script were functional.

In part 2 I'll talk about sending a response back to the server and setting up the DBI to query a database.

Sunday, October 25, 2009

VoIP: Why You Should Try FreeSWITCH

VoIP is here to stay. Do a google search on "PBX" or "telephone system" and you'll see there's no going back to the TDM-only days. I'm an old-school PBX guy and I can definitely see the writing on the wall. I actually like TDM, but the advantages of VoIP are just too hard to ignore or dismiss.

So, you want to get into VoIP, but you aren't sure where to begin. There are lots of products out there claiming to be "what you need." Of course, you may not know exactly what you need. Do you need a PBX? A soft-switch? An application server? Something else? It's hard to know when you're just getting started. Even if you've already started down the path with a particular piece of software (or hardware for that matter) there's something you need to know about: FreeSWITCH.

Before I continue, let me just say that I am a bit of a fanboy. I am certainly biased. If you can look past my obvious homerism and think about what FreeSWITCH can do for you then I think you might be pleasantly surprised. FreeSWITCH is extremely scalable and versatile. It is designed to meet many different needs. So, what exactly is FreeSWITCH?

FreeSWITCH is a cross-platform, scalable soft-switching library. In other words, it can be embedded in other software, like .so or .dll files are. Yes, it runs on Windows. It runs reasonably well, I might add. Most people don't embed FreeSWITCH in their own software but instead run the "freeswitch" application. This is like the difference between cURL (the program) and libcurl (the underlying software library). The default FreeSWITCH install is a simple but powerful PBX. However, it can scale up or down. For example, you can use it as a soft-phone or a soft-switch. Since it is a telephony switching engine that can scale you can use it in many forms. I use it as a soft-phone on my laptop. (I find it to be much more stable than Ekiga.) There are others who use it as a carrier class soft-switch serving many thousands of customers. FreeSWITCH will scale with your hardware, so you can use it as you see fit.

The scalable nature of FreeSWITCH helps you. You want to get into VoIP but don't know exactly what you need? FreeSWITCH can scale to meet your needs. It's a great choice for a telephony platform. So if you want to build a SOHO PBX or a large-scale enterprise PBX or a VoIP-PSTN gateway then FreeSWITCH can help. So what can't it do? FreeSWITCH operates as a back-to-back user agent (B2BUA) which means that it is not designed to act as a SIP proxy. Instead, it is meant to complement a SIP proxy. (If you need a SIP proxy then stick with OpenSIPS or one of its cousins.)

One thing that FreeSWITCH does very well is handling media. It can handle audio streams at 8kHz, 16kHz, 32kHz, and 48kHz. It can handle numerous codecs, including some really nice HD codecs like Polycom's Siren(tm) codecs or the fantastic CELT. Best of all, it can bridge audio streams from any codec/sampling rate to any other codec/sampling. I know that may not sound like a big deal, but just try it with other systems. Try having 20 people in a single conference where they are all calling in with different codecs and sampling rates and see how well they can hear each other. I don't know of any other system that can handle sampling rates above 16kHz. FreeSWITCH will go up to 48kHz. If you have a good headset and ear phones then the high definition codecs sound incredible. (Once you go HD voice you will never want to go back to standard 8kHz analog phone lines or worse, GSM cell phone quality calls.)

FreeSWITCH is extremely well-designed and is very stable. It can scale far beyond its competitors on the same hardware. While 10,000 call legs on Asterisk was prize-worthy (see the Asterisk S-Prize) the FS devs were playing around with 20,000 call legs just for fun. They long ago found out the levels where the number of UDP ports runs out as well as how easily they could saturate a 100MB Ethernet connection. Bragging rights aside, the number of concurrent calls on a single box isn't that great a measurement of how awesome your telephony platform really is. Just because you can run 16,000 call legs on one box does not mean you should, at least not in production. One hiccup taking out 8,000 calls is probably not good for business.

FreeSWITCH is configured with XML files, or with a back-end database that serves XML configuration information. This is very scalable - one can have multiple FreeSWITCH boxes receiving configuration information from a redundant db cluster. FreeSWITCH is very modular, and in the XML configuration you can enable or disable various modules. Don't need a module? Disable it. You enable only the modules that you need.

One other great thing about FreeSWITCH: the hooks. You can enable the built-in HTTP server and send commands and receive the output as text, XML or HTML markup. FreeSWITCH can output CDRs in CSV files or with the very powerful cdr_xml module. CDRs in XML are amazing as it is, but in addition to dumping XML to a file, FreeSWITCH can POST XML CDRs to a Web server that can in turn handle the db back-end. This allows for easy off-line handling of CDRs. The power of the XML CDRs cannot be overstated. If you've ever dealt with the drama of CDRs on an Asterisk system then you know what I'm talking about. When it comes to CDRs, it's better to have too much information rather than not enough. Single-record CSVs are okay, but XML CDRs give you a complete call history. You can log the A leg, B leg, or both legs. Each leg's XML CDR file has a field to identify the "other" leg so that you can logically associate two XML CDR files and create a complete call record. The greatest "hook" in FreeSWITCH, though, is the event socket.

FreeSWITCH has an amazing eventing system where modules send event messages to the core and receive messages from the core. This allows for agnosticism in the design of the system. Disparate modules don't have to know anything about each other. All they have to do is send messages to the core and act upon messages from the core. The event socket is an extension of this eventing system. An external process can connect to FreeSWITCH and subscribe to these events and act accordingly. The process can control calls, record stats, monitor the system, etc. Any programming language that supports socket programming can be used to control FreeSWITCH. It really is amazing.

Try FreeSWITCH, I promise you will be impressed. Even if you are totally satisfied with your existing system, be it OSS like Asterisk and YATE, or proprietary like 3CX, I recommend giving FreeSWITCH a test drive. Some have done so and immediately decided to add FreeSWITCH to their repertoire. Others needed functionality or stability that Asterisk or other systems could not provide. What can FreeSWITCH do for you? Among other things it will give you one of the most powerful telephony engines in the world and you won't have to spend a dime on software. At the very least you will have an ace up your sleeve the next time you need to build a VoIP system.

Monday, September 14, 2009

Can I Just Tell You How Much I Like HD Voice?

Wow.

Every time I spend all day on a HD conference and then someone on a cell phone calls in I am reminded of just how horrible cell service is. It's worse than the 300~3300Hz stuff we get on the regular PSTN, which is saying a lot. Anyway, I'm just ranting. Thanks for listening.

BTW, an interesting fact came out when we were tinkering around in our conference. We have the ability to do TTS (text-to-speech for you non-telephony folks) as well as play .wav files for everyone in the conference to hear. The other day Anthony Minessale (lead FreeSWITCH developer) found a sound of crickets chirping. It's perfect for those times when you ask for help on the conference and are greeted with silence. Anyway, it happened that everyone but me was on a 8kHz connection for one reason or another. I was connected with 32kHz Polycom Siren 14, aka G.722.1c. Tony played the crickets sound and asked if we heard the crickets chirping. I said yes but everyone else said nope. After a few seconds of head-scratching Tony realized that I was on 32kHz and I was the only one who could hear the crickets.

The moral of the story: If you want to hear crickets chirping then get HD voice! :D

Okay, okay, I admit maybe that's not the most ringing endorsement of HD voice, but it is a curious phenomenon and it does demonstrate that traditional 8kHz voice has issues beyond whether someone said "S" or "F"... Anyway, if you haven't downloaded and tried out FreeSWITCH just yet then definitely do so soon! I highly recommend it, and not just for HD voice. It is more stable and scalable than Asterisk. Heck, it's more powerful than any commercial solution I've ever seen.

-MC

Thursday, September 3, 2009

Kicking It Off: Skype For Asterisk = *YAWN*

Okay, I'm not Mr. Blogger by any stretch of the imagination but occasionally I have an opinion I'd like to share so I decided to start a small blog. The inaugural blog post will deal with a topic that has the twitterverse all abuzz: Skype for Asterisk.

On the surface this seems like a really cool thing: Open Source Telephony meets Skype (and its 440+ million users) for free calls. Skype for Asterisk (SfA) is a collaboration between the Skype developers and Digium, the company behind the Asterisk open source PBX. The good thing about this union is that it does not use any proverbial hacks, that is, Digium was given access to the Skype SDK/API/whatever you call it. In plain English: you don't have to have a Skype client running on your Asterisk box for SfA to work. And it's "only" $66 per concurrent channel/user.

Okay, so what's the problem? you ask. Quite simply this: Skype has a higher quality codec called SILK, which actually sounds nice if you're used to the lousy quality of regular PSTN calls or the horrible quality of mobile phone connections. However, SfA does not use this proprietary codec. Instead it supports only two codecs: G.711 and G.729A. Suffice it to say I'm not a huge fan of either of these codecs. (See this post for my feelings on G.729.) And G.711 sucks up a lot of bandwidth and gives only marginal quality. Relatedly, the Skype for SIP program supports only G.729.

My question is this: WHY?!? Scratch that - I don't care why, I only care that SILK is not an option. I can understand not limiting the codec choices to SILK - that actually makes sense. However, having only low quality codecs available seems just plain silly to me. I can already make "free" calls on the Internet without Skype using low quality audio. With FreeSWITCH I'm able to make free calls with high quality codecs. Adding Skype and SILK to the list just makes the HQ pool bigger. Giving me more low quality calls at one-time cost of $76 per channel ($66 for SfA, $10 for G.729 license) doesn't exactly get my blood pumping.

If I'm a business and I'm looking at adding Skype capacity to my PBX then I really need to think this through. Let's say I think I might get 10 simultaneous Skype calls, and that I want to use G.729 instead of G.711 so that I can save bandwidth. That's $760 before I've spent a dime on hardware, and I haven't even tested to make sure this is going to work. Here's an alternative solution: Use FreeSWITCH with the Skypiax module. If you already run FreeSWITCH as a PBX then it's pretty easy to get Skype support: just compile and run mod_skypiax. If don't have a FreeSWITCH machine running just yet then find a spare server and start learning it! :) The author of mod_skypiax, Giovanni Maruzzelli, has nice instructions on getting up and running. You can get high-quality Skype calls on FreeSWITCH which can connect to other SIP-based communications systems. You can do this with zero out-of-pocket software costs.

So what's the catch? Simple: mod_skypiax is a bit of a hack in the programming sense of the word. Each concurrent channel of Skype requires an instance of the Skype client. Gasp! The horrors! Oh wait, it's not actually all that bad. Testing on Linux systems we've done 20 concurrent channels with decent performance. (Giovanni is working with the ALSA developers on making things even better.) If you need a lot of Skype channels then just stack the servers. Spend that SfA + G.729 money on hardware instead.

So how does it all work? How is it that SfA (and Skype for SIP) don't support SILK but the "hack" of Skypiax on FreeSWITCH does support it? Simple: the "hack" uses the Skype client, and the Skype client does the SILK transcoding. The Skype client transcodes between SILK and 16-bit signed linear audio. FreeSWITCH never sees SILK, it only sees a simple audio stream which it can then transcode into G.722, Speex, CELT, or any other supported codec. On the other hand, SfA doesn't do SILK, only G.729 and G.711. SfSIP uses only G.729 (right now). In simple terms, the "hack" uses the Skype client which does the magic of transcoding to/from SILK.

Before all the Asterisk fans get their knickers in a twist, relax. I spoke with Giovanni and he is almost done with Skypiax for Asterisk. When he releases it then all you Asterisk users will have the "free" option as well. The difference, though, is that Asterisk is less stable that FreeSWITCH and you'll have to figure out how many Skype client instances you can reliably run without your Asterisk box going haywire. Of course, since Asterisk doesn't do 16kHz codecs very well I can't tell you if you will get the high quality audio using Skypiax. Please try and report back.

Now it's your turn. Tell me what you think of all this stuff: Skype, Asterisk, FreeSWITCH, HD Voice, etc. What do you use and why? How well does it work? Do you even care about HD voice? I know I do, but I use it all day every day. When and how do you use it? I'm listening...