OSX Pianobar Growl Integration

Worked on a great script tonight with my friend Intralanman from the FreeSWITCH community.  As a change of course we decided to add a layer on an already amazing application called Pianobar: http://6xq.net/projects/pianobar/.  You can view the joint project here: https://github.com/intralanman/pianobar-eventcmd

and my fork here: https://github.com/kmross/pianobar-eventcmd

and this is what we get here:

Screen Shot 2013-04-30 at 12.13.49 AM

ADRA donations for Hurricane Sandy

I would like to think that many of you that read my blog also have a good heart.  My thoughts and prayers go out to those in need while Hurricane Sandy barrages our land with brutal rain and high winds.  If you would like to donate, please do so here to help those in need.  I personally know some of the folks at ADRA and have even donated some of my time in the past to help them out.  They are extremely honest and 100% of your donation goes to help those in need.  You can also donate by clicking on the banner below.

Install FusionPBX on Raspberry Pi

Well, I couldn’t stop with JUST installing FreeSWITCH, so I took it a step further and installed FusionPBX which is the UI.  I had to do a tidbit of editing to their install script, and hack some workarounds, but I got it working successfully.

With the assumption that FreeSwitch is installed using my tutorial here, you’re halfway home to getting FusionPBX installed.  Note: rolled in sudo -s (root)

Prior to installing, I downloaded a couple packages that I assumed I needed:

apt-get install php5-pgsql postgresql

I placed the edited installed script here, so you probably will want to wget it:

cd /usr/local/bin/
wget http://www.kevinmross.com/downloads/install_fusionpbx.sh

Now, the install script is pretty horridly edited and I really did not take any time with it nor brushed it over with a ‘fine-tooth-comb‘ to optimize, so it will install a bunch of possibly useless packages, but its really no big deal for ‘proof of concept’ right?

After you download it, its time to make it executable and then run it!:

chmod 755 /usr/local/bin/install_fusionpbx/install_fusionpbx.sh
/usr/local/bin/install_fusionpbx.sh install-both user |tee /tmp/install_fusion.log

The script starts off by checking your system:

Good, you are root.
Internet connection is working, continuing!
This script was written for Ubuntu 10.04 LTS codename Lucid

Your OS appears to be:
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux testing/unstable
Release: testing/unstable
Codename: n/a
Do you want to continue [y|n]?

Obviously we want to continue, so we say “y”.

The script will go through a ton of packages and checks, and assuming there is no issues, we can move onto the next step.

now install FusionPBX. This should go fast.

Press Enter to continue (check for errors)

…and obviously we press enter again if there were no errors…

Adding user `freeswitch' to group `www-data' ...
Adding user freeswitch to group www-data
Adding user `www-data' to group `daemon' ...
Adding user www-data to group daemon
freeswitch is now a member of the www-data group
www-data is now a member of the dameon group

Press Enter to continue (check for errors)


FusionPBX install needs Write permissions on group to remove files
The daemon group (of which www-data is a member) can now edit all files
in your FreeSWITCH installation. This may or may not be desirable

if you want to change this, run (as root)
/usr/bin/find /usr/local/freeswitch -type f -exec /bin/chmod g-w {} \;
/usr/bin/find /usr/local/freeswitch -type d -exec /bin/chmod g-w {} \;
however; FusionPBX won't be able to make changes anymore
renaming default FreeSWITCH extensions .noload
Press Enter to continue (check for errors)

…and yet again…

The next step is for a database setup.  I am extremely familiar with Postgres so that will be my database of choice.

Now for a database...

New Option...
SQlite is already installed (and required)

Would you like to install MySQL, PostgreSQL or stay with Sqlite (m/p/S)? p
precise is PostgreSQL 9.1 by default
Installing PostgeSQL version 9.1

during the install of Postgres, I noticed that the script threw an error where the database did not create successfully:

createdb: database creation failed: ERROR: encoding UTF8 does not match locale en_US

At some point I was prompted to enter a password which failed miserably:

The pgsql username is fusionpbx
The pgsql database name is fusionpbx
Please provide a password for the fusionpbx user
Let's repeat that
psql: FATAL: database "fusionpbx" does not exist
overwriting pgsql password variable with random data

So I just logged into a new ssh session (if you are using screen, you can just detatch), and noticed there was no data folder for the install and the db had not been init.  So I just did it manually:

mkdir /usr/local/pgsql/
mkdir /usr/local/pgsql/data
chown postgres /usr/local/pgsql/data
su - postgres

and to initialize…

/usr/lib/postgresql/9.1/bin/initdb -D /usr/local/pgsql/data

after initializing it with a success message…

Success. You can now start the database server using:

/usr/lib/postgresql/9.1/bin/postgres -D /usr/local/pgsql/data
/usr/lib/postgresql/9.1/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start

I started up postgres and created the database manually, set user, pass, role, etc.

/usr/local/pgsql/bin/createdb fusionpbx

once in in postgres cli…

postgres=# ALTER USER fusionpbx with PASSWORD 'YOUR_PASSWORD';

and then…

Now you'll need to manually finish the install and come back
This way I can finish up the last bit of permissions issues
Just go to
MAKE SURE YOU CHOOSE PostgreSQL as your Database on the first page!!!
ON the Second Page:
Database Name: fusionpbx
Database Username: fusionpbx
Database Password: whateveryouentered
Database Username: Leave_Blank (remove pgsql)
Create Database Password: Leave_Blank

I will wait here until you get done with that.
When PostgreSQL is configured come back and press enter.

I then went in and entered the database db type, db name, login, password, etc into the webUI.  It will take a bit of time to install, but once it is, go back to the CLI and finish the installation there:

I will wait here until you get done with that.
When PostgreSQL is configured come back and press enter.

The FusionPBX installation changed permissions of /usr/local/freeswitch/storage
Waiting on you to finish installation (via browser), I'll clean up
the last bit of permissions when you finish.Waiting on /var/www/fusionpbx/includes/config.php

/var/www/fusionpbx/includes/config.php Found!
Waiting 5 more seconds to be sure.
..... Fixing...
Setting up Fail2Ban for FusionPBX
Restarting authentication failure monitor: fail2ban.
Installation Completed. Now configure FreeSWITCH via the FusionPBX browser interface
Default login is (whatever you picked in the GUI install):
User: WhateverUsernameYouPicked
Passwd: YourPasswordYouPicked
Checking to see if FreeSWITCH is running!
6471 Backgrounding.

And thats it folks.  That is a quick and hacked up way to install freePBX on the raspi:

Pandora on Raspberry Pi

The raspberry pie makes a great pandora unit.  Duct tape it to the back of a battery-powered speaker with the 3.5 plug connected and it becomes a rocking portable boombox….make sure you have a long ethernet cord though!  Here’s how assuming root@:

We first want to push the audio out to the 3.5 jack:

root@raspberrypi:~# amixer cset numid=3 1

then install pianobar:

root@raspberrypi:~# apt-get install pianobar

Pianobar controls are located here.

FreeSWITCH on the Raspberry Pi

The $35 mean machine really comes out on top for slapping together a PBX very quickly.  Before I started this project, I saw Asterisk being ported over onto the Raspberry Pi, so I decided to take a shot at it a couple months back just before ClueCon for FreeSWITCH.  Here were the results:

You initially want to start out with a Raspian image (I used Wheezy): http://www.raspberrypi.org/downloads

DD the image onto your SD-card.  You can use the wiki located here for instructions on how to do it.

Be sure to go through the install process using raspi-config.  You will want to expand the partition, etc.

And now we begin…

I like to roll around as root so as soon as I logged in as the default ‘pi’ user, I immediately dropped into a sudo shell as root.

sudo -s

I immediately installed several other pieces of software/libraries I like to have for this build as well as for my own future use:

apt-get update
apt-get install screen default-jre mlocate autoconf automake libtool libncurses5-dev libjpeg8-dev default-jre git libperl-dev libdb-dev libiksemel-dev gnutls-bin libgnutls-dev

While we are at it here, lets link up a couple libraries:

ln -s /usr/lib/arm-linux-gnueabihf/libgdbm_compat.so.3 /usr/lib/libgdbm_compat.so
ln -s /usr/lib/arm-linux-gnueabihf/libgdbm.so.3 /usr/lib/libgdbm.so

The first thing to do here is to clone the git repo on the unit, but we have to change directories to:

cd /usr/local/src

For a stable release:

git clone -b v1.2.stable git://git.freeswitch.org/freeswitch.git

or if you want the latest and greatest

git clone git://git.freeswitch.org/freeswitch.git

From here we will change directories into the FreeSWITCH dir.

cd freeswitch

We then will want to run the boostrap to make the modules.conf file for us to edit


You can now edit the modules.conf if you want to add any additional modules by uncommenting them out.  (For my build, I uncommented mod_dingaling which gives support for Google Voice)

Once that step is done, lets configure:


After configure was done, I edited the makefile to remove the second instance of “-Werror” which is a flag that stops the build process on a warning.  Info: Not doing this will stop the build, so if you hate yourself and want to waste hours of RasPi CPU time, feel free to do this continuously.

vi makefile

just an FYI: if you get angry with the arrow keys in vi, you can

:set term=cons25

…which should make you happy again.

I went ahead and removed the second instance of “Werror” within the make file because I was getting possible irrelevant warnings that were stopping the compile process.  This is a cheap way around and probably isn’t recommended as it could create segfaults within FreeSWITCH…but I did it anyways. (This is proof of concept…what do you expect here?)

Once we are gucci, we can continue with make:


and then we shall install that puppy

make all install cd-sounds-install cd-moh-install

After many relentless hours of compiling; if there were no errors,  you have successfully built FreeSWITCH.  Lets run it!


Alternatively, you could add some tricks to it like chowning the FS directory so it doesn’t run under root, but this was a quickie proof of concept to show that it is possible to run FS under the RasPI.

My close friend Intralanman over at FSS gave me the glorious idea of using distcc with the Pi to help speed along the process.  I may toss up notes or a new article including it.

If you feel like going back to raspian but want to save you current image, you can always dd it off using either your linux or mac box.  I usually dd and compress at the same time to save space.  It will compress nicely too:

dd if=/dev/disk2 | gzip > {image_destination}/freeswitch_image.dd.gz


Network Speed and Jitter Perl Script

My friend Shawn and I have recently been burdened by terrible networks (both LAN and WAN).  Shawn finally got fed up before I did and decided to write a tool in perl to test network capability and calculate the deviance (jitter).  This is a lifesaver especially when measuring UDP for SIP.  I really appreciate him for this…except he needs to add a graph! (inside joke) =D  Bravo Shawn!  As always, the code was originally properly formatted, but wordpress just hates copy and pasting and seems to remove that on me.

#!/usr/bin/perl -w

use strict;

use Net::Ping;
use Time::HiRes;
use WWW::Curl;
use WWW::Curl::Easy;

use constant VERNUM => 2012092808;

my ($hostip,$proto);

printf "IP:\n";
$hostip = <>;
chomp ($hostip);

printf "PROTOCOL:\n";
$proto = <>;
chomp ($proto);
printf "\n";

sub PING {
my ($ret,$dur,$ip,$count,$bytes);
my ($px,$pn,$psum,$psos,$pvar,$psd,$pavg);
my ($time,$ploss,$grade,$gL);
my ($eff_latency,$mosR,$mosR2,$mosgrade);
my $noret = 0;

my @bytes = qw(8 12 16 32 64 128 256 512 768 1024);
my @pvals;

open (PT, ">", "/tmp/netbench.txt") or die $!;
foreach $bytes (@bytes) {
for ($count = 25; $count >= 1; $count--) {
my $p = Net::Ping->new($proto, "1", $bytes);
($ret, $dur, $ip) = $p->ping($hostip);
$time = (1000 * $dur);
if ($ret == 0) {
printf PT ("[TIMEOUT]\n");
} elsif ($time > 500) {
printf PT ("[E] Size: $bytes - Time: $time\n");
} elsif ($time > 300) {
printf PT ("[D] Size: $bytes - Time: $time\n");
} elsif ($time > 150) {
printf PT ("[C] Size: $bytes - Time: $time\n");
} elsif ($time > 100) {
printf PT ("[B] Size: $bytes - Time: $time\n");
} else {
printf PT ("[A] Size: $bytes - Time: $time\n");
push(@pvals, (1000 * $dur));
foreach $px (@pvals) {
$psum += $px;
$psos += $px * $px;
$pvar = ($psos-(($psum*$psum)/$pn))/($pn-1);
$psd = sqrt($pvar);
$pavg = ($psum/$pn);
if (($pavg > 500) || ($psd > 150)) {
printf PT ("[E] Size: $bytes - Average: $pavg - Deviance: $psd\n");
} elsif (($pavg > 300) || ($psd > 100)) {
printf PT ("[D] Size: $bytes - Average: $pavg - Deviance: $psd\n");
} elsif (($pavg > 150) || ($psd > 50)) {
printf PT ("[C] Size: $bytes - Average: $pavg - Deviance: $psd\n");
} elsif (($pavg > 100) || ($psd > 30)) {
printf PT ("[B] Size: $bytes - Average: $pavg - Deviance: $psd\n");
} else {
printf PT ("[A] Size: $bytes - Average: $pavg - Deviance: $psd\n");
printf ("Size: $bytes - Average: $pavg - Deviance: $psd\n");

$ploss = (($noret/250) * 100);
if ($noret >= 40) {
printf PT ("[E] Packets lost: $noret - Loss percentage: $ploss\n");
} elsif ($noret >= 6) {
printf PT ("[D] Packets lost: $noret - Loss percentage: $ploss\n");
} elsif ($noret > 1) {
printf PT ("[C] Packets lost: $noret - Loss percentage: $ploss\n");
} elsif ($noret == 1) {
printf PT ("[B] Packets lost: $noret - Loss percentage: $ploss\n");
} else {
printf PT ("[A] Packets lost: $noret - Loss percentage: $ploss\n");
printf ("Packets lost: $noret - Loss percentage: $ploss\n");
$eff_latency = ($pavg+$psd*2+10);
if ($eff_latency < 160) {
$mosR = (93.2-($eff_latency/40));
} else {
$mosR = (93.2-($eff_latency-120)/10);
$mosR2 = ($mosR-($ploss*2.5));
$mosgrade = (1+(0.035)*$mosR2+(.000007)*$mosR2*($mosR2-60)*(100-$mosR2));
if ($mosgrade >= 4.30) {
printf PT ("[A] MOS: $mosgrade\n");
printf ("MOS: %.2f - Grade: [A]\n", $mosgrade);
} elsif ($mosgrade >= 4.20) {
printf PT ("[B] MOS: $mosgrade\n");
printf ("MOS: %.2f - Grade: [B]\n", $mosgrade);
} elsif ($mosgrade >= 4.00) {
printf PT ("[C] MOS: $mosgrade\n");
printf ("MOS: %.2f - Grade: [C]\n", $mosgrade);
} elsif ($mosgrade >= 2.50) {
printf PT ("[D] MOS: $mosgrade\n");
printf ("MOS: %.2f - Grade: [D]\n", $mosgrade);
} elsif ($mosgrade < 2.50) {
printf PT ("[E] MOS: $mosgrade\n");
printf ("MOS: %.2f - Grade: [E]\n", $mosgrade);
close (PT);

sub CURL {
my $curl = WWW::Curl::Easy->new;
my $cstart = time();
my ($fsize,$timedif,$c_spd);

$curl->setopt(CURLOPT_URL, 'http://speedtest.wdc01.softlayer.com/downloads/test100.zip');

my $response_body;

my $retcode = $curl->perform;

if ($retcode == 0) {
$fsize = 104874307;
} else {
print("ERROR: $retcode ".$curl->strerror($retcode)." ".$curl->errbuf."\n");
my $cend = time();
$timedif = ($cend-$cstart);
$c_spd = int((((($fsize/$timedif)/1000)/1000)*8));
printf ("SPEED: $c_spd mbps\n");


Perl Sonicwall configuration dump decoder

Many times I run into horrible network configuration’s.  The most popular firewall I see out in the field within a major portion of clients unfortunately is the Sonicwall series (NSA, TZ).  The popularity of these firewalls spans from both small and medium businesses.  In VOIP, it is VERY necessary to make sure the client’s configuration is compatible with the VOIP configuration.  In the past, Sonicwall has a bad habit of causing problems, but admittedly are becoming better.  They may be horrid, they may not do things correctly, but they still need to be addressed accordingly.

Below is a script I put together when I found out that the Sonicwall dump (.exp) that was given to me was just a base64 conversion.  This is very useful to help troubleshoot when you do not have remote access to the unit.

#decode sonicwall exported config files
#Usage: cat sonicwall.exp | ./sonciwalldecode.pl > output.txt

use strict;
use MIME::Base64;

local($/) = undef; # slurp
my $decodesw = decode_base64(<STDIN>);
$decodesw =~ s/&/\n/gms;
print $decodesw;

Text Selection & Call Origination Javascript bookmarklet

As you all may know I have worked for Barracuda Networks for a bit under two years.  The product I work with everyday is the Cudatel.  Based on FreeSWITCH, it has the potential to be quite the game-changer within the VOIP world (that is, if Barracuda plays their cards right).  I figured it would be fitting if the first post to the new website would be some good ol code I slapped together that uses the Cudatel’s restAPI.  Below is a bookmarklet that lets one’s cursor selection within a browser be sent out to the Cudatel.  This gives the user potential to select a phone number, and dial out; eliminating the need for a TAPI interface (at least within a browser).

This could be taken to an extreme with a number autodetection browser integration plugin (much like skype has with FireFox, IE, and Chrome.  But for now, this works spectacular.  Not much thought was put into this as there could be many more conditions for error checking and perhaps conversion between alpha and numeric characters (1-800-abc-defg).


javascript:(function(){var num = window.getSelection ? window.getSelection().toString() : document.selection.createRange().text;num = num.replace(/[^\d.]/g, "");if(num.length < 10){alert("Failure");}var iframe = document.createElement('iframe');iframe.src="http://<url_of_your_cudatel>/gui/freeswitch/originate?__auth_user=<USERNAME>&__auth_pass=<YOURPASSWORD>&destination=" + num;document.body.appendChild(iframe);})()


EDIT July 2, 2013 – Thanks to my friend Michael, he thought it would be swell to add an alternative popup box when nothing is highlighted so one could always put in a number:

javascript:(function(){var num = window.getSelection ? window.getSelection().toString() : document.selection.createRange().text;num = num.replace(/[^\d.]/g, "");if(!num){void(num=prompt('What number, please:',''))};if(num.length < 10){alert("Invalid number, please try again.")};var iframe = document.createElement('iframe');iframe.src="http://<url_of_your_cudatel>/gui/freeswitch/originate?__auth_user=<EXT>&__auth_pass=<PASS>&destination=" + num;document.body.appendChild(iframe);})()