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?
[stdexten]
; ... standard code for handling a dialled local extension ...
[internal-extensions]
; ... extension definitions and hints for all our local extensions ...
[internal-residential]
include => internal-extensions
[internal-business]
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â€.
[internal-residential]
include => internal-extensions
exten => _0X.,1,Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})
[internal-business]
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:
Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})
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:
Dial(SIP/${EXTEN}:password::username@voiptalk.org)
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
andhandytone2
should all be able to ring each other internally.andyp
,wife
, andhandytone1
shall make outgoing calls onvoiptalkRESIDENTIAL
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
.
[voiptalkOFFICE](voiptalk)
defaultuser=222222222
secret=your_222222222_secret_goes_here
fromuser=222222222
context=external
callbackextension=trunkOFFICE
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.
[external]
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
andhandytone2
should all be able to ring each other internally.andyp
,wife
, andhandytone1
shall make outgoing calls onvoiptalkRESIDENTIAL
by default.handytone2
shall make outgoing calls onvoiptalkOFFICE
by default.- Incoming calls to
voiptalkOFFICE
shall ringandyp
andhandytone2
- Incoming calls to
voiptalkRESIDENTIAL
shall ringandyp
,wife
, andhandytone1
.
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.