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,handytone1andhandytone2should all be able to ring each other internally.andyp,wife, andhandytone1shall make outgoing calls onvoiptalkRESIDENTIALby 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,handytone1andhandytone2should all be able to ring each other internally.andyp,wife, andhandytone1shall make outgoing calls onvoiptalkRESIDENTIALby default.handytone2shall make outgoing calls onvoiptalkOFFICEby default.- Incoming calls to
voiptalkOFFICEshall ringandypandhandytone2 - Incoming calls to
voiptalkRESIDENTIALshall 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.