/ asterisk

Asterisk with Google Voice

I recently rebuilt my asterisk cluster as I migrated my primary node from RackSpace to DigitalOcean. I take opportunities like this to review configurations and security. Something I had done before was integrate google voice with asterisk, but it hadn't been working for a while. With the migration, I repaired this problem. It's been running for weeks now and proven to be very stable. Getting it setup took some effort, though, and that's what we'll explain here.

Further, I didn't just want to answer google voice calls with asterisk. I wanted to let google voice continue to provide simultaneous ring to my cellphone and provide voicemail with transcription. So I could only "answer" the call through asterisk if I actually pick up the call from my desk phone. Answering a google voice call from a jabber client involves a bit of trickery with a delay and DTMF, but asterisk dialplans are so powerful it is easy to satisify this compound requirement.

pause; answer channel; if answered by user then send DTMF(1) to google voice.

network overview

The process to make google voice work with asterisk has changed through various versions of asterisk. I choose to run standard releases so the information herein is specific to asterisk v12, but should be aplicable to LTS v11 as well. For an explination of asterisk versions, see this page.

The asterisk wiki has a guide with most of the information on how to make this work, but unfortunatly it doesn't include information relevant to version 12, which requires pjproject. ICE will not work without pjsip resource modules and will throw an error like:

Unable to add Google ICE candidates as ICE support not available or no candidates available

Fixing this error involves manually compiling and installing pjproject because you probably won't find it in your distro's repositories, and then recompiling asterisk. Let's get started!

Step 1: dependencies

This page outlines dependencies required by various versions of asterisk. For asterisk 12 on ubuntu, here is what we need:

apt-get install build-essential wget libssl-dev libncurses5-dev libnewt-dev  libxml2-dev uuid-dev libjansson-dev libxslt1-dev libiksemel-dev pkg-config

Step 2: pjproject

The asterisk wiki provides a great explanation of how to satisify this dependency, so we'll just provide the core information here. FYI, this is for an install on ubuntu LTS (12.04) -- your configure --prefix may differ depending on your environment.

wget http://www.pjsip.org/release/2.2.1/pjproject-2.2.1.tar.bz2
tar -xjf pjproject-2.2.1.tar.bz2
cd pjproject-2.2.1

./configure --prefix=/usr --enable-shared --disable-sound --disable-resample --disable-video --disable-opencore-amr

make dep
#run as root:
make install

Step 3: recompile asterisk

Now go back and configure/compile asterisk. When you do the menuselect, you should find the various res_pjsip modules are enabled.
pjsip modules

Step 4: config files








And finally, our dialplan. Remember that we didn't want asterisk to answer all google voice calls -- we only wanted asterisk to answer the google voice calls if we answered the call from one of our SIP stations. Google Voice won't connect the call until we send it DTMF(1); notice the D(:1) argument in the Dial command; that's the trick! If you would like to understand how this option works, see the description on the voip-info wiki.

  exten => s,1,NoOp("Receiving call from google voice")

  ;This won't actually answer the channel with google
  ;voice, but the wait is necessary for gVoice and 
  ;the answer is necessary for asterisk. I think...
  same => n,Wait(1)
  same => n,Answer()
  ;Google Voice provides callerID number, but the
  ;callerID name is mostly nonsense. The number is
  ;internationalized. In this block we strip +1 from
  ;domestic (USA) numbers and drop the CallerID name
  same => n,Set(cnum=${CALLERID(number)})
  same => n,GotoIf($[${LEN(${cnum})} != 12]?cid-done)
  same => n,GotoIf($["${cnum:0:2}" != "+1"]?cid-done)
  same => n,Set(cnum=${cnum:2})
  ;with callerID fixed, now update:
  same => n(cid-done),Set(CALLERID(all)="" <${cnum}>)
  ;send the call to two SIP stations:
  same => n,Dial(SIP/107&SIP/103,30,twD(:1))
  ;If the call gets answered by either station,
  ;asterisk will send DTMF(1) to gVoice, which
  ;tells google we answered the call.