The Fugue Counterpoint by Hans Fugal

3Feb/081

Local Caller ID Database

If you use a VOIP provider for PSTN calls, you will be able to relate to the frustratingly boring caller ID names that get passed down to you. Very infrequently do I get anything better than a city name. Even if you have a direct PSTN connection into Asterisk, you may find the caller ID names from cell phone users (maybe just about everyone that calls you) are less than precise. Here's a solution.

We want to store alternative names in some kind of database that Asterisk can access when a call comes in. AstDB is perfect for this. We also want to leave things unchanged if we haven't manually stored a name for this number. The following will do the trick:

    Set(CALLERID(name)=${IF(${DB_EXISTS(cid/${CALLERID(num)})}?${DB(cid/${CALLERID(num)})}:${CALLERID(name)})})

Now, we just need a way to update the database with names. At first I had grandiose ideas of an AJAX-enabled website that shows you the last few CDR records and lets you edit the names with a spiffy in-place editor. You could still accomplish it, but in the end I came up with a much simpler if less elegant solution. At least, it's simpler if you use the terminal all the time like I do. Put this script in your path:

#! /bin/sh
# usage: $0 number "name"
user=`username`
host=falcon
exec ssh $host asterisk -rx \'database put cid \"$1\" \"$2\"\'

Combine this with jabber notification as I've discussed before, and a little cut & paste from your jabber window, and updating names is cake.

1Jun/070

ChanSpy Silence

I was setting up ChanSpy in an Asterisk dialplan today and it just wasn't working. Here is the snippet:

exten => 501,1,ChanSpy()

I would be connected, and the Asterisk console would tell me I was spying on people, but I would hear nothing at all. For the record, the calls I was spying on were all sorts, but mostly Zap, and I was spying from a SIP softphone.

After some blind fiddling, I found this combination works:

exten => 501,1,ChanSpy(,b)

The b option is "only spy on channels involved in a bridged call". I don't know why this fixes it, but it does.

For the record, it's working great even when calls are being recorded (with MixMonitor), without setting transmit_silence_during_record=yes in /etc/asterisk/asterisk.conf (as mentioned on the wiki). I don't know about the Record application.

17May/071

Jabber Call Notification

I can't believe I never thought of this before. It's the ultimate in couch potatoism.

We don't use the phone much. When it rings, the house fills with moaning and groaning because nobody wants to answer it, but we often don't dare ignore it because we don't know who it is. As I usually have my laptop with me, or at least in sight, I realized (with the idea coming from a client who wants me to do some Jabber integration) that the perfect solution is to have Asterisk send me a notification via Jabber with the caller ID.

It's very simple. I use the sendxmpp program to
do the heavy lifting. Here's the
Batphone script:

#!/usr/bin/ruby

## Configuration
# sendxmpp config file has to be mode 600 and owned by the asterisk user
CONFIG="~fugalh/telephony/.sendxmpprc"
RESOURCE="Asterisk"
RECIPIENTS="hans@fugal.net erin@fugal.net"

require 'agi'
agi = AGI.new
IO.popen("sendxmpp -r #{RESOURCE} -f #{CONFIG} #{RECIPIENTS}", "w") {|f|
  f.puts "Incoming call from #{agi.env['callerid']}"
}

As much as I love Batphone, it's almost as easy to do with a shell script:

#!/bin/sh

# sendxmpp config file needs to be mode 600 and owned by the asterisk user
CONFIG=~fugalh/telephony/.sendxmpprc
RESOURCE=Asterisk
RECIPIENTS="hans@fugal.net erin@fugal.net"

# this snippet from http://yakko.cs.wmich.edu/~drclaw/asterisk/cidname/
declare -a array
while read -e ARG && [ "$ARG" ] ; do
    array=(` echo $ARG | sed -e 's/://'`)
    export ${array[0]}=${array[1]}
done

echo "Incoming call from $agi_callerid" | \
    sendxmpp -r $RESOURCE -f $CONFIG $RECIPIENTS

If you are lucky enough to get agi_calleridname set as well, you obviously
might like to integrate that information into your message too. Here's the Asterisk dialplan snippet:

exten => s,1,AGI(/home/fugalh/telephony/jabber.agi)
exten => s,n,Dial(SIP/sipura&SIP/hans,30)
; ...
Tagged as: , , 1 Comment
6Mar/070

¡Adios, MediaProxy!

I have extolled the virtues of
(Open)SER+MediaProxy
in the past, but I can no longer recommend it. Instead I recommend using
Asterisk as a sort of pseudo media proxy. Why? Read on.

The problem is that
SIP and
NAT don't get
along. The reason they don't get along (besides that NAT is evil) is that the
RTP packets (the
media stream) may follow a completely different, and more direct, path from
endpoint to endpoint than the SIP packets do. This is a good thing, except in
the face of NAT. If there's a NAT involved, the RTP packets often can't get
through. SER+MediaProxy solves this by tricking the endpoints into thinking
mediaproxy is the other endpoint for RTP data. MediaProxy, which is not behind
a NAT, is able to receive data from both parties and forward it on to each
party (via the NAT holes already punched by them talking to the media proxy).

It's an elegant setup. It's a wonderful solution to an evil problem. But it
turns out, quite surprisingly, that MediaProxy doesn't scale as well as other
solutions. That is, there's a too-low ceiling on the number of simultaneous
calls that MediaProxy can handle before the CPU maxes out.

Here's a setup that scales much better. Instead of doing the MediaProxy dance
when NAT is detected, instead have SER proxy the packets through Asterisk. Have
Asterisk set up to accept calls from SER (who has already authenticated the
user), or to do the user authentication (in addition to SER?), and it will
happily insert itself in the middle of the call as a back-to-back user agent.
If you do this you will want to take care that you avoid gratuitous transcoding
because that will certainly not scale as well as MediaProxy. But if you can
keep from transcoding, this scales more than 2x better than MediaProxy.

This is a surprising result, because Asterisk is more complicated than
MediaProxy, and the whole back-to-back user agent scheme is a lot more
complicated than simply forwarding packets which is in essence all MediaProxy
has to do, and that Asterisk has generally done a poor job of supporting SIP.
MediaProxy is written in Python, and Asterisk in C. That might be part of it.
Jared Smith tells me that
there are various new optimizations for bridging calls in Asterisk, such as
header caching. That might be another part of it.

Since setting up Asterisk this way is no harder and I think quite a bit easier
than setting up MediaProxy (esp. in light of the "don't use_mediaproxy() (and
friends) more than once in a route" bug), and Asterisk scales better in the
real world, I have to recommend Asterisk as your media "proxy".

The story doesn't end here, though. It continues to evolve. It remains to be
seen whether another implementation of a media proxy than MediaProxy or
RTPProxy (which is still not as scalable as Asterisk in our tests) can do the
job more efficiently still. I think that it should be possible. I might do it
as a learning project in Erlang, but no promises. At this point I think it is
doubtful whether a naïve implementation in any language, even C, would outrun
Asterisk with its bridging optimizations. On the other hand, forwarding RTP and
RTCP packets unchanged isn't rocket science and it just might be easy to outrun
Asterisk.

Thanks to Elliot at Arrivaltel and Jared for helping
me with testing, pontificating, and discussion, and to Brent Thomson for
casting a shadow of doubt over MediaProxy (for other reasons) in my mind in the
first place.

1Mar/071

Holy Telephony, Batman!

batphone

Does the world need yet another Ruby Asterisk Gateway Interface library? Does
the world need a guy who dresses up like a bat?

I was not satisfied with the complexity and learning curve of existing AGI
libraries for Ruby, so rather than spend an hour learning one of them I spent
several hours writing my own. I hope this pays off in the future when it only
takes me 5 minutes to remember/relearn how to use batphone. It was fun, anyway.
That's the point, isn't it? That's why Batman does it. Not for the citizens of
Gotham, but because it's fun.

Here's a synopsis:

#!/usr/bin/ruby
require 'agi'

agi = AGI.new
agi.answer
agi.stream_file('batman_help_the_monkeys_are_everywhere', nil)
begin
  # press pound to make them stop!
  r = agi.stream_file('tt-monkeys', '#')
end while r.result != ?#
agi.stream_file('POW', nil)
agi.hangup

Here's the URLs: For Documentation press
1. For Download press
2. For direct
access to the batphone press 3.

POW!

12May/060

SPA-3000

Getting started with Asterisk just got easier. Well, it didn't just get
easier, because the SPA-3000 isn't a new product. It's just that I just now
realized how perfect this device is for the fledgling VOIPer.

The traditional advice is to get an Asterisk Developer's
Kit
which gives you one
FXS port and one FXO port, expandable. In the old days, this wasn't bad advice
because the old devkit was reasonably priced. The new devkit is better, but
pricier. At $240 it can hardly be considered entry level for any but the most
serious (or rich) Asterisk newcomers.

The Sipura SPA-3000 is an amazing
bundle of joy that also provides an FXS and FXO port. What I didn't realize
(but should have guessed) before now was that it can not only bridge its FXS
and FXO ports, but act as a gateway with external SIP devices, like Asterisk.
So this thing can do everything the Asterisk devkit can do except add FXS or
FXO ports, but without all the headache or cost. You can find these for less
than a hundred, and you don't have to install it in your PC, worry about
interrupts, or set up zap*.conf. You can still use Asterisk, of course, but
you can also pair it up directly with SER or any SIP
provider you like. Yes, you could do that with Asterisk too, but frankly
Asterisk isn't a stellar SIP implementation and if you're serious about SIP
you'll find on occasion that you might like to bypass it. (Whether or not you
want to be serious about SIP is another post. ;-)

If you want to get started with VOIP in the comfort of your own home, all you
need is a Linux box and an SPA-3000.

What about all the phones scattered throughout the house? Plug the phone
company directly into the SPA FXO, and the SPA FXS into the wall. (Or just go
straight VOIP, in which case you don't technically need a 3000 but might be
better served with a 1000 or 2000 family member)

What about Digium?! How will the Asterisk developers feed their children and
pets?! You traitor! You capitalist! You... You... Microsoft-lover!

I am full of gratitude for the Asterisk developers and for Digium, but I
frankly believe Digium's products are overpriced and I have no qualms in taking
my business elsewhere when it makes sense to do so. I have a Sipura SPA-1001
and I am very impressed with the quality of it, so I am confident in my
recommendation. Go with the SPA.

20Oct/050

radp – Ruby Asterisk Dial Plan generator

With many thanks to Jim Weirich for his excellent
presentation

(which I unfortunately could not experience in person), I present an
Asterisk DSL called radp.

Asterisk is incredibly cool and powerful, and until now has been
incredibly painful to configure for someone as accostumed to the beauty
of ruby as I am. That all ends today.

http://hans.fugal.net/src/radp

Tagged as: No Comments