Asterisk dialplan configuration: Difference between revisions
(3 intermediate revisions by the same user not shown) | |||
Line 32: | Line 32: | ||
Context 사용시 주의해야 할 점은 보안이다. 정확한 방법으로 Context 을 설정한다면 정해진 사용자에게 정해진 기능을 제공할 수 있다. 하지만 엉뚱한 방법으로 Context 를 설정하게 되면, 엉뚱한 기능들이 동작할 수 있다. 게다가 Asterisk 를 위시한 많은 IP-PBX 시스템은 주요 해킹 공격 대상이 된다. 일반적인 Web 과 달리 통화요금 과금과 같이 돈이 관련된 부분이기 때문이다. 때문에 Context 와 같은 Dialplan 설정시 많은 주의를 요한다. | Context 사용시 주의해야 할 점은 보안이다. 정확한 방법으로 Context 을 설정한다면 정해진 사용자에게 정해진 기능을 제공할 수 있다. 하지만 엉뚱한 방법으로 Context 를 설정하게 되면, 엉뚱한 기능들이 동작할 수 있다. 게다가 Asterisk 를 위시한 많은 IP-PBX 시스템은 주요 해킹 공격 대상이 된다. 일반적인 Web 과 달리 통화요금 과금과 같이 돈이 관련된 부분이기 때문이다. 때문에 Context 와 같은 Dialplan 설정시 많은 주의를 요한다. | ||
* ex) 국제전화 사용 | * ex) 국제전화 사용 | ||
==== Special context ==== | |||
Other than special extensions, there is a special context "default" that is used when either a) an extension context is deleted while an extension is in use, or b) a specific starting extension handler has not been defined(unless overridden by the low level channel interface). | |||
=== Extensions === | === Extensions === | ||
Line 54: | Line 57: | ||
==== Special extensions ==== | ==== Special extensions ==== | ||
Asterisk 에는 몇몇 Special Extension 들이 있다. 이 Special Extension 들을 이용하면 특정 상황에서 자동으로 작동하는 Dialplan 을 작성할 수 있다. | |||
* a: Assistant extension | * a: Assistant extension | ||
: This extension is similar to the o extension, only it gets triggered when the caller presses the asterisk (*) key while recording a voice mail message. This is typically used to reach an assistant. | : This extension is similar to the o extension, only it gets triggered when the caller presses the asterisk (*) key while recording a voice mail message. This is typically used to reach an assistant. | ||
Line 76: | Line 81: | ||
: When an analog call comes into Asterisk, the call is sent to the s extension. The s extension is also used in macros. | : When an analog call comes into Asterisk, the call is sent to the s extension. The s extension is also used in macros. | ||
: Please note that the 's' extension is not a catch-all extension. It's simply the location that analog calls and macros begin. | : Please note that the 's' extension is not a catch-all extension. It's simply the location that analog calls and macros begin. | ||
: "s" Extension 은 모든 경우에서 맞아떨어지는 "wildcard" extension 이 아니다. 단지 start extension 일 뿐이다. | |||
: Note: In old versions of Asterisk the PBX in some cases defaulted to extension "s" when a given extension was wrong(like in AMI originate). This is no longer the case. | |||
* t: Response timeout extension | * t: Response timeout extension | ||
Line 194: | Line 201: | ||
* ${SIP_RECVADDR} * : The address a SIP MESSAGE request was received from. | * ${SIP_RECVADDR} * : The address a SIP MESSAGE request was received from. | ||
* ${VOICEMAIL_PLAYBACKSTATUS} * : Status of the VoiceMailPlayMsg application. SUCCESS if the voicemail was played back successfully, FAILED otherwise. | * ${VOICEMAIL_PLAYBACKSTATUS} * : Status of the VoiceMailPlayMsg application. SUCCESS if the voicemail was played back successfully, FAILED otherwise. | ||
== Sample == | |||
<pre> | |||
; extensions.conf - the Asterisk dial plan | |||
; | |||
; Static extension configuration file, used by | |||
; the pbx_config module. This is where you configure all your | |||
; inbound and outbound calls in Asterisk. | |||
; | |||
; This configuration file is reloaded | |||
; - With the "dialplan reload" command in the CLI | |||
; - With the "reload" command (that reloads everything) in the CLI | |||
; | |||
; The "General" category is for certain variables. | |||
; | |||
[general] | |||
; | |||
; If static is set to no, or omitted, then the pbx_config will rewrite | |||
; this file when extensions are modified. Remember that all comments | |||
; made in the file will be lost when that happens. | |||
; | |||
; XXX Not yet implemented XXX | |||
; | |||
static=yes | |||
; | |||
; if static=yes and writeprotect=no, you can save dialplan by | |||
; CLI command "dialplan save" too | |||
; | |||
writeprotect=no | |||
; | |||
; If autofallthrough is set, then if an extension runs out of | |||
; things to do, it will terminate the call with BUSY, CONGESTION | |||
; or HANGUP depending on Asterisk's best guess. This is the default. | |||
; | |||
; If autofallthrough is not set, then if an extension runs out of | |||
; things to do, Asterisk will wait for a new extension to be dialed | |||
; (this is the original behavior of Asterisk 1.0 and earlier). | |||
; | |||
;autofallthrough=no | |||
; | |||
; | |||
; | |||
; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses | |||
; a Trie to find the best matching pattern is used. In dialplans | |||
; with more than about 20-40 extensions in a single context, this | |||
; new algorithm can provide a noticeable speedup. | |||
; With 50 extensions, the speedup is 1.32x | |||
; with 88 extensions, the speedup is 2.23x | |||
; with 138 extensions, the speedup is 3.44x | |||
; with 238 extensions, the speedup is 5.8x | |||
; with 438 extensions, the speedup is 10.4x | |||
; With 1000 extensions, the speedup is ~25x | |||
; with 10,000 extensions, the speedup is 374x | |||
; Basically, the new algorithm provides a flat response | |||
; time, no matter the number of extensions. | |||
; | |||
; By default, the old pattern matcher is used. | |||
; | |||
; ****This is a new feature! ********************* | |||
; The new pattern matcher is for the brave, the bold, and | |||
; the desperate. If you have large dialplans (more than about 50 extensions | |||
; in a context), and/or high call volume, you might consider setting | |||
; this value to "yes" !! | |||
; Please, if you try this out, and are forced to return to the | |||
; old pattern matcher, please report your reasons in a bug report | |||
; on https://issues.asterisk.org. We have made good progress in providing | |||
; something compatible with the old matcher; help us finish the job! | |||
; | |||
; This value can be switched at runtime using the cli command "dialplan set extenpatternmatchnew true" | |||
; or "dialplan set extenpatternmatchnew false", so you can experiment to your hearts content. | |||
; | |||
;extenpatternmatchnew=no | |||
; | |||
; If clearglobalvars is set, global variables will be cleared | |||
; and reparsed on a dialplan reload, or Asterisk reload. | |||
; | |||
; If clearglobalvars is not set, then global variables will persist | |||
; through reloads, and even if deleted from the extensions.conf or | |||
; one of its included files, will remain set to the previous value. | |||
; | |||
; NOTE: A complication sets in, if you put your global variables into | |||
; the AEL file, instead of the extensions.conf file. With clearglobalvars | |||
; set, a "reload" will often leave the globals vars cleared, because it | |||
; is not unusual to have extensions.conf (which will have no globals) | |||
; load after the extensions.ael file (where the global vars are stored). | |||
; So, with "reload" in this particular situation, first the AEL file will | |||
; clear and then set all the global vars, then, later, when the extensions.conf | |||
; file is loaded, the global vars are all cleared, and then not set, because | |||
; they are not stored in the extensions.conf file. | |||
; | |||
clearglobalvars=no | |||
; | |||
; User context is where entries from users.conf are registered. The | |||
; default value is 'default' | |||
; | |||
;userscontext=default | |||
; | |||
; You can include other config files, use the #include command | |||
; (without the ';'). Note that this is different from the "include" command | |||
; that includes contexts within other contexts. The #include command works | |||
; in all asterisk configuration files. | |||
;#include "filename.conf" | |||
;#include <filename.conf> | |||
;#include filename.conf | |||
; | |||
; You can execute a program or script that produces config files, and they | |||
; will be inserted where you insert the #exec command. The #exec command | |||
; works on all asterisk configuration files. However, you will need to | |||
; activate them within asterisk.conf with the "execincludes" option. They | |||
; are otherwise considered a security risk. | |||
;#exec /opt/bin/build-extra-contexts.sh | |||
;#exec /opt/bin/build-extra-contexts.sh --foo="bar" | |||
;#exec </opt/bin/build-extra-contexts.sh --foo="bar"> | |||
;#exec "/opt/bin/build-extra-contexts.sh --foo=\"bar\"" | |||
; | |||
; The "Globals" category contains global variables that can be referenced | |||
; in the dialplan with the GLOBAL dialplan function: | |||
; ${GLOBAL(VARIABLE)} | |||
; ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid | |||
; Unix/Linux environmental variables can be reached with the ENV dialplan | |||
; function: ${ENV(VARIABLE)} | |||
; | |||
[globals] | |||
CONSOLE=Console/dsp ; Console interface for demo | |||
;CONSOLE=DAHDI/1 | |||
;CONSOLE=Phone/phone0 | |||
IAXINFO=guest ; IAXtel username/password | |||
;IAXINFO=myuser:mypass | |||
TRUNK=DAHDI/G2 ; Trunk interface | |||
; | |||
; Note the 'G2' in the TRUNK variable above. It specifies which group (defined | |||
; in chan_dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use | |||
; in the specified group. The four possible options are: | |||
; | |||
; g: select the lowest-numbered non-busy DAHDI channel | |||
; (aka. ascending sequential hunt group). | |||
; G: select the highest-numbered non-busy DAHDI channel | |||
; (aka. descending sequential hunt group). | |||
; r: use a round-robin search, starting at the next highest channel than last | |||
; time (aka. ascending rotary hunt group). | |||
; R: use a round-robin search, starting at the next lowest channel than last | |||
; time (aka. descending rotary hunt group). | |||
; | |||
TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0) | |||
;TRUNK=IAX2/user:pass@provider | |||
;FREENUMDOMAIN=mydomain.com ; domain to send on outbound | |||
; freenum calls (uses outbound-freenum | |||
; context) | |||
; | |||
; WARNING WARNING WARNING WARNING | |||
; If you load any other extension configuration engine, such as pbx_ael.so, | |||
; your global variables may be overridden by that file. Please take care to | |||
; use only one location to set global variables, and you will likely save | |||
; yourself a ton of grief. | |||
; WARNING WARNING WARNING WARNING | |||
; | |||
; Any category other than "General" and "Globals" represent | |||
; extension contexts, which are collections of extensions. | |||
; | |||
; Extension names may be numbers, letters, or combinations | |||
; thereof. If an extension name is prefixed by a '_' | |||
; character, it is interpreted as a pattern rather than a | |||
; literal. In patterns, some characters have special meanings: | |||
; | |||
; X - any digit from 0-9 | |||
; Z - any digit from 1-9 | |||
; N - any digit from 2-9 | |||
; [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) | |||
; . - wildcard, matches anything remaining (e.g. _9011. matches | |||
; anything starting with 9011 excluding 9011 itself) | |||
; ! - wildcard, causes the matching process to complete as soon as | |||
; it can unambiguously determine that no other matches are possible | |||
; | |||
; For example, the extension _NXXXXXX would match normal 7 digit dialings, | |||
; while _1NXXNXXXXXX would represent an area code plus phone number | |||
; preceded by a one. | |||
; | |||
; Each step of an extension is ordered by priority, which must always start | |||
; with 1 to be considered a valid extension. The priority "next" or "n" means | |||
; the previous priority plus one, regardless of whether the previous priority | |||
; was associated with the current extension or not. The priority "same" or "s" | |||
; means the same as the previously specified priority, again regardless of | |||
; whether the previous entry was for the same extension. Priorities may be | |||
; immediately followed by a plus sign and another integer to add that amount | |||
; (most useful with 's' or 'n'). Priorities may then also have an alias, or | |||
; label, in parentheses after their name which can be used in goto situations. | |||
; | |||
; Contexts contain several lines, one for each step of each extension. One may | |||
; include another context in the current one as well, optionally with a date | |||
; and time. Included contexts are included in the order they are listed. | |||
; Switches may also be included within a context. The order of matching within | |||
; a context is always exact extensions, pattern match extensions, includes, and | |||
; switches. Includes are always processed depth-first. So for example, if you | |||
; would like a switch "A" to match before context "B", simply put switch "A" in | |||
; an included context "C", where "C" is included in your original context | |||
; before "B". | |||
; | |||
;[context] | |||
; | |||
;autohints = yes | |||
; If enabled for a context, a device state hint will be automatically created in | |||
; the context with the name of the device and updated with device state changes. | |||
; | |||
;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...) | |||
; | |||
; Timing list for includes is | |||
; | |||
; <time range>,<days of week>,<days of month>,<months>[,<timezone>] | |||
; | |||
; Note that ranges may be specified to wrap around the ends. Also, minutes are | |||
; fine-grained only down to the closest even minute. | |||
; | |||
;include => daytime,9:00-17:00,mon-fri,*,* | |||
;include => weekend,*,sat-sun,*,* | |||
;include => weeknights,17:02-8:58,mon-fri,*,* | |||
; | |||
; ignorepat can be used to instruct drivers to not cancel dialtone upon receipt | |||
; of a particular pattern. The most commonly used example is of course '9' | |||
; like this: | |||
; | |||
;ignorepat => 9 | |||
; | |||
; so that dialtone remains even after dialing a 9. Please note that ignorepat | |||
; only works with channels which receive dialtone from the PBX, such as DAHDI, | |||
; Phone, and VPB. Other channels, such as SIP and MGCP, which generate their | |||
; own dialtone and converse with the PBX only after a number is complete, are | |||
; generally unaffected by ignorepat (unless DISA or another method is used to | |||
; generate a dialtone after answering the channel). | |||
; | |||
; | |||
; Sample entries for extensions.conf | |||
; | |||
; | |||
[dundi-e164-canonical] | |||
;include => stdexten | |||
; | |||
; List canonical entries here | |||
; | |||
;exten => 12564286000,1,Gosub(6000,stdexten(IAX2/foo)) | |||
;exten => 12564286000,n,Goto(default,s,1) ; exited Voicemail | |||
;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7}) | |||
[dundi-e164-customers] | |||
; | |||
; If you are an ITSP or Reseller, list your customers here. | |||
; | |||
;exten => _12564286000,1,Dial(SIP/customer1) | |||
;exten => _12564286001,1,Dial(IAX2/customer2) | |||
[dundi-e164-via-pstn] | |||
; | |||
; If you are freely delivering calls to the PSTN, list them here | |||
; | |||
;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428 | |||
;exten => _1256325XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Ditto for 256-325 | |||
[dundi-e164-local] | |||
; | |||
; Context to put your dundi IAX2 or SIP user in for | |||
; full access | |||
; | |||
include => dundi-e164-canonical | |||
include => dundi-e164-customers | |||
include => dundi-e164-via-pstn | |||
[dundi-e164-switch] | |||
; | |||
; Just a wrapper for the switch | |||
; | |||
switch => DUNDi/e164 | |||
[dundi-e164-lookup] | |||
; | |||
; Locally to lookup, try looking for a local E.164 solution | |||
; then try DUNDi if we don't have one. | |||
; | |||
include => dundi-e164-local | |||
include => dundi-e164-switch | |||
; | |||
; DUNDi can also be implemented as a Macro instead of using | |||
; the Local channel driver. | |||
; | |||
[macro-dundi-e164] | |||
; | |||
; ARG1 is the extension to Dial | |||
; | |||
; Extension "s" is not a wildcard extension that matches "anything". | |||
; In macros, it is the start extension. In most other cases, | |||
; you have to goto "s" to execute that extension. | |||
; | |||
; Note: In old versions of Asterisk the PBX in some cases defaulted to | |||
; extension "s" when a given extension was wrong (like in AMI originate). | |||
; This is no longer the case. | |||
; | |||
; For wildcard matches, see above - all pattern matches start with | |||
; an underscore. | |||
exten => s,1,Goto(${ARG1},1) | |||
include => dundi-e164-lookup | |||
; | |||
; Here are the entries you need to participate in the IAXTEL | |||
; call routing system. Most IAXTEL numbers begin with 1-700, but | |||
; there are exceptions. For more information, and to sign | |||
; up, please go to www.gnophone.com or www.iaxtel.com | |||
; | |||
[iaxtel700] | |||
exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxtel) | |||
; | |||
; The SWITCH statement permits a server to share the dialplan with | |||
; another server. Use with care: Reciprocal switch statements are not | |||
; allowed (e.g. both A -> B and B -> A), and the switched server needs | |||
; to be on-line or else dialing can be severly delayed. | |||
; | |||
[iaxprovider] | |||
;switch => IAX2/user:[key]@myserver/mycontext | |||
[trunkint] | |||
; | |||
; International long distance through trunk | |||
; | |||
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4}) | |||
exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})}) | |||
[trunkld] | |||
; | |||
; Long distance context accessed through trunk | |||
; | |||
exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1}) | |||
exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
[trunklocal] | |||
; | |||
; Local seven-digit dialing accessed through trunk interface | |||
; | |||
exten => _9NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
[trunktollfree] | |||
; | |||
; Long distance context accessed through trunk interface | |||
; | |||
exten => _91800NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
exten => _91888NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
exten => _91877NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
exten => _91866NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) | |||
[international] | |||
; | |||
; Master context for international long distance | |||
; | |||
ignorepat => 9 | |||
include => longdistance | |||
include => trunkint | |||
[longdistance] | |||
; | |||
; Master context for long distance | |||
; | |||
ignorepat => 9 | |||
include => local | |||
include => trunkld | |||
[local] | |||
; | |||
; Master context for local, toll-free, and iaxtel calls only | |||
; | |||
ignorepat => 9 | |||
include => default | |||
include => trunklocal | |||
include => iaxtel700 | |||
include => trunktollfree | |||
include => iaxprovider | |||
;Include parkedcalls (or the context you define in features conf) | |||
;to enable call parking. | |||
include => parkedcalls | |||
; | |||
; You can use an alternative switch type as well, to resolve | |||
; extensions that are not known here, for example with remote | |||
; IAX switching you transparently get access to the remote | |||
; Asterisk PBX | |||
; | |||
; switch => IAX2/user:password@bigserver/local | |||
; | |||
; An "lswitch" is like a switch but is literal, in that | |||
; variable substitution is not performed at load time | |||
; but is passed to the switch directly (presumably to | |||
; be substituted in the switch routine itself) | |||
; | |||
; lswitch => Loopback/12${EXTEN}@othercontext | |||
; | |||
; An "eswitch" is like a switch but the evaluation of | |||
; variable substitution is performed at runtime before | |||
; being passed to the switch routine. | |||
; | |||
; eswitch => IAX2/context@${CURSERVER} | |||
; The following two contexts are a template to enable the ability to dial | |||
; ISN numbers. For more information about what an ISN number is, please see | |||
; http://www.freenum.org. | |||
; | |||
; This is the dialing hook. use: | |||
; include => outbound-freenum | |||
[outbound-freenum] | |||
; We'll add more digits as needed. The purpose is to dial things | |||
; like extension numbers at domains (ITAD number) so we're matching | |||
; on lengths of 1 through 6 prior to the separator (the asterisk [*]) | |||
; | |||
exten => _X*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
exten => _XX*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
exten => _XXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
exten => _XXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
exten => _XXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
exten => _XXXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) | |||
[outbound-freenum2] | |||
; This is the handler which performs the dialing logic. It is called | |||
; from the [outbound-freenum] context | |||
; | |||
exten => _X!,1,Verbose(2,Performing ISN lookup for ${EXTEN}) | |||
same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)}) ; make sure the suffix is all digits as well | |||
same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1) | |||
; filter out bad characters per the README-SERIOUSLY.best-practices.txt document | |||
same => n,Set(TIMEOUT(absolute)=10800) | |||
same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)}) ; perform our lookup with freenum.org | |||
same => n,GotoIf($["${isnresult}" != ""]?from) | |||
same => n,Set(DIALSTATUS=CONGESTION) | |||
same => n,Goto(fn-CONGESTION,1) | |||
same => n(from),Set(__SIPFROMUSER=${CALLERID(num)}) | |||
same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial) ; check if we set the FREENUMDOMAIN global variable in [global] | |||
same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)}) ; if we did set it, then we'll use it for our outbound dialing domain | |||
same => n(dial),Dial(SIP/${isnresult},40) | |||
same => n,Goto(fn-${DIALSTATUS},1) | |||
exten => fn-BUSY,1,Busy() | |||
exten => _f[n]-.,1,NoOp(ISN: ${DIALSTATUS}) | |||
same => n,Congestion() | |||
[macro-trunkdial] | |||
; | |||
; Standard trunk dial macro (hangs up on a dialstatus that should | |||
; terminate call) | |||
; ${ARG1} - What to dial | |||
; | |||
exten => s,1,Dial(${ARG1}) | |||
exten => s,n,Goto(s-${DIALSTATUS},1) | |||
exten => s-NOANSWER,1,Hangup() | |||
exten => s-BUSY,1,Hangup() | |||
exten => _s-.,1,NoOp | |||
[stdexten] | |||
; | |||
; Standard extension subroutine: | |||
; ${EXTEN} - Extension | |||
; ${ARG1} - Device(s) to ring | |||
; ${ARG2} - Optional context in Voicemail | |||
; | |||
; Note that the current version will drop through to the next priority in the | |||
; case of their pressing '#'. This gives more flexibility in what do to next: | |||
; you can prompt for a new extension, or drop the call, or send them to a | |||
; general delivery mailbox, or... | |||
; | |||
; The use of the LOCAL() function is purely for convenience. Any variable | |||
; initially declared as LOCAL() will disappear when the innermost Gosub context | |||
; in which it was declared returns. Note also that you can declare a LOCAL() | |||
; variable on top of an existing variable, and its value will revert to its | |||
; previous value (before being declared as LOCAL()) upon Return. | |||
; | |||
exten => _X.,50000(stdexten),NoOp(Start stdexten) | |||
exten => _X.,n,Set(LOCAL(ext)=${EXTEN}) | |||
exten => _X.,n,Set(LOCAL(dev)=${ARG1}) | |||
exten => _X.,n,Set(LOCAL(cntx)=${ARG2}) | |||
exten => _X.,n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})}) | |||
exten => _X.,n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum | |||
exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) | |||
exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce | |||
exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start | |||
exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce | |||
exten => stdexten-BUSY,n,Return() ; If they press #, return to start | |||
exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer | |||
exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain | |||
exten => a,n,Return() | |||
[stdPrivacyexten] | |||
; | |||
; Standard extension subroutine: | |||
; ${ARG1} - Extension | |||
; ${ARG2} - Device(s) to ring | |||
; ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority) | |||
; ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)` | |||
; ${ARG5} - Context in voicemail (if empty, then "default") | |||
; | |||
; See above note in stdexten about priority handling on exit. | |||
; | |||
exten => _X.,60000(stdPrivacyexten),NoOp(Start stdPrivacyexten) | |||
exten => _X.,n,Set(LOCAL(ext)=${ARG1}) | |||
exten => _X.,n,Set(LOCAL(dev)=${ARG2}) | |||
exten => _X.,n,Set(LOCAL(dontcntx)=${ARG3}) | |||
exten => _X.,n,Set(LOCAL(tortcntx)=${ARG4}) | |||
exten => _X.,n,Set(LOCAL(cntx)=${ARG5}) | |||
exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""]) | |||
exten => _X.,n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening | |||
; option (or use P for databased call _X.creening) | |||
exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) | |||
exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce | |||
exten => stdexten-NOANSWER,n,NoOp(Finish stdPrivacyexten NOANSWER) | |||
exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start | |||
exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce | |||
exten => stdexten-BUSY,n,NoOp(Finish stdPrivacyexten BUSY) | |||
exten => stdexten-BUSY,n,Return() ; If they press #, return to start | |||
exten => stdexten-DONTCALL,1,Goto(${dontcntx},s,1) ; Callee chose to send this call to a polite "Don't call again" script. | |||
exten => stdexten-TORTURE,1,Goto(${tortcntx},s,1) ; Callee chose to send this call to a telemarketer torture script. | |||
exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer | |||
exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain | |||
exten => a,n,Return() | |||
[macro-page] | |||
; | |||
; Paging macro: | |||
; | |||
; Check to see if SIP device is in use and DO NOT PAGE if they are | |||
; | |||
; ${ARG1} - Device to page | |||
exten => s,1,ChanIsAvail(${ARG1},s) ; s is for ANY call | |||
exten => s,n,GotoIf($[${AVAILSTATUS} = "1"]?autoanswer:fail) | |||
exten => s,n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs | |||
exten => s,n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others | |||
exten => s,n,NoOp() ; Add others here and Post on the Wiki!!!! | |||
exten => s,n,Dial(${ARG1}) | |||
exten => s,n(fail),Hangup() | |||
[demo] | |||
include => stdexten | |||
; | |||
; We start with what to do when a call first comes in. | |||
; | |||
exten => s,1,Wait(1) ; Wait a second, just for fun | |||
exten => s,n,Answer() ; Answer the line | |||
exten => s,n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds | |||
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds | |||
exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message | |||
exten => s,n(instruct),BackGround(demo-instruct) ; Play some instructions | |||
exten => s,n,WaitExten() ; Wait for an extension to be dialed. | |||
exten => 2,1,BackGround(demo-moreinfo) ; Give some more information. | |||
exten => 2,n,Goto(s,instruct) | |||
exten => 3,1,Set(CHANNEL(language)=fr) ; Set language to french | |||
exten => 3,n,Goto(s,restart) ; Start with the congratulations | |||
exten => 1000,1,Goto(default,s,1) | |||
; | |||
; We also create an example user, 1234, who is on the console and has | |||
; voicemail, etc. | |||
; | |||
exten => 1234,1,Playback(transfer,skip) ; "Please hold while..." | |||
; (but skip if channel is not up) | |||
exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)})) | |||
exten => 1234,n,Goto(default,s,1) ; exited Voicemail | |||
exten => 1235,1,VoiceMail(1234,u) ; Right to voicemail | |||
exten => 1236,1,Dial(Console/dsp) ; Ring forever | |||
exten => 1236,n,VoiceMail(1234,b) ; Unless busy | |||
; | |||
; # for when they're done with the demo | |||
; | |||
exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo" | |||
exten => #,n,Hangup() ; Hang them up. | |||
; | |||
; A timeout and "invalid extension rule" | |||
; | |||
exten => t,1,Goto(#,1) ; If they take too long, give up | |||
exten => i,1,Playback(invalid) ; "That's not valid, try again" | |||
; | |||
; Create an extension, 500, for dialing the | |||
; Asterisk demo. | |||
; | |||
exten => 500,1,Playback(demo-abouttotry) ; Let them know what's going on | |||
exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo | |||
exten => 500,n,Playback(demo-nogo) ; Couldn't connect to the demo site | |||
exten => 500,n,Goto(s,6) ; Return to the start over message. | |||
; | |||
; Create an extension, 600, for evaluating echo latency. | |||
; | |||
exten => 600,1,Playback(demo-echotest) ; Let them know what's going on | |||
exten => 600,n,Echo() ; Do the echo test | |||
exten => 600,n,Playback(demo-echodone) ; Let them know it's over | |||
exten => 600,n,Goto(s,6) ; Start over | |||
; | |||
; You can use the Macro Page to intercom a individual user | |||
exten => 76245,1,Macro(page,SIP/Grandstream1) | |||
; or if your peernames are the same as extensions | |||
exten => _7XXX,1,Macro(page,SIP/${EXTEN}) | |||
; | |||
; | |||
; System Wide Page at extension 7999 | |||
; | |||
exten => 7999,1,Set(TIMEOUT(absolute)=60) | |||
exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d) | |||
; Give voicemail at extension 8500 | |||
; | |||
exten => 8500,1,VoiceMailMain() | |||
exten => 8500,n,Goto(s,6) | |||
; | |||
; Here's what a phone entry would look like (IXJ for example) | |||
; | |||
;exten => 1265,1,Dial(Phone/phone0,15) | |||
;exten => 1265,n,Goto(s,5) | |||
; | |||
; The page context calls up the page macro that sets variables needed for auto-answer | |||
; It is in is own context to make calling it from the Page() application as simple as | |||
; Local/{peername}@page | |||
; | |||
[page] | |||
exten => _X.,1,Macro(page,SIP/${EXTEN}) | |||
;[mainmenu] | |||
; | |||
; Example "main menu" context with submenu | |||
; | |||
;exten => s,1,Answer | |||
;exten => s,n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..." | |||
;exten => s,n,WaitExten | |||
;exten => 1,1,Goto(submenu,s,1) | |||
;exten => 2,1,Hangup | |||
;include => default | |||
; | |||
;[submenu] | |||
;exten => s,1,Ringing ; Make them comfortable with 2 seconds of ringback | |||
;exten => s,n,Wait,2 | |||
;exten => s,n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..." | |||
;exten => s,n,WaitExten | |||
;exten => 1,1,Goto(default,steve,1) | |||
;exten => 2,1,Goto(default,mark,2) | |||
[public] | |||
; | |||
; ATTENTION: If your Asterisk is connected to the internet and you do | |||
; not have allowguest=no in sip.conf, everybody out there may use your | |||
; public context without authentication. In that case you want to | |||
; double check which services you offer to the world. | |||
; | |||
include => demo | |||
[default] | |||
; | |||
; By default we include the demo. In a production system, you | |||
; probably don't want to have the demo there. | |||
; | |||
include => demo | |||
; | |||
; An extension like the one below can be used for FWD, Nikotel, sipgate etc. | |||
; Note that you must have a [sipprovider] section in sip.conf | |||
; | |||
;exten => _41X.,1,Dial(SIP/${FILTER(0-9,${EXTEN:2})}@sipprovider,,r) | |||
; Real extensions would go here. Generally you want real extensions to be | |||
; 4 or 5 digits long (although there is no such requirement) and start with a | |||
; single digit that is fairly large (like 6 or 7) so that you have plenty of | |||
; room to overlap extensions and menu options without conflict. You can alias | |||
; them with names, too, and use global variables | |||
;exten => 6245,hint,SIP/Grandstream1&SIP/Xlite1(Joe Schmoe) ; Channel hints for presence | |||
;exten => 6245,1,Dial(SIP/Grandstream1,20,rt) ; permit transfer | |||
;exten => 6245,n(dial),Dial(${HINT},20,rtT) ; Use hint as listed | |||
;exten => 6245,n,VoiceMail(6245,u) ; Voicemail (unavailable) | |||
;exten => 6245,s+1,Hangup ; s+1, same as n | |||
;exten => 6245,dial+101,VoiceMail(6245,b) ; Voicemail (busy) | |||
;exten => 6361,1,Dial(IAX2/JaneDoe,,rm) ; ring without time limit | |||
;exten => 6389,1,Dial(MGCP/aaln/1@192.168.0.14) | |||
;exten => 6390,1,Dial(JINGLE/caller/callee) ; Dial via jingle using labels | |||
;exten => 6391,1,Dial(JINGLE/asterisk@digium.com/mogorman@astjab.org) ;Dial via jingle using asterisk as the transport and calling mogorman. | |||
;exten => 6394,1,Dial(Local/6275/n) ; this will dial ${MARK} | |||
;exten => 6275,1,Gosub(${EXTEN},stdexten(${MARK})) | |||
; assuming ${MARK} is something like DAHDI/2 | |||
;exten => 6275,n,Goto(default,s,1) ; exited Voicemail | |||
;exten => mark,1,Goto(6275,1) ; alias mark to 6275 | |||
;exten => 6536,1,Gosub(${EXTEN},stdexten(${WIL})) | |||
; Ditto for wil | |||
;exten => 6536,n,Goto(default,s,1) ; exited Voicemail | |||
;exten => wil,1,Goto(6236,1) | |||
;If you want to subscribe to the status of a parking space, this is | |||
;how you do it. Subscribe to extension 6600 in sip, and you will see | |||
;the status of the first parking lot with this extensions' help | |||
;exten => 6600,hint,park:701@parkedcalls | |||
;exten => 6600,1,noop | |||
; | |||
;To subscribe to the availability of a free member in the 'markq' queue. | |||
;Note: '_avail' is added to the QueueName | |||
;exten => 8501,hint,Queue:markq_avail | |||
;exten => 8501,1,Queue(markq) | |||
; | |||
; You can also monitor the status of a queue by providing a hint for a | |||
; particular queue name. | |||
;exten => 8502,hint,Queue:markq | |||
;exten => 8502,1,Queue(markq) | |||
; | |||
; Some other handy things are an extension for checking voicemail via | |||
; voicemailmain | |||
; | |||
;exten => 8500,1,VoicemailMain | |||
;exten => 8500,n,Hangup | |||
; | |||
; Or a conference room (you'll need to edit meetme.conf to enable this room) | |||
; | |||
;exten => 8600,1,Meetme(1234) | |||
; | |||
; Or playing an announcement to the called party, as soon it answers | |||
; | |||
;exten = 8700,1,Dial(${MARK},30,A(/path/to/my/announcemsg)) | |||
; | |||
; example of a compartmentalized company called "acme" | |||
; | |||
; this is the context that your incoming IAX/SIP trunk dumps you in... | |||
;[acme-incoming] | |||
;exten => s,1,Wait(1) | |||
;exten => s,n,Answer() | |||
;exten => s,n(menu),Playback(acme/vm-brief-menu) | |||
;exten => s,n(exten),Background(vm-enter-num-to-call) | |||
;exten => s,n,WaitExten(5) | |||
;exten => s,n(goodbye),Playback(vm-goodbye) | |||
;exten => s,n(end),Hangup() | |||
; | |||
;include => acme-extens | |||
; | |||
;exten => i,1,Playback(vm-invalid) | |||
;exten => i,n,Goto(s,exten) ; optionally, transfer to operator | |||
; | |||
;exten => t,1,Goto(s,goodbye) | |||
; | |||
; this is the context our internal SIP hardphones use (see sip.conf) | |||
; | |||
;[acme-internal] | |||
;exten => s,1,Answer() | |||
;exten => s,n(exten),Background(vm-enter-num-to-call) | |||
;exten => s,n,WaitExten(5) | |||
;exten => s,n(goodbye),Playback(vm-goodbye) | |||
;exten => s,n(end),Hangup() | |||
; | |||
;include => trunkint | |||
;include => trunkld | |||
;include => trunklocal | |||
; | |||
;include => acme-extens | |||
; | |||
; you can test what your system sounds like to outside callers by dialing this | |||
;exten => 777,1,DISA(no-password,acme-incoming) | |||
; | |||
; grouping of acme's extensions... never used directly, always included. | |||
; | |||
;[acme-extens] | |||
;include => stdexten | |||
;exten => 111,1,Gosub(111,stdexten(SIP/pete_1,acme)) | |||
;exten => 111,n,Goto(s,exten) | |||
; | |||
;exten => 112,1,Gosub(112,stdexten(SIP/nancy_1,acme)) | |||
;exten => 112,n,Goto(s,end) | |||
; | |||
; end of acme example | |||
; | |||
; Time context: you can patch this in via the following. | |||
; | |||
; [acme-internal] | |||
; ... | |||
; exten => 777,1,Gosub(time) | |||
; exten => 777,n,Hangup() | |||
; | |||
; ... | |||
; include => time | |||
; | |||
; Note: if you're geographically spread out, you can have SIP extensions | |||
; specify their own local timezone in sip.conf as: | |||
; | |||
; [boi] | |||
; type=friend | |||
; context=acme-internal | |||
; callerid="Boise Ofc. <2083451111>" | |||
; ... | |||
; ; use system-wide default timezone of MST7MDT | |||
; | |||
; [lws] | |||
; type=friend | |||
; context=acme-internal | |||
; callerid="Lewiston Ofc. <2087431111>" | |||
; ... | |||
; setvar=timezone=PST8PDT | |||
; | |||
; "timezone" isn't a 'reserved' name in any way, and other places where | |||
; the timezone is significant (e.g. calls to "SayUnixTime()", etc) will | |||
; require modification as well. Note that voicemail.conf already has | |||
; a mechanism for timezones. | |||
; | |||
[time] | |||
exten => _X.,30000(time),NoOp(Time: ${EXTEN} ${timezone}) | |||
exten => _X.,n,Wait(0.25) | |||
exten => _X.,n,Answer() | |||
; the amount of delay is set for English; you may need to adjust this time | |||
; for other languages if there's no pause before the synchronizing beep. | |||
exten => _X.,n,Set(FUTURETIME=$[${EPOCH} + 12]) | |||
exten => _X.,n,SayUnixTime(${FUTURETIME},Zulu,HNS) | |||
exten => _X.,n,SayPhonetic(z) | |||
; use the timezone associated with the extension (sip only), or system-wide | |||
; default if one hasn't been set. | |||
exten => _X.,n,SayUnixTime(${FUTURETIME},${timezone},HNS) | |||
exten => _X.,n,Playback(spy-local) | |||
exten => _X.,n,WaitUntil(${FUTURETIME}) | |||
exten => _X.,n,Playback(beep) | |||
exten => _X.,n,Return() | |||
; | |||
; ANI context: use in the same way as "time" above | |||
; | |||
[ani] | |||
exten => _X.,40000(ani),NoOp(ANI: ${EXTEN}) | |||
exten => _X.,n,Wait(0.25) | |||
exten => _X.,n,Answer() | |||
exten => _X.,n,Playback(vm-from) | |||
exten => _X.,n,SayDigits(${CALLERID(ani)}) | |||
exten => _X.,n,Wait(1.25) | |||
exten => _X.,n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit | |||
exten => _X.,n,Return() | |||
; For more information on applications, just type "core show applications" at your | |||
; friendly Asterisk CLI prompt. | |||
; | |||
; "core show application <command>" will show details of how you | |||
; use that particular application in this file, the dial plan. | |||
; "core show functions" will list all dialplan functions | |||
; "core show function <COMMAND>" will show you more information about | |||
; one function. Remember that function names are UPPER CASE. | |||
</pre> | |||
== See also == | == See also == |
Latest revision as of 22:27, 19 July 2019
개요
Asterisk Dialplan 설정 법 설명.
Dialplan syntax
Asterisk 에서 Dialplan 을 설정하는 파일 이름은 extensions.conf 이다.
- extensions.conf
- 보통은 /etc/asterisk/extensions.conf 에 위치해 있다.
- 하지만 소스로 설치를 하거나 다른 방법으로 설치하게 되면 다른곳에 파일이 위치할 수도 있다.
ex) /usr/local/etc/asterisk, /opt/etc/asterisk
Dialplan 은 크게 4가지 컨셉으로 구성되어 있다.
contexts, extensions, priorities, applications
Context
Context 는 쉽게 말해서 객체지향의 Class 와 비슷한 개념으로 볼 수 있다.
Context 를 생성할 때는 Context 이름을 중괄호([])로 감싸야한다. 이름에 사용할 수 있는 문자는 A-Z, a-z, 0-9, -, _ 이다.
[incoming]
- Context 생성시 사용가능한 문자 길이는 최대 79 자 이다. (80 characters - 1 terminating null).
Context 에는 특별히 사용되는 특수 Context 두 가지가 있는데, [general] 과 [globals] 이다. [general] 섹션은 일반적인 Dialplan 설정들, [globals] 섹션에는 전역 Dialplan 설정들이 있는 Context 이다. 새로운 Context 생성시 [general], [globals], [default] 이름은 피하도록 하자. 이 외의 다른 이름은 전부 사용 가능하다.
채널을 설정할 경우(sip.conf, iax.conf, chan_dahdi.conf 등등..) 필수 입력 항목중에 context 항목이 있다. Context 는 호간의 연결 성립시, 채널이 동작하게되는 Dialplan 의 시작점이다. 즉, Asterisk 에 등록된 채널 A 가 있을 경우, 만약 A 로 전화가 걸려왔을 때, 어떤 방식으로 전화가 흘러가게끔 할 것인지를 결정하게 되는 것이다.
- 전화(Connection)가 걸려왔을 경우 정해진 수순에 따라 전화가 흘러가게끔 하는 것, 이것이 Dialplan 이다.
- ex) 10초동안 응답이 없을 경우 자동 IVR 연결, 10초 동안 연결이 없을 경우 휴대폰 전화로 연결 등등..
Context 사용시 주의해야 할 점은 보안이다. 정확한 방법으로 Context 을 설정한다면 정해진 사용자에게 정해진 기능을 제공할 수 있다. 하지만 엉뚱한 방법으로 Context 를 설정하게 되면, 엉뚱한 기능들이 동작할 수 있다. 게다가 Asterisk 를 위시한 많은 IP-PBX 시스템은 주요 해킹 공격 대상이 된다. 일반적인 Web 과 달리 통화요금 과금과 같이 돈이 관련된 부분이기 때문이다. 때문에 Context 와 같은 Dialplan 설정시 많은 주의를 요한다.
- ex) 국제전화 사용
Special context
Other than special extensions, there is a special context "default" that is used when either a) an extension context is deleted while an extension is in use, or b) a specific starting extension handler has not been defined(unless overridden by the low level channel interface).
Extensions
Extensions 흔히 전화번호로도 번역이 된다. 하지만 Asterisk 에서의 Extensions 는 더 강력한 기능을 가진다.
Asterisk 에서는 각각의 Context 마다 하나 혹은 다수의 Extensions 를 가질 수 있다. 해당 Extension 이 동작할 경우(전화가 걸려온 경우), Asterisk 는 해당 Extension 에 설정된 Dialplan 을 수행하는 것이다.
Extension 설정시, exten 구문으로 시작하게 된다.
exten =>
Extension 은 세가지 구성요소들을 가진다.
- name(or number)
- priority
- application
이 구성 요소들은 쉼표(,)로 구분된다.
exten => name, priority, application()
Special extensions
Asterisk 에는 몇몇 Special Extension 들이 있다. 이 Special Extension 들을 이용하면 특정 상황에서 자동으로 작동하는 Dialplan 을 작성할 수 있다.
- a: Assistant extension
- This extension is similar to the o extension, only it gets triggered when the caller presses the asterisk (*) key while recording a voice mail message. This is typically used to reach an assistant.
- e: Exception catchall extension
- This extension will substitute as a catchall for any of the 'i', 't' or 'T' extensions, if any of them do not exist and catching the error in a single routine is desired.
- The function EXCEPTION may be used to query the type of exception or the location where it occurred.
- h: Hangup extension
- When a call is hung up, Asterisk executes the h extension in the current context.
- This is typically used for some sort of clean-up after a call has been completed.
- i: Invalid entry extension
- If Asterisk can't find an extension in the current context that matches the digits during the Background() or EaitExten() applications, it will send the call to the i extension.
- You can then handle the call however you see fit.
- o: Operator extension
- If a caller presses the zero key on their phone keypad while recording a voice mail message, and the o extension exists, the caller will be redirected to the o extension.
- This is typically used so that the caller can press zero to reach an operator.
- s: Start extension
- When an analog call comes into Asterisk, the call is sent to the s extension. The s extension is also used in macros.
- Please note that the 's' extension is not a catch-all extension. It's simply the location that analog calls and macros begin.
- "s" Extension 은 모든 경우에서 맞아떨어지는 "wildcard" extension 이 아니다. 단지 start extension 일 뿐이다.
- Note: In old versions of Asterisk the PBX in some cases defaulted to extension "s" when a given extension was wrong(like in AMI originate). This is no longer the case.
- t: Response timeout extension
- When the caller waits too long before entering a response to the Background() or WaitExten() applications, and there are no more priorities in the current extension, the call is sent to the t extension.
- T: Absolute timeout extension
- This is the extension that is executed when the 'absolute' timeout is reached. See "core show function TIMEOUT" for more information on setting timeouts.
Pattern Matching
원문은 이곳<ref>https://wiki.asterisk.org/wiki/display/AST/Pattern+Matching</ref>에서 확인할 수 있다.
패턴 매칭은 항상 "_" 기호로 시작한다. 해당 기호로 시작해야지만 Asterisk 에서 패턴 매칭을 사용한다는 것을 인식할 수 있기 때문이다.
X, Z, N
X, Z, N 은 가장 흔히 사용하는 패턴 매칭 기호이다.
- X
- X/x 대/소문자 구분이 없다. 0 ~ 9 까지의 하나의 숫자를 의미한다.
- Z
- Z/z 대/소문자 구분이 없다. 1 ~ 9 까지의 하나의 숫자를 의미한다.
- N
- N/n 대/소문자 구분이 없다. 2 ~ 9 까지의 하나의 숫자를 의미한다.
- Example
- 예제를 들어보자. 다음은 6400 부터 6499 까지 의 번호를 매칭하는 패턴이다.
exten => _64XX,1,SayDigits(${EXTEN})
Character Sets
만약 특정 숫자의 범위를 지정하고자 한다면, "[]" 기호안에 숫자의 범위를 입력하여 지정할 수 있다. 예를 들어, 6300 번 부터 6400 번까지의 번호를 지정하고 싶다면 어떻게 해야 할까? (_64XX, _63XX) 과 같이 두개의 번호를 지정하여 사용할 수 있다. 하지만 범위지정 방식으로 사용할 경우 (_6[34]XX) 으로 설정이 가능하다.
만약 [1-468] 과 같이 지정을 했다면, 이는 1 부터 468 까지의 숫자가 아니라, 4, 6, 8 의 숫자를 의미하는 것이다.
Other Special Characters
Within Asterisk patterns, we can also use a couple of other characters to represent ranges of numbers. The period character (.) at the end of a pattern matches one or more remaining characters. You put it at the end of a pattern when you want to match extensions of an indeterminate length. As an example, the pattern _9876. would match any number that began with 9876 and had at least one more character or digit.
The exclamation mark (!) character is similar to the period and matches zero or more remaining characters. It is used in overlap dialing to dial through Asterisk. For example, _9876! would match any number that began with 9876 including 9876, and would respond that the number was complete as soon as there was an unambiguous match.
Asterisk treats a period or exclamation mark as the end of a pattern. If you want a period or exclamation mark in your pattern as a plain character you should put it into a character set: [.] or [!].
Using the CONTEXT, EXTEN, PRIORITY, UNIQUEID, and CHANNEL Variables
원문은 이곳<ref>https://wiki.asterisk.org/wiki/display/AST/Using+the+CONTEXT%2C+EXTEN%2C+PRIORITY%2C+UNIQUEID%2C+and+CHANNEL+Variables</ref>에서 확인할 수 있다. Asterisk dialplan 에서 채널을 생성하고 사용할 때 필요한 정보는 CONTEXT, EXTEN, PRIORITY 이다. 즉 다음과 같이 사용한다.
exten=>6123,1,SayNumber(${EXTEN})
그런데, 만약 extension 정보를 수정하고 다시 reload 를 했다면 어떻게 될까? 만약 채널에서 현재 사용중인 EXTEN 정보가 변경이 되었다면 문제가 발생할 것이다. 그래서 이를 위해 Asterisk 내부적으로 생성되고 관리되는 키 정보가 있는데, 이것이 바로 UNIQUEID 이다. 모든 채널들은 고유의 Unique 값들을 가지게 된다. UNIQUEID 값은 흔히 다음과 같이 표현된다.
1267568856.11
Dialplan 에서 채널을 생성할 경우, UniqueID 값은 자동생성되며, 만약 AMI 등과 같은 명령으로 채널을 생성할 경우, 이를 지정해줄 수도 있다.
Asterisk 에서 자동생성되는 Unique ID 값은 다음과 같이 구성되어 있다.
1267568856.11 채널_생성_당시의_유닉스_타임.Asterisk_재시작_이후_만들어진_채널_갯수
CHANNEL 변수 역시 각 채널마다 중복되지 않는 키 정보로 사용될 수 있다. Hex number 값으로 구성되며, 해당 Exten 으로 채널을 생성할 경우, 1씩 올라가는 방식이다. 하지만 Asterisk 재시작시, 모든 채널 값들이 0으로 초기화되기 때문에 재시작을 하게 된다면, 재시작 이전의 CHANNEL 변수 값과 중복되는 현상이 발생한다.
Variables
Standard channel variables
"*" 가 붙은 변수들은 dialplan 에서 write 가 불가능하고 오직 read 만 가능한 변수들이다. 만약 write 를 할 경우, 경고나 에러 메시지 없이 무시된다.
Variables present in Asterisk 1.8 and forward
Asterisk-1.8 부터 계속 사용되고 있는 channel variable 내용 정리.
- ${CDR(accountcode)}* : Account code(if specified).
- ${BLINDTRANSFER} : The name of the channel on the other side of a blind transfer.
- ${BRIDGEPEER} : Bridged peer.
- ${BRIDGEPVTCALLID} : Bridged peer PVT call ID(SIP call ID if a SIP call).
- ${CALLERID(ani)}* : Caller ANI(PRI channels).
- ${CALLERID(ani2)}* : ANI2(info digits) also called Originating line information or OLI.
- ${CALLERID(all)} : Caller ID.
- ${CALLERID(dnid)}* : Dialed Number Identifer.
- ${CALLERID(name)}* : Caller ID Name only.
- ${CALLERID(rdnis)}* : Redirected Dial Number ID Service.
- ${CALLINGANI2}* : Caller ANI2(PRI channels).
- ${CALLINGPRES}* : Caller ID presentation for incoming calls(PRI channels).
- ${CALLINGTNS}* : Transit network Selector(PRI channels).
- ${CALLINGTON}* : Caller Type of Number(PRI channels).
- ${CHANNEL}* : Current channel name.
- ${CONTEXT}* : Current context.
- ${DATETIME}* : Current date time in the format: DDMMYYYY-HH:MM:SS(Deprecated; use ${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}).
- ${DB_RESULT} : Result value of DB_EXISTS() dial plan function.
- ${EPOCH}* : Current unix style epoch.
- ${EXTEN}* : Current extension.
- ${ENV(VAR)} : Environmental variable VAR.
- ${GOTO_ON_BLINDXFR} : Transfer to the specified context/extension/priority after a blind transfer(use ^ characters in place of | to separate context/extension/prioirty when setting this variable from the dialplan).
- ${HANGUPCAUSE}* : Asterisk cause of hangup(inbound/outbound).
- ${HINT}* : Channel hints for this extension.
- ${HINTNAME}* : Suggested Caller ID name for this extension.
- ${INVALID_EXTEN} : The invalid called extension(used in the "i" extension).
- ${LANGUAGE}* : Current language(Deprecated; use ${CHANNEL(language)}).
- ${LEN(VAR)} : String length of VAR(integer).
- ${PRIORITY}* : Current language(Deprecated; use ${CHANNEL(language)}).
- ${PRIREDIRECTREASON} : Reason for redirect on PRI, if a call was directed.
- ${TIMESTAMP}* : Current date time in the format: YYYYMMDD-HHMMSS(Deprecated; use ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}).
- ${TRANSFER_CONTEXT} : Context for transferred calls.
- ${FORWARD_CONTEXT} : Context for forwarded calls.
- ${DYNAMIC_PEERNAME} : The name of the channel on the other side when a dynamic feature is used.
- ${DYNAMIC_FEATURENAME} : The name of the last triggered dynamic feature.
- ${UNIQUEID}* : Current call unique identifier.
- ${SYSTEMNAME}* : Value of the systemname option of asterisk.conf.
- ${ENTITYID}* : Global Entity ID set automatically, or from asterisk.conf.
Variables present in Asterisk 11 and forward
Asterisk-11 부터 계속 사용되고 있는 channel variable 내용 정리.
- ${AGIEXITONHANGUP} : Set to 1 to force the behavior of a call to AGI to behave as it did in 1.4, where the AGI script would exit immediately on detecting a channel hangup.
- ${CALENDAR_SUCCESS} * : Status of the CALENDAR_WRITE function. Set to 1 if the function completed successfully; 0 otherwise.
- ${SIP_RECVADDR} * : The address a SIP MESSAGE request was received from.
- ${VOICEMAIL_PLAYBACKSTATUS} * : Status of the VoiceMailPlayMsg application. SUCCESS if the voicemail was played back successfully, FAILED otherwise.
Sample
; extensions.conf - the Asterisk dial plan ; ; Static extension configuration file, used by ; the pbx_config module. This is where you configure all your ; inbound and outbound calls in Asterisk. ; ; This configuration file is reloaded ; - With the "dialplan reload" command in the CLI ; - With the "reload" command (that reloads everything) in the CLI ; ; The "General" category is for certain variables. ; [general] ; ; If static is set to no, or omitted, then the pbx_config will rewrite ; this file when extensions are modified. Remember that all comments ; made in the file will be lost when that happens. ; ; XXX Not yet implemented XXX ; static=yes ; ; if static=yes and writeprotect=no, you can save dialplan by ; CLI command "dialplan save" too ; writeprotect=no ; ; If autofallthrough is set, then if an extension runs out of ; things to do, it will terminate the call with BUSY, CONGESTION ; or HANGUP depending on Asterisk's best guess. This is the default. ; ; If autofallthrough is not set, then if an extension runs out of ; things to do, Asterisk will wait for a new extension to be dialed ; (this is the original behavior of Asterisk 1.0 and earlier). ; ;autofallthrough=no ; ; ; ; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses ; a Trie to find the best matching pattern is used. In dialplans ; with more than about 20-40 extensions in a single context, this ; new algorithm can provide a noticeable speedup. ; With 50 extensions, the speedup is 1.32x ; with 88 extensions, the speedup is 2.23x ; with 138 extensions, the speedup is 3.44x ; with 238 extensions, the speedup is 5.8x ; with 438 extensions, the speedup is 10.4x ; With 1000 extensions, the speedup is ~25x ; with 10,000 extensions, the speedup is 374x ; Basically, the new algorithm provides a flat response ; time, no matter the number of extensions. ; ; By default, the old pattern matcher is used. ; ; ****This is a new feature! ********************* ; The new pattern matcher is for the brave, the bold, and ; the desperate. If you have large dialplans (more than about 50 extensions ; in a context), and/or high call volume, you might consider setting ; this value to "yes" !! ; Please, if you try this out, and are forced to return to the ; old pattern matcher, please report your reasons in a bug report ; on https://issues.asterisk.org. We have made good progress in providing ; something compatible with the old matcher; help us finish the job! ; ; This value can be switched at runtime using the cli command "dialplan set extenpatternmatchnew true" ; or "dialplan set extenpatternmatchnew false", so you can experiment to your hearts content. ; ;extenpatternmatchnew=no ; ; If clearglobalvars is set, global variables will be cleared ; and reparsed on a dialplan reload, or Asterisk reload. ; ; If clearglobalvars is not set, then global variables will persist ; through reloads, and even if deleted from the extensions.conf or ; one of its included files, will remain set to the previous value. ; ; NOTE: A complication sets in, if you put your global variables into ; the AEL file, instead of the extensions.conf file. With clearglobalvars ; set, a "reload" will often leave the globals vars cleared, because it ; is not unusual to have extensions.conf (which will have no globals) ; load after the extensions.ael file (where the global vars are stored). ; So, with "reload" in this particular situation, first the AEL file will ; clear and then set all the global vars, then, later, when the extensions.conf ; file is loaded, the global vars are all cleared, and then not set, because ; they are not stored in the extensions.conf file. ; clearglobalvars=no ; ; User context is where entries from users.conf are registered. The ; default value is 'default' ; ;userscontext=default ; ; You can include other config files, use the #include command ; (without the ';'). Note that this is different from the "include" command ; that includes contexts within other contexts. The #include command works ; in all asterisk configuration files. ;#include "filename.conf" ;#include <filename.conf> ;#include filename.conf ; ; You can execute a program or script that produces config files, and they ; will be inserted where you insert the #exec command. The #exec command ; works on all asterisk configuration files. However, you will need to ; activate them within asterisk.conf with the "execincludes" option. They ; are otherwise considered a security risk. ;#exec /opt/bin/build-extra-contexts.sh ;#exec /opt/bin/build-extra-contexts.sh --foo="bar" ;#exec </opt/bin/build-extra-contexts.sh --foo="bar"> ;#exec "/opt/bin/build-extra-contexts.sh --foo=\"bar\"" ; ; The "Globals" category contains global variables that can be referenced ; in the dialplan with the GLOBAL dialplan function: ; ${GLOBAL(VARIABLE)} ; ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid ; Unix/Linux environmental variables can be reached with the ENV dialplan ; function: ${ENV(VARIABLE)} ; [globals] CONSOLE=Console/dsp ; Console interface for demo ;CONSOLE=DAHDI/1 ;CONSOLE=Phone/phone0 IAXINFO=guest ; IAXtel username/password ;IAXINFO=myuser:mypass TRUNK=DAHDI/G2 ; Trunk interface ; ; Note the 'G2' in the TRUNK variable above. It specifies which group (defined ; in chan_dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use ; in the specified group. The four possible options are: ; ; g: select the lowest-numbered non-busy DAHDI channel ; (aka. ascending sequential hunt group). ; G: select the highest-numbered non-busy DAHDI channel ; (aka. descending sequential hunt group). ; r: use a round-robin search, starting at the next highest channel than last ; time (aka. ascending rotary hunt group). ; R: use a round-robin search, starting at the next lowest channel than last ; time (aka. descending rotary hunt group). ; TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0) ;TRUNK=IAX2/user:pass@provider ;FREENUMDOMAIN=mydomain.com ; domain to send on outbound ; freenum calls (uses outbound-freenum ; context) ; ; WARNING WARNING WARNING WARNING ; If you load any other extension configuration engine, such as pbx_ael.so, ; your global variables may be overridden by that file. Please take care to ; use only one location to set global variables, and you will likely save ; yourself a ton of grief. ; WARNING WARNING WARNING WARNING ; ; Any category other than "General" and "Globals" represent ; extension contexts, which are collections of extensions. ; ; Extension names may be numbers, letters, or combinations ; thereof. If an extension name is prefixed by a '_' ; character, it is interpreted as a pattern rather than a ; literal. In patterns, some characters have special meanings: ; ; X - any digit from 0-9 ; Z - any digit from 1-9 ; N - any digit from 2-9 ; [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) ; . - wildcard, matches anything remaining (e.g. _9011. matches ; anything starting with 9011 excluding 9011 itself) ; ! - wildcard, causes the matching process to complete as soon as ; it can unambiguously determine that no other matches are possible ; ; For example, the extension _NXXXXXX would match normal 7 digit dialings, ; while _1NXXNXXXXXX would represent an area code plus phone number ; preceded by a one. ; ; Each step of an extension is ordered by priority, which must always start ; with 1 to be considered a valid extension. The priority "next" or "n" means ; the previous priority plus one, regardless of whether the previous priority ; was associated with the current extension or not. The priority "same" or "s" ; means the same as the previously specified priority, again regardless of ; whether the previous entry was for the same extension. Priorities may be ; immediately followed by a plus sign and another integer to add that amount ; (most useful with 's' or 'n'). Priorities may then also have an alias, or ; label, in parentheses after their name which can be used in goto situations. ; ; Contexts contain several lines, one for each step of each extension. One may ; include another context in the current one as well, optionally with a date ; and time. Included contexts are included in the order they are listed. ; Switches may also be included within a context. The order of matching within ; a context is always exact extensions, pattern match extensions, includes, and ; switches. Includes are always processed depth-first. So for example, if you ; would like a switch "A" to match before context "B", simply put switch "A" in ; an included context "C", where "C" is included in your original context ; before "B". ; ;[context] ; ;autohints = yes ; If enabled for a context, a device state hint will be automatically created in ; the context with the name of the device and updated with device state changes. ; ;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...) ; ; Timing list for includes is ; ; <time range>,<days of week>,<days of month>,<months>[,<timezone>] ; ; Note that ranges may be specified to wrap around the ends. Also, minutes are ; fine-grained only down to the closest even minute. ; ;include => daytime,9:00-17:00,mon-fri,*,* ;include => weekend,*,sat-sun,*,* ;include => weeknights,17:02-8:58,mon-fri,*,* ; ; ignorepat can be used to instruct drivers to not cancel dialtone upon receipt ; of a particular pattern. The most commonly used example is of course '9' ; like this: ; ;ignorepat => 9 ; ; so that dialtone remains even after dialing a 9. Please note that ignorepat ; only works with channels which receive dialtone from the PBX, such as DAHDI, ; Phone, and VPB. Other channels, such as SIP and MGCP, which generate their ; own dialtone and converse with the PBX only after a number is complete, are ; generally unaffected by ignorepat (unless DISA or another method is used to ; generate a dialtone after answering the channel). ; ; ; Sample entries for extensions.conf ; ; [dundi-e164-canonical] ;include => stdexten ; ; List canonical entries here ; ;exten => 12564286000,1,Gosub(6000,stdexten(IAX2/foo)) ;exten => 12564286000,n,Goto(default,s,1) ; exited Voicemail ;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7}) [dundi-e164-customers] ; ; If you are an ITSP or Reseller, list your customers here. ; ;exten => _12564286000,1,Dial(SIP/customer1) ;exten => _12564286001,1,Dial(IAX2/customer2) [dundi-e164-via-pstn] ; ; If you are freely delivering calls to the PSTN, list them here ; ;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428 ;exten => _1256325XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Ditto for 256-325 [dundi-e164-local] ; ; Context to put your dundi IAX2 or SIP user in for ; full access ; include => dundi-e164-canonical include => dundi-e164-customers include => dundi-e164-via-pstn [dundi-e164-switch] ; ; Just a wrapper for the switch ; switch => DUNDi/e164 [dundi-e164-lookup] ; ; Locally to lookup, try looking for a local E.164 solution ; then try DUNDi if we don't have one. ; include => dundi-e164-local include => dundi-e164-switch ; ; DUNDi can also be implemented as a Macro instead of using ; the Local channel driver. ; [macro-dundi-e164] ; ; ARG1 is the extension to Dial ; ; Extension "s" is not a wildcard extension that matches "anything". ; In macros, it is the start extension. In most other cases, ; you have to goto "s" to execute that extension. ; ; Note: In old versions of Asterisk the PBX in some cases defaulted to ; extension "s" when a given extension was wrong (like in AMI originate). ; This is no longer the case. ; ; For wildcard matches, see above - all pattern matches start with ; an underscore. exten => s,1,Goto(${ARG1},1) include => dundi-e164-lookup ; ; Here are the entries you need to participate in the IAXTEL ; call routing system. Most IAXTEL numbers begin with 1-700, but ; there are exceptions. For more information, and to sign ; up, please go to www.gnophone.com or www.iaxtel.com ; [iaxtel700] exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxtel) ; ; The SWITCH statement permits a server to share the dialplan with ; another server. Use with care: Reciprocal switch statements are not ; allowed (e.g. both A -> B and B -> A), and the switched server needs ; to be on-line or else dialing can be severly delayed. ; [iaxprovider] ;switch => IAX2/user:[key]@myserver/mycontext [trunkint] ; ; International long distance through trunk ; exten => _9011.,1,Macro(dundi-e164,${EXTEN:4}) exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})}) [trunkld] ; ; Long distance context accessed through trunk ; exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1}) exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) [trunklocal] ; ; Local seven-digit dialing accessed through trunk interface ; exten => _9NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) [trunktollfree] ; ; Long distance context accessed through trunk interface ; exten => _91800NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) exten => _91888NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) exten => _91877NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) exten => _91866NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}}) [international] ; ; Master context for international long distance ; ignorepat => 9 include => longdistance include => trunkint [longdistance] ; ; Master context for long distance ; ignorepat => 9 include => local include => trunkld [local] ; ; Master context for local, toll-free, and iaxtel calls only ; ignorepat => 9 include => default include => trunklocal include => iaxtel700 include => trunktollfree include => iaxprovider ;Include parkedcalls (or the context you define in features conf) ;to enable call parking. include => parkedcalls ; ; You can use an alternative switch type as well, to resolve ; extensions that are not known here, for example with remote ; IAX switching you transparently get access to the remote ; Asterisk PBX ; ; switch => IAX2/user:password@bigserver/local ; ; An "lswitch" is like a switch but is literal, in that ; variable substitution is not performed at load time ; but is passed to the switch directly (presumably to ; be substituted in the switch routine itself) ; ; lswitch => Loopback/12${EXTEN}@othercontext ; ; An "eswitch" is like a switch but the evaluation of ; variable substitution is performed at runtime before ; being passed to the switch routine. ; ; eswitch => IAX2/context@${CURSERVER} ; The following two contexts are a template to enable the ability to dial ; ISN numbers. For more information about what an ISN number is, please see ; http://www.freenum.org. ; ; This is the dialing hook. use: ; include => outbound-freenum [outbound-freenum] ; We'll add more digits as needed. The purpose is to dial things ; like extension numbers at domains (ITAD number) so we're matching ; on lengths of 1 through 6 prior to the separator (the asterisk [*]) ; exten => _X*X!,1,Goto(outbound-freenum2,${EXTEN},1) exten => _XX*X!,1,Goto(outbound-freenum2,${EXTEN},1) exten => _XXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) exten => _XXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) exten => _XXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) exten => _XXXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1) [outbound-freenum2] ; This is the handler which performs the dialing logic. It is called ; from the [outbound-freenum] context ; exten => _X!,1,Verbose(2,Performing ISN lookup for ${EXTEN}) same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)}) ; make sure the suffix is all digits as well same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1) ; filter out bad characters per the README-SERIOUSLY.best-practices.txt document same => n,Set(TIMEOUT(absolute)=10800) same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)}) ; perform our lookup with freenum.org same => n,GotoIf($["${isnresult}" != ""]?from) same => n,Set(DIALSTATUS=CONGESTION) same => n,Goto(fn-CONGESTION,1) same => n(from),Set(__SIPFROMUSER=${CALLERID(num)}) same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial) ; check if we set the FREENUMDOMAIN global variable in [global] same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)}) ; if we did set it, then we'll use it for our outbound dialing domain same => n(dial),Dial(SIP/${isnresult},40) same => n,Goto(fn-${DIALSTATUS},1) exten => fn-BUSY,1,Busy() exten => _f[n]-.,1,NoOp(ISN: ${DIALSTATUS}) same => n,Congestion() [macro-trunkdial] ; ; Standard trunk dial macro (hangs up on a dialstatus that should ; terminate call) ; ${ARG1} - What to dial ; exten => s,1,Dial(${ARG1}) exten => s,n,Goto(s-${DIALSTATUS},1) exten => s-NOANSWER,1,Hangup() exten => s-BUSY,1,Hangup() exten => _s-.,1,NoOp [stdexten] ; ; Standard extension subroutine: ; ${EXTEN} - Extension ; ${ARG1} - Device(s) to ring ; ${ARG2} - Optional context in Voicemail ; ; Note that the current version will drop through to the next priority in the ; case of their pressing '#'. This gives more flexibility in what do to next: ; you can prompt for a new extension, or drop the call, or send them to a ; general delivery mailbox, or... ; ; The use of the LOCAL() function is purely for convenience. Any variable ; initially declared as LOCAL() will disappear when the innermost Gosub context ; in which it was declared returns. Note also that you can declare a LOCAL() ; variable on top of an existing variable, and its value will revert to its ; previous value (before being declared as LOCAL()) upon Return. ; exten => _X.,50000(stdexten),NoOp(Start stdexten) exten => _X.,n,Set(LOCAL(ext)=${EXTEN}) exten => _X.,n,Set(LOCAL(dev)=${ARG1}) exten => _X.,n,Set(LOCAL(cntx)=${ARG2}) exten => _X.,n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})}) exten => _X.,n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce exten => stdexten-BUSY,n,Return() ; If they press #, return to start exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain exten => a,n,Return() [stdPrivacyexten] ; ; Standard extension subroutine: ; ${ARG1} - Extension ; ${ARG2} - Device(s) to ring ; ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority) ; ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)` ; ${ARG5} - Context in voicemail (if empty, then "default") ; ; See above note in stdexten about priority handling on exit. ; exten => _X.,60000(stdPrivacyexten),NoOp(Start stdPrivacyexten) exten => _X.,n,Set(LOCAL(ext)=${ARG1}) exten => _X.,n,Set(LOCAL(dev)=${ARG2}) exten => _X.,n,Set(LOCAL(dontcntx)=${ARG3}) exten => _X.,n,Set(LOCAL(tortcntx)=${ARG4}) exten => _X.,n,Set(LOCAL(cntx)=${ARG5}) exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""]) exten => _X.,n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening ; option (or use P for databased call _X.creening) exten => _X.,n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce exten => stdexten-NOANSWER,n,NoOp(Finish stdPrivacyexten NOANSWER) exten => stdexten-NOANSWER,n,Return() ; If they press #, return to start exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce exten => stdexten-BUSY,n,NoOp(Finish stdPrivacyexten BUSY) exten => stdexten-BUSY,n,Return() ; If they press #, return to start exten => stdexten-DONTCALL,1,Goto(${dontcntx},s,1) ; Callee chose to send this call to a polite "Don't call again" script. exten => stdexten-TORTURE,1,Goto(${tortcntx},s,1) ; Callee chose to send this call to a telemarketer torture script. exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain exten => a,n,Return() [macro-page] ; ; Paging macro: ; ; Check to see if SIP device is in use and DO NOT PAGE if they are ; ; ${ARG1} - Device to page exten => s,1,ChanIsAvail(${ARG1},s) ; s is for ANY call exten => s,n,GotoIf($[${AVAILSTATUS} = "1"]?autoanswer:fail) exten => s,n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs exten => s,n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others exten => s,n,NoOp() ; Add others here and Post on the Wiki!!!! exten => s,n,Dial(${ARG1}) exten => s,n(fail),Hangup() [demo] include => stdexten ; ; We start with what to do when a call first comes in. ; exten => s,1,Wait(1) ; Wait a second, just for fun exten => s,n,Answer() ; Answer the line exten => s,n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message exten => s,n(instruct),BackGround(demo-instruct) ; Play some instructions exten => s,n,WaitExten() ; Wait for an extension to be dialed. exten => 2,1,BackGround(demo-moreinfo) ; Give some more information. exten => 2,n,Goto(s,instruct) exten => 3,1,Set(CHANNEL(language)=fr) ; Set language to french exten => 3,n,Goto(s,restart) ; Start with the congratulations exten => 1000,1,Goto(default,s,1) ; ; We also create an example user, 1234, who is on the console and has ; voicemail, etc. ; exten => 1234,1,Playback(transfer,skip) ; "Please hold while..." ; (but skip if channel is not up) exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)})) exten => 1234,n,Goto(default,s,1) ; exited Voicemail exten => 1235,1,VoiceMail(1234,u) ; Right to voicemail exten => 1236,1,Dial(Console/dsp) ; Ring forever exten => 1236,n,VoiceMail(1234,b) ; Unless busy ; ; # for when they're done with the demo ; exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo" exten => #,n,Hangup() ; Hang them up. ; ; A timeout and "invalid extension rule" ; exten => t,1,Goto(#,1) ; If they take too long, give up exten => i,1,Playback(invalid) ; "That's not valid, try again" ; ; Create an extension, 500, for dialing the ; Asterisk demo. ; exten => 500,1,Playback(demo-abouttotry) ; Let them know what's going on exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo exten => 500,n,Playback(demo-nogo) ; Couldn't connect to the demo site exten => 500,n,Goto(s,6) ; Return to the start over message. ; ; Create an extension, 600, for evaluating echo latency. ; exten => 600,1,Playback(demo-echotest) ; Let them know what's going on exten => 600,n,Echo() ; Do the echo test exten => 600,n,Playback(demo-echodone) ; Let them know it's over exten => 600,n,Goto(s,6) ; Start over ; ; You can use the Macro Page to intercom a individual user exten => 76245,1,Macro(page,SIP/Grandstream1) ; or if your peernames are the same as extensions exten => _7XXX,1,Macro(page,SIP/${EXTEN}) ; ; ; System Wide Page at extension 7999 ; exten => 7999,1,Set(TIMEOUT(absolute)=60) exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d) ; Give voicemail at extension 8500 ; exten => 8500,1,VoiceMailMain() exten => 8500,n,Goto(s,6) ; ; Here's what a phone entry would look like (IXJ for example) ; ;exten => 1265,1,Dial(Phone/phone0,15) ;exten => 1265,n,Goto(s,5) ; ; The page context calls up the page macro that sets variables needed for auto-answer ; It is in is own context to make calling it from the Page() application as simple as ; Local/{peername}@page ; [page] exten => _X.,1,Macro(page,SIP/${EXTEN}) ;[mainmenu] ; ; Example "main menu" context with submenu ; ;exten => s,1,Answer ;exten => s,n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..." ;exten => s,n,WaitExten ;exten => 1,1,Goto(submenu,s,1) ;exten => 2,1,Hangup ;include => default ; ;[submenu] ;exten => s,1,Ringing ; Make them comfortable with 2 seconds of ringback ;exten => s,n,Wait,2 ;exten => s,n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..." ;exten => s,n,WaitExten ;exten => 1,1,Goto(default,steve,1) ;exten => 2,1,Goto(default,mark,2) [public] ; ; ATTENTION: If your Asterisk is connected to the internet and you do ; not have allowguest=no in sip.conf, everybody out there may use your ; public context without authentication. In that case you want to ; double check which services you offer to the world. ; include => demo [default] ; ; By default we include the demo. In a production system, you ; probably don't want to have the demo there. ; include => demo ; ; An extension like the one below can be used for FWD, Nikotel, sipgate etc. ; Note that you must have a [sipprovider] section in sip.conf ; ;exten => _41X.,1,Dial(SIP/${FILTER(0-9,${EXTEN:2})}@sipprovider,,r) ; Real extensions would go here. Generally you want real extensions to be ; 4 or 5 digits long (although there is no such requirement) and start with a ; single digit that is fairly large (like 6 or 7) so that you have plenty of ; room to overlap extensions and menu options without conflict. You can alias ; them with names, too, and use global variables ;exten => 6245,hint,SIP/Grandstream1&SIP/Xlite1(Joe Schmoe) ; Channel hints for presence ;exten => 6245,1,Dial(SIP/Grandstream1,20,rt) ; permit transfer ;exten => 6245,n(dial),Dial(${HINT},20,rtT) ; Use hint as listed ;exten => 6245,n,VoiceMail(6245,u) ; Voicemail (unavailable) ;exten => 6245,s+1,Hangup ; s+1, same as n ;exten => 6245,dial+101,VoiceMail(6245,b) ; Voicemail (busy) ;exten => 6361,1,Dial(IAX2/JaneDoe,,rm) ; ring without time limit ;exten => 6389,1,Dial(MGCP/aaln/1@192.168.0.14) ;exten => 6390,1,Dial(JINGLE/caller/callee) ; Dial via jingle using labels ;exten => 6391,1,Dial(JINGLE/asterisk@digium.com/mogorman@astjab.org) ;Dial via jingle using asterisk as the transport and calling mogorman. ;exten => 6394,1,Dial(Local/6275/n) ; this will dial ${MARK} ;exten => 6275,1,Gosub(${EXTEN},stdexten(${MARK})) ; assuming ${MARK} is something like DAHDI/2 ;exten => 6275,n,Goto(default,s,1) ; exited Voicemail ;exten => mark,1,Goto(6275,1) ; alias mark to 6275 ;exten => 6536,1,Gosub(${EXTEN},stdexten(${WIL})) ; Ditto for wil ;exten => 6536,n,Goto(default,s,1) ; exited Voicemail ;exten => wil,1,Goto(6236,1) ;If you want to subscribe to the status of a parking space, this is ;how you do it. Subscribe to extension 6600 in sip, and you will see ;the status of the first parking lot with this extensions' help ;exten => 6600,hint,park:701@parkedcalls ;exten => 6600,1,noop ; ;To subscribe to the availability of a free member in the 'markq' queue. ;Note: '_avail' is added to the QueueName ;exten => 8501,hint,Queue:markq_avail ;exten => 8501,1,Queue(markq) ; ; You can also monitor the status of a queue by providing a hint for a ; particular queue name. ;exten => 8502,hint,Queue:markq ;exten => 8502,1,Queue(markq) ; ; Some other handy things are an extension for checking voicemail via ; voicemailmain ; ;exten => 8500,1,VoicemailMain ;exten => 8500,n,Hangup ; ; Or a conference room (you'll need to edit meetme.conf to enable this room) ; ;exten => 8600,1,Meetme(1234) ; ; Or playing an announcement to the called party, as soon it answers ; ;exten = 8700,1,Dial(${MARK},30,A(/path/to/my/announcemsg)) ; ; example of a compartmentalized company called "acme" ; ; this is the context that your incoming IAX/SIP trunk dumps you in... ;[acme-incoming] ;exten => s,1,Wait(1) ;exten => s,n,Answer() ;exten => s,n(menu),Playback(acme/vm-brief-menu) ;exten => s,n(exten),Background(vm-enter-num-to-call) ;exten => s,n,WaitExten(5) ;exten => s,n(goodbye),Playback(vm-goodbye) ;exten => s,n(end),Hangup() ; ;include => acme-extens ; ;exten => i,1,Playback(vm-invalid) ;exten => i,n,Goto(s,exten) ; optionally, transfer to operator ; ;exten => t,1,Goto(s,goodbye) ; ; this is the context our internal SIP hardphones use (see sip.conf) ; ;[acme-internal] ;exten => s,1,Answer() ;exten => s,n(exten),Background(vm-enter-num-to-call) ;exten => s,n,WaitExten(5) ;exten => s,n(goodbye),Playback(vm-goodbye) ;exten => s,n(end),Hangup() ; ;include => trunkint ;include => trunkld ;include => trunklocal ; ;include => acme-extens ; ; you can test what your system sounds like to outside callers by dialing this ;exten => 777,1,DISA(no-password,acme-incoming) ; ; grouping of acme's extensions... never used directly, always included. ; ;[acme-extens] ;include => stdexten ;exten => 111,1,Gosub(111,stdexten(SIP/pete_1,acme)) ;exten => 111,n,Goto(s,exten) ; ;exten => 112,1,Gosub(112,stdexten(SIP/nancy_1,acme)) ;exten => 112,n,Goto(s,end) ; ; end of acme example ; ; Time context: you can patch this in via the following. ; ; [acme-internal] ; ... ; exten => 777,1,Gosub(time) ; exten => 777,n,Hangup() ; ; ... ; include => time ; ; Note: if you're geographically spread out, you can have SIP extensions ; specify their own local timezone in sip.conf as: ; ; [boi] ; type=friend ; context=acme-internal ; callerid="Boise Ofc. <2083451111>" ; ... ; ; use system-wide default timezone of MST7MDT ; ; [lws] ; type=friend ; context=acme-internal ; callerid="Lewiston Ofc. <2087431111>" ; ... ; setvar=timezone=PST8PDT ; ; "timezone" isn't a 'reserved' name in any way, and other places where ; the timezone is significant (e.g. calls to "SayUnixTime()", etc) will ; require modification as well. Note that voicemail.conf already has ; a mechanism for timezones. ; [time] exten => _X.,30000(time),NoOp(Time: ${EXTEN} ${timezone}) exten => _X.,n,Wait(0.25) exten => _X.,n,Answer() ; the amount of delay is set for English; you may need to adjust this time ; for other languages if there's no pause before the synchronizing beep. exten => _X.,n,Set(FUTURETIME=$[${EPOCH} + 12]) exten => _X.,n,SayUnixTime(${FUTURETIME},Zulu,HNS) exten => _X.,n,SayPhonetic(z) ; use the timezone associated with the extension (sip only), or system-wide ; default if one hasn't been set. exten => _X.,n,SayUnixTime(${FUTURETIME},${timezone},HNS) exten => _X.,n,Playback(spy-local) exten => _X.,n,WaitUntil(${FUTURETIME}) exten => _X.,n,Playback(beep) exten => _X.,n,Return() ; ; ANI context: use in the same way as "time" above ; [ani] exten => _X.,40000(ani),NoOp(ANI: ${EXTEN}) exten => _X.,n,Wait(0.25) exten => _X.,n,Answer() exten => _X.,n,Playback(vm-from) exten => _X.,n,SayDigits(${CALLERID(ani)}) exten => _X.,n,Wait(1.25) exten => _X.,n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit exten => _X.,n,Return() ; For more information on applications, just type "core show applications" at your ; friendly Asterisk CLI prompt. ; ; "core show application <command>" will show details of how you ; use that particular application in this file, the dial plan. ; "core show functions" will list all dialplan functions ; "core show function <COMMAND>" will show you more information about ; one function. Remember that function names are UPPER CASE.
See also
Books
- Asterisk: The Definitive Guide, 4th Edition
References
<references />