The Fugue

Counterpoint by Hans Fugal

Local Caller ID Database

Posted by Hans Fugal Sun, 03 Feb 2008 18:54:38 GMT

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.

1 comment |

ChanSpy Silence

Posted by Hans Fugal Fri, 01 Jun 2007 17:00:34 GMT

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.

no comments |

Jabber Call Notification

Posted by Hans Fugal Thu, 17 May 2007 20:52:00 GMT

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)
; ...

1 comment |

¡Adios, MediaProxy!

Posted by Hans Fugal Tue, 06 Mar 2007 17:46:29 GMT

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.

no comments |

Holy Telephony, Batman!

Posted by Hans Fugal Thu, 01 Mar 2007 14:20:07 GMT

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!

1 comment |

SPA-3000

Posted by Hans Fugal Sat, 13 May 2006 03:19:34 GMT

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.

no comments |

radp - Ruby Asterisk Dial Plan generator

Posted by Hans Fugal Thu, 20 Oct 2005 16:05:49 GMT

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

Posted in | no comments |