Now the final, most involved part of the process: Configuring the dialplan. We’ll take this bit by bit, but if you’re not sure about what a particular line does, check out the Wiki at Voip-Info.org.
Dialplan Basics
First we’ll get the basics of our dialplan configuration in place.
- Create
/etc/asterisk/extensions.confwith your favorite text editor. - Add the following block to the new extensions file
[general][globals]
This gives us some general structure for the extensions configuration. - Next, we will add a subroutine for handling calls to internal extensions. This will simplify the dialplan later on.
[internal-call]
exten => s,1,Verbose(====> Processing Internal Call)
exten => s,n,Set(DIALEXT=${ARG1})
exten => s,n,Verbose(====> Call is from ${CALLERID(all)} to ${DIALEXT})
exten => s,n,Dial(SIP/${DIALEXT},15,tT)
exten => s,n,GotoIf($["${SIPPEER(${DIALEXT},status)}" = ""]?badext:vmsw)
exten => s,n(vmsw),GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten => s,n(unavail),Verbose(====> Extension ${DIALEXT} is unavailable)
exten => s,n,Voicemail(${ARG1}@default,u)
exten => s,n,Hangup()
exten => s,n(busy),Verbose(====> Extension ${DIALEXT} is busy)
exten => s,n,Voicemail(${ARG1}@default,b)
exten => s,n,Hangup()
exten => s,n(badext),Verbose(====> Extension dialed does not go to a valid SIP channel)
exten => s,n,Playback(pbx-invalid)
exten => s,n,Hangup()
exten => s,n,Returnexten => h,1,Verbose(====> Ending Internal Call Processing - call was hung up)
exten => h,n,Return
This subroutine take an extension as an argument and dials it. If the extension doesn’t exist, an error message is played. If the extension is busy or unavailable, the call is transferred to Voicemail, which plays the appropriate greeting. s and h are special extensions in Asterisk. s acts as a placeholder for calls entering the context, while h defines actions that should be taken when a call in the context is hung up. - Now we’ll add a subroutine to handle making the outgoing calls using Google Voice
[gv-out]
exten => s,1,Verbose(====> Exexution passed to Google Voice Handler)
exten => s,n,Set(CALLING=${ARG1})
exten => s,n,Set(GVUID=googlevoiceusername)
exten => s,n,Set(GVPASS=googlevoicepassword)
exten => s,n,Set(SGNUM=5555550000)
exten => s,n,Set(PARKEXT=7100)
exten => s,n,Playback(pls-wait-connect-call)
exten => s,n,Set(PARKINGEXTEN=${PARKEXT})
exten => s,n,Park()exten => h,1,Verbose(====> Call Parked - Initiating Google Voice Call)
exten => h,n,System(gvoice -e ${GVUID} -p ${GVPASS} call ${CALLING} ${SGNUM})
exten => h,n,Verbose(====> GV Call initated)
This subroutine takes a single argument: the 11-digit number to call out to. You’ll need to changeGVUID,GVPASS, andSGNUMto be your Google Voice username, Google Voice password, and sipgate phone number. - Now we’ll add the
[incoming]context. This is where all calls coming in from sipgate end up.
[incoming]
exten => 9999999e1,1,Verbose(====> Processing incoming sipgate call from ${CALLERID(num)})
exten => 9999999e1,n,Set(GVCID=5555555555)
exten => 9999999e1,n,Set(RINGEXT=1000)
exten => 9999999e1,n,Set(PARKEXT=7100)
exten => 9999999e1,n,GotoIf($[${CALLERID(num)}=${GVCID}]?gvringback:incoming)
exten => 9999999e1,n(gvringback),Verbose(====> Call is a Google Voice Ringback)
exten => 9999999e1,n,Answer()
exten => 9999999e1,n,ParkedCall(${PARKEXT})
exten => 9999999e1,n,Verbose(====> Ringback Connected)
exten => 9999999e1,n,Return
exten => 9999999e1,n(incoming),Verbose(====> Call is a regular incoming call)
exten => 9999999e1,n,Gosub(internal-call,s,1(${RINGEXT}))
exten => 9999999e1,n,Verbose(====> Execution returned to incoming)
exten => 9999999e1,n,Returnexten => h,1,Verbose(====> End processing incoming sipgate call - call was hung up)
exten => h,n,Return
You’ll need to change9999999e1to your sipgate SIP-ID andGVCIDto your 10-digit Google Voice number - Finally, we’ll add the [internal] extension, where calls from any of our phones end up.
[internal]
; Internal Calls
exten => _100[1-8],1,Verbose(====> Internal call)
exten => _100[1-8],n,GoSub(internal-call,s,1(${EXTEN})
exten => _100[1-8],n,Verbose(====> End internal call)exten => 1009,1,Verbose(====> Dialing voicemail)
exten => 1009,n,VoiceMailMain(@default)
exten => 1009,n,Verbose(====> End dialing voicemail)exten => 1010,1,Verbose(====> Speed dial 15555557777)
exten => 1010,n,GoSub(gv-out,s,1(15555557777))
exten => 1010,n,Verbose(====> End speed dial 15555557777)exten => 3000,1,Verbose(====> Play a test message)
exten => 3000,n,Playback(tt-weasels)
exten => 3000,n,Verbose(====> End playing test message)exten => 911,1,Verbose(====> 911 call)
exten => 911,n,Playback(no-911-1)
exten => 911,n,Hangup()
exten => 911,n,Verbose(====> End 911 call); Outbound Calls
exten => _1NXXNXXXXXX,1,Verbose(====> 11-digit outbound call to ${EXTEN})
exten => _1NXXNXXXXXX,n,GoSub(gv-out,s,1(${EXTEN}))
exten => _1NXXNXXXXXX,n,Verbose(====> End 11-digit outbound call to ${EXTEN})exten => _NXXNXXXXXX,1,Verbose(====> 10-digit outbound call to ${EXTEN})
exten => _NXXNXXXXXX,n,GoSub(gv-out,s,1(1${EXTEN}))
exten => _NXXNXXXXXX,n,Verbose(====> End 10-digit outbound call to ${EXTEN})exten => _NXXXXXX,1,Verbose(====> 7-digit outbound call to ${EXTEN})
exten => _NXXXXXX,n,Set(AREACODE=555)
exten => _NXXXXXX,n,GoSub(gv-out,s,1(1${AREACODE}${EXTEN}))
exten => _NXXXXXX,n,Verbose(====> End 7-digit outbound call to ${EXTEN})
This is the real meat of the dialplan. You’ll want to changeAREACODEto whatever area code you want to use for 7-digit dialing, as well as the number for the speed dial on extension 1010. As you can see, combining pattern matching with naming the SIP channels to match their associated extension number reduces the number of entries required in the dialplan. It also allows us to add more phones by just configuring sip.conf and voicemail.conf, with no changes to the dialplan. - Now, reload the dialplan from the Asterisk CLI
asterisk*CLI> dialplan reload
Now that we’ve configured the dialplan, all that’s left to do is test… (continue)
Hi Kenny,
This is a very cool article. I’m really interested in setting up this system . You think we can do something similar on router that run tomato firmware? or is it too much for the router? I wish you have step by step instruction for the router since I’m fairly new to Linux world. Anyway great post. Thanks