Asterisk For a Small Business (IV)

By | 2012-09-01

When last we spoke, we had created an internal phone system. We had four extensions that could all happily call each other. This time we’re going to extend that facility to include the ability to dial arbitrary numbers using our outgoing trunks.

Recall how we arranged our contexts in the dialplan?

; ... standard code for handling a dialled local extension ...

; ... extension definitions and hints for all our local extensions ...

include => internal-extensions
include => internal-extensions

Also recall that we used the “context=” option in sip.conf to place SIP/andyp, SIP/wife, and SIP/handytone1 in the “[internal-residential]” context; and SIP/handytone2 in the “[internal-business]” context.

At this point, “internal-residential” and “internal-business” behave identically since they both only include the extensions definition. However, our “internal-extensions” context only says what to do for a very limited subset of possible dial strings. What if an endpoint in the “internal” context dials something other than another extension? At the moment – nothing. Let’s change that to “something”.

include => internal-extensions
exten => _0X.,1,Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})

include => internal-extensions
exten => _0X.,1,Dial(SIP/voiptalkOFFICE/${EXTEN})

Asterisk scans the dialplan in the order it’s defined, so when a new call enters, say “internal-residential”, it hits the included “internal-extensions” first. If none of them matches the dialled string, asterisk continues scanning “internal-residential”. Here I’ve added a special extension, “_0X.”. The “_” tells Asterisk that it shouldn’t match this extension literally, instead it should do a pattern match.

  • “_” pattern match
  • “0” match a literal zero. Therefore anything dialled without a zero prefix will not match.
  • “X” match any digit 0-9.
  • “.” match any number of any character

You can therefore read this extension to mean “anything prefixed with a zero”. All UK numbers start with a zero (if you count the area code), so will be handled by this entry. The handler runs the following command:


Here, “${EXTEN}” will be replaced not with the pattern but with the string that matched the pattern – i.e. what the caller dialled. This form of “Dial()” references one of our endpoints that we defined (and named) in sip.conf. In reality, Asterisk looks up the options from sip.conf and translates this to:


But our symbolic form is far more meaningful to us.

Note now that I’ve added a different dial target to each of [internal-residential] and [internal-extensions]. This means when no local extension matches each dials out externally on a different trunk.

For now we’ve addresses the two outgoing requirements from our list:

  • andyp, wife, handytone1 and handytone2 should all be able to ring each other internally.
  • andyp, wife, and handytone1 shall make outgoing calls on voiptalkRESIDENTIAL by default.

We’ll return to the internal part of the dial plan later, but now we turn to how to process incoming calls.

Recall one of our trunk configurations from sip.conf.


Now we’re more familiar with the dialplan, the context and callbackextension options should make more sense. We already know that the context option defines which dialplan context handles inbound calls from this endpoint. Just as we put all our internal endpoints to be handled within an “[internal-extensions]” context, we have put our two external endpoints in an “[external]” context.

What about the dialled extension though? Remember that from the point of view of our trunk provider, we have only one extension, “222222222” in the case of this “voiptalkOFFICE” endpoint. In essence then – there is no information for us to obtain from the dialled extension given by a trunk it will always be our single number. That’s why Asterisk is able to use the callbackextension option as a trigger for registration with the provider, all we’re doing is overriding one fixed piece of information with another (as a fringe benefit it would also address the situation where we had the same username at two providers – how would we tell them apart in the dialplan?). callbackextension then simply defines what Asterisk will rewrite the dialstring to when it runs the dialplan context to handle this incoming call.

Let’s now add an appropriate “[external]” context for these incoming calls from an external trunk.

exten => voiptalkRESIDENTIAL,1,Verbose(1,Incoming call on callbackextension=${EXTEN})
exten => voiptalkRESIDENTIAL,n,Dial(SIP/andyp&SIP/wife&SIP/handytone1)
exten => voiptalkOFFICE,1,Verbose(1,Incoming call on callbackextension=${EXTEN} from ${CALLERID(all)})
exten => voiptalkOFFICE,n,Dial(SIP/andyp&SIP/handytone2)

Here we’ve used Asterisk’s ability to specify multiple endpoints in a single “Dial()” to ring exactly the extensions we wanted in our original spec.

  • andyp, wife, handytone1 and handytone2 should all be able to ring each other internally.
  • andyp, wife, and handytone1 shall make outgoing calls on voiptalkRESIDENTIAL by default.
  • handytone2 shall make outgoing calls on voiptalkOFFICE by default.
  • Incoming calls to voiptalkOFFICE shall ring andyp and handytone2
  • Incoming calls to voiptalkRESIDENTIAL shall ring andyp, wife, and handytone1.

Check, check, check, check, check.

We’ve now got a perfectly workable telephone system. Why stop now though? Next time we’ll look at adding some additional features; in particular: voicemail. Then you can chuck away that answering machine.

asterisk1 asterisk2 asterisk3 asterisk4 asterisk5

Leave a Reply