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

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

./bootstrap.sh

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:

./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:

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!

/usr/local/freeswitch/bin/freeswitch

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

Cheers!

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);
$p->hires();
($ret, $dur, $ip) = $p->ping($hostip);
$time = (1000 * $dur);
if ($ret == 0) {
printf PT ("[TIMEOUT]\n");
$noret++;
} 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;
$pn++;
$psos += $px * $px;
}
$p->close();
}
$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_HEADER,1);
$curl->setopt(CURLOPT_URL, 'http://speedtest.wdc01.softlayer.com/downloads/test100.zip');

my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$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");
}

PING();
CURL();

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.

#!/usr/bin/perl
#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).

Enjoy.

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