[Asterisk] Variables in Asterisk

Using Variables in Asterisk Dialplans

Asterisk 에서 Dialplan 작성시, 내부 변수를 목적에 따라 Global, Shared, Chanel-specific 변수로 구분해서 사용할 수 있다.
공통적으로 변수를 사용할 때 다음과 같은 방식으로 사용할 수 있다.

${foo:offset:length}

foo 는 변수의 이름이고, offset 은 변수의 내용 중 참조하고자 하는 시작 위치, length 는 offset 으로부터 참조하고자 하는 변수 내용의 길이이다.

변수 이름 작성시, 사용자 지정 변수(User-defined value)는 대/소문자 상관 없이 참조가 가능하나, Asterisk 에서 지정하여 사용하는 변수(ex. ${EXTEN}) 같은 경우는 대/소문자를 구분한다.

크게 4가지 타입의 변수(Global, Shared, Channel, Environment)가 있는데, 각각의 의미는 다음과 같다.

Global : [globals] 섹션에서 설정하거나 SetGlobalVal 명령으로 설정된 변수. 한번 설정하면 언제/어디서 든지 호출하여 참조가 가능하다.
Shared : Variables are new in Asterisk 1.6(however a backport is available for 1.4). Two (or more?) channels can gain full access with the help of Asterisk func SHARED to what otherwise would be a channel variable.
Channel : 특정 Call 에 연동되어 사용가능한 변수. Global 타입과는 달리 Call(Channel)에서만 사용 가능하다. 즉, Call(Channel) 종료시, 해당 변수는 모두 삭제된다.
Environment : Unix 환경 변수. Dialplan 내에서 ENV() 함수로 사용가능하다. ${ENV(var)} var 에는 참조하고자하는 Unix 환경변수 이름을 입력하면 된다.

만약, Channel 변수를 설정할 때, Global 변수에 설정되어 있는 변수와 똑같은 이름으로 설정하게 된다면 Channel 변수를 참조하게 된다.

[FooTest]
exten => 100,1,SetGlobalVar(FOO=5)
exten => 100,2,NoOp(${FOO})
exten => 100,3,NoOp(${foo})
exten => 100,4,Set(foo=8)
exten => 100,5,NoOp(${FOO})
exten => 100,6,NoOp(${foo})

— Executing SetGlobalVar("Zap/1-1", "FOO=5") in new stack
— Setting global variable 'FOO' to '5'
— Executing NoOp("Zap/1-1", "5") in new stack
— Executing NoOp("Zap/1-1", "5") in new stack
— Executing Set("Zap/1-1", "foo=8") in new stack
— Executing NoOp("Zap/1-1", "8") in new stack
— Executing NoOp("Zap/1-1", "8") in new stack

Global 변수 설정 직후 ${FOO} 의 값을 확인해보면 “5” 로 나오는 것을 확인할 수 있다. 하지만 Channel 변수로 설정 후, ${FOO} 값을 확인해보면 모두 “8”로 표시되는 것을 알 수 있다.

Inheritance of Channel Variables

변수 선언시, _(underscore)를 붙이게 되면 이는 Inheritance of Channel Variable 임을 선언하는 것이다. 그런데 이 ‘_'(underscore) 를 하나를 붙이느냐, 두개를 붙이느냐에 따라 변수가 상속되는 범위가 달라진다.
하나를 붙이면 한번만 상속되고, 두개를 붙이게 되면 계속해서 상속된다.

exten => 104,1,Set(FEE=fee)
exten => 104,2,Set(_FIE=fie)
exten => 104,3,Set(__FUM=fum)
exten => 104,4,Dial(Local/105)

exten => 105,1,NoOp(${FEE})
exten => 105,2,NoOp(${FIE})
exten => 105,3,NoOp(${FUM})
exten => 105,4,Dial(Local/106)

exten => 106,1,NoOp(${FEE})
exten => 106,2,NoOp(${FIE})
exten => 106,2,NoOp(${FUM})

results in

— Executing Set("SIP/oberon-365e", "FEE=fee") in new stack
— Executing Set("SIP/oberon-365e", "_FIE=fie") in new stack
— Executing Set("SIP/oberon-365e", "__FUM=fum") in new stack
— Executing Dial("SIP/oberon-365e", "Local/105") in new stack
— Called 105
— Executing NoOp("Local/105@default-7263,2", "") in new stack
— Executing NoOp("Local/105@default-7263,2", "fie") in new stack
— Executing NoOp("Local/105@default-7263,2", "fum") in new stack
— Executing Dial("Local/105@default-7263,2", "Local/106") in new stack
— Called 106
— Executing NoOp("Local/106@default-49be,2", "") in new stack
— Executing NoOp("Local/106@default-49be,2", "") in new stack
— Executing NoOp("Local/106@default-49be,2", "fum") in new stack

Using $

If you want to set a global variable containing the another variable name in the [globals] category of extensions.conf you have to do something like this:

[globals]
SS=$
MY_VAR=${SS}{EPOCH}-${SS}{EXTEN}.gsm

This way the MY_VAR value is ${EPOCH}-${EXTEN}.gsmUsing it with the EVAL() function is very useful. I.e. If you want to record you can do this:

exten => 104,1,Set(filename=${EVAL(${MYVAR}){)
exten => 104,2,MixMonitor(${filename})

Predefined Channel Variables

  • ${ACCOUNTCODE}: Account code, if specified – see Asterisk billing (DEPRECATED in 1.2.0 and removed in 1.4. Use ${CDR(accountcode)}
  • ${ANSWEREDTIME}: This is the amount of time(in seconds) for actual call.
  • ${BLINDTRANSFER}: The active SIP channel that dialed the number. This will return the SIP Channel that dialed the number when doing blind transfers – see BLINDTRANSFER
  • ${CALLERID(all)}: The current Caller ID name and number – See Setting Callerid for usage in Asterisk 1.4
  • ${CALLERID(name)}: The current Caller ID name – ${CALLERIDNAME} was used in versions of Asterisk prior to 1.2.0, it was DEPRECATED in 1.2.0 and removed in 1.4.
  • ${CALLERID(num)}: The current Caller ID number – ${CALLERIDNUM} was used in versions of Asterisk prior to 1.2.0, it was DEPRECATED in 1.2.0 and removed in 1.4.

(Note: this is not necessarily numeric as the name would indicate and can legitimately contain the space character. Commands acting on this variable (such as ‘GotoIf’, for example) should be aware of this).

  • ${CALLINGPRES}: PRI Call ID Presentation variable for incoming calls (See callingpres )
  • ${CHANNEL}: Current channel name
  • ${CONTEXT}: The name of the current context
  • ${DATETIME}: Current date time in the format: DDMMYYYY-HH:MM:SS This is deprecated in Asterisk 1.2, instead use :${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)})
  • ${DIALEDPEERNAME}: Name of the called party. Broken for now, see DIALEDPEERNAME
  • ${DIALEDPEERNUMBER}: Number of the called party. Broken for now, see DIALEDPEERNUMBER
  • ${DIALEDTIME}: Time since the number was dialed (only works when dialed party answers the line?!)
  • ${DIALSTATUS}: Status of the call. See DIALSTATUS (note: In the current SVN release, DIALSTATUS seems to have been removed. Now you should use the DEVSTATE function. Try in astersisk console “core show function DEVSTATE” for more informations)
  • ${DNID}: Dialed Number Identifier. Limitations apply, see DNID
  • ${EPOCH}: The current UNIX-style epoch (number of seconds since 1 Jan 1970)
  • ${EXTEN}: The current extension – cannot be modified with the set command- just use the GoTo to change the EXTEN variable!
  • ${HANGUPCAUSE}: The last hangup return code on a Zap channel connected to a PRI interface
  • ${INVALID_EXTEN}: The extension asked for when redirected to the i (invalid) extension
  • ${LANGUAGE}: The current language setting. See Asterisk multi-language
  • ${MEETMESECS}: Number of seconds a user participated in a MeetMe conference
  • ${PRIORITY}: The current priority
  • ${RDNIS}: The current redirecting DNIS, Caller ID that redirected the call. Limitations apply, see RDNIS
  • ${SIPDOMAIN}: SIP destination domain of an inbound call (if appropriate)
  • ${SIP_CODEC}: Set the SIP codec for the inbound (=first) call leg (see channelvariables.txt or README.variables in 1.2); Asterisk 1.6.2 also comes with SIP_CODEC_OUTBOUND for the remote (=second) call leg.
  • ${SIPCALLID}: The SIP dialog Call-ID: header
  • ${SIPUSERAGENT}: The SIP user agent header
  • ${TIMESTAMP}: Current date time in the format: YYYYMMDD-HHMMSS This is deprecated as of Asterisk 1.4, instead use :${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)})
  • ${TRANSFERCAPABILITY}: Type of Channel
  • ${TXTCIDNAME}: Result of application TXTCIDName (see below)
  • ${UNIQUEID}: Current call unique identifier
  • ${TOUCH_MONITOR}: used for “one touch record” (see features.conf, and wW dial flags). If is set on either side of the call then that var contains the app_args for app_monitor otherwise the default of WAV||m is used
  • ${TOUCH_MONITOR_PREFIX}: used for “one touch record” (see features.conf, and wW dial flags). This set Prefix to ${TOUCH_MONITOR} default: auto “New in 1.8”

Application-specific variables

특정 Function/Application 들은 Input/Output 으로 Channel 변수들을 이용한 결과값들을 제공한다.

  • AgentCallbackLogin returns ${AGENTBYCALLERID_${CALLERID}}: The ID of the agent successfully logged on.
  • ChanIsAvail returns ${AVAILCHAN}: The first available channel
  • Dial takes input from ${VXML_URL}: Send XML Url to Cisco 7960 or to i6net VoiceXML browser
  • Dial takes input from ${ALERT_INFO}: Set ring cadence or allow intercom on for various SIP phones
  • Dial returns ${CAUSECODE}: If the dial failed, this is the errormessage
  • Dial returns ${DIALSTATUS}: Text code returning status of last dial attempt.
  • Dial takes input from ${TRANSFER_CONTEXT}: If this variable exists, when a #transfer is executed it goes to the selected extension on this context.
  • EnumLookup returns ${ENUM}: The result of the lookup
  • Hangup reads the ${PRI_CAUSE} variable for setting PRI return codes
  • MeetMe takes input from {MEETME_AGI_BACKGROUND}: An AGI script to run
  • MeetMe returns ${MEETMESECS}: The number of seconds the user was in a conference
  • Playback returns ${PLAYBACKSTATUS}: The status of the command (FAILED|SUCCESS)
  • Queue returns ${QUEUESTATUS}: The reason for popping the call out of the queue
  • TXTCIDName returns ${TXTCIDNAME}: The result of the DNS lookup
  • VoiceMail returns ${VMSTATUS}: indicates the status of the execution of the VoiceMail application. Possible values are: SUCCESS | USEREXIT | FAILED .

Macro-specific variables

Macro context 에서는 추가적인 Channel 변수들이 사용가능하다.

  • ${ARG1}: The first argument passed to the macro
  • ${ARG2}: The second argument passed to the macro (and so on)
  • ${MACRO_CONTEXT}: The context of the extension that triggered this macro
  • ${MACRO_EXTEN}: The extension that triggered this macro
  • ${MACRO_OFFSET}: Set by a macro to influence the priority where execution will continue after exiting the macro
  • ${MACRO_PRIORITY}: The priority in the extension where this macro was triggered

Call files extension specific variables

  • ${REASON}: A number that represents the reason why an outgoing call failed. See Asterisk Reason variable.

Environment Variables

Unix 환경 변수들도 참조가 가능하다.

${ENV(foo)}

  • ${ENV(ASTERISK_PROMPT)}: the current Asterisk CLI prompt.
  • ${ENV(RECORDED_FILE)}: the filename of the last file saved by the Record command (available in CVS > 2004-03-21)

String Handling Functions

String Length

${LEN(foo)}

foo 변수의 길이를 리턴한다. 해당 변수가 NULL 인지 빈 문자열인지 확인하는데 효과적인 방법이다.

exten => 100,1,Set(Fruit=pear)
exten => 100,2,NoOp(${LEN(Fruit)})
exten => 100,3,NoOp(${LEN(${Fruit})})

첫번째 NoOp() 결과는 “5”를 리턴한다(Fruit). 두번째 NoOp() 결과는 “4”를 리턴한다(${Fruit} == pear)

Substrings

${foo:offset:length}

returns a substring of the string foo, beginning at offset offset and returning the next length characters. The first character is at offset 0.

  • If offset is negative, it is taken leftwards from the right hand end of the string.
  • If length is omitted or is negative, then all the rest of the string beginning at offset is returned.
${123456789:1} - returns the string 23456789
${123456789:-4} - returns the string 6789
${123456789:0:3} - returns the string 123
${123456789:2:3} - returns the string 345
${123456789:-4:3} - returns the string 678

exten => _NXX.,1,Set(areacode=${EXTEN:0:3}) - get the first 3 digits of ${EXTEN}
exten => _516XXXXXXX,1,Dial(${EXTEN:3}) - get all but the first 3 digits of ${EXTEN}
exten => 100,1,Set(whichVowel=4)

exten => 100,2,Set(foo=AEIOU:${whichVowel}:1) - sets ${foo} to the single letter 'U'

String Concatenation

두 개이상의 문자열들을 합친다면 다음과 같이 하면 된다.

${foo}${bar}
555${theNumber}
${longDistancePrefix}555${theNumber}

Variable math

변수들을 이용하여 더하기, 곱하기, 증가하기들을 하고싶다면..

exten => s,1,Set(SOMEVAR=$[${SOMEVAR} + 1]) ; increment
exten => s,2,Set(SOMEVAR=$[2 * ${SOMEVAR}]) ; multiplication etc...
In times past, a single space was required between items in the $[...] expressions. This is no longer the case!

In late model Asterisks (1.2?), the MATH function is also available...

exten => s,1,Set(SOMEVAR=${MATH(${SOMEVAR}+1,i)}) ; increment, get result as integer
exten => s,2,Set(SOMEVAR=${MATH(2*${SOMEVAR})}) ; multiplication etc...

출처 : http://www.voip-info.org/wiki/view/Asterisk+variables

[Asterisk] Advanced Dialplan

Basic Expressions

Asterisk 에서 모든 표현식(수식)은 $ [ ] 표시된다.

$[expression]

그리고 다음과 같이 사용할 수 있다.

$[${COUNT} + 1]$[${COUNT} / 2]

Asterisk Dialplan 내에서 표현식이 있다면 해당 구문은 먼저 모든 표현식이 계산된 이후에 진행된다.
다음의 예제를 생각해보자.

exten => 204,1,Noop()
        same => n,Answer()
        same => n,Set(COUNT=3)
        same => n,Set(NEWCOUNT=$[${COUNT} + 1])
        same => n,SayNumber(${NEWCOUNT})

2번째 priority 에서 COUNT 변수에 3을 입력했다.
그리고 3번째 priority 에서 하나의 Set appilication 만이 사용됐는데, 사실은 3가지 일이 벌어졌다.

1. ${COUNT} 를 3으로 대치한다. 즉, 표현식은 다음과 같이 변경된다.
same => n,Set(NEWCOUNT=$[3 + 1])

2. 표현식을 계산한다. 즉, 3과 1을 더한다. 결과값 4가 나온다.
same => n,Set(NEWCOUNT=4)

3. Set() Application이 NEWCOUNT 에 4를 입력한다.

Operators

Boolean operators

expr1 | expr2
or 연산자. expr1 혹은 expr2 둘 중 하나라도 참이라면 참.

expr1 & expr2
and 연산자. expr1 혹은 expr2 둘 중 하나라도 거짓이면 거짓.

expr1 {=, >, >=, <, <=, !=} expr2비교 연산자. expr1, expr2 각 숫자라면 숫자 비교를 하고, 아니라면 문자열 비교를 한다.

Mathematical operators

expr1 {+, -} expr2
더하기, 빼기.

expr1 {*, /, %} expr2
곱하기, 나누기, 나머지.

Regular expression operators

expr1 : expr2
정규 표현식 내용 참조.

expr1 =~ expr2
정규 표현식 내용 참조.

String
exten => 234,1,Set(NEWTEST=blah${TEST})

Dialplan Functions

Dialplan Function 들은 많은 기능들을 가지고 있다. 문자열 길이 계산, 시간 및 날짜 계산, MD5 체크섬 오류 확인 등등의 기능을 제공한다.

Syntax

Dialplan Function 은 다음과 같은 기본 Syntax 구조를 가진다.

FUNCTION_NAME(argument)

그리고 다음과 같이 Function 자체가 다른 Function 의 Argument 로 사용되는 것도 가능하다.

${FUNCTION_NAME(${FUNCTION_NAME(argument)})}

Conditional Branching

Asterisk 에서 제공하는 함수들을 이용하면 여러가지 조건에 따라 분기를 생성할 수 있다. 이를 Conditional Branching 이라고 한다.

The GotoIf() Application

Conditional Branching 의 핵심은 GotoIf() Application 이다. GotoIf() Application 은 입력된 조건 식의 참/거짓 여부에 따라 해당 콜을 다른 곳으로 분배시키는 역할을 한다.

GotoIf(expression?destination1:destination2)

만약 expression 이 참이면 destination1로, 거짓이면 destination2 로 해당 콜을 넘겨준다. 그렇다면 무엇이 참이고 거짓일까? 표현식의 결과값이 공백 String 이거나 0이면 거짓이고 그 외의 것들은 모두 참으로 판별한다.
destination 은 다음중 한가지로 지정할 수 있다.

– weasels 와 같이  동일한 extension 내의 priority label- 123,wesels 와 같이 동일한 context 내의 다른 extension 과 priority label
– incoming,123,weasels 와 같이 다른 context, 다른 extension, 다른 priority label

입력되는 destination 중 하나는 생략이 가능하다. 즉, 하나의 destination 만 입력을 해도 괜찮다는 뜻이다. 하지만 이는 역으로 반드시 하나는 입력해야 된다는 뜻이다. 입력되지 않은 destination 의 경우, 그냥 다음 priority 구문을 진행한다.

exten => 207,1,NoOp()
        same => n,Set(TEST=1)
        same => n,GotoIf($[${TEST} = 1]?weasels:iguanas)
        same => n(weasels),Playback(weasels-eaten-phonesys)
        same => n,Hangup()
        same => n(iguanas),Playback(office-iguanas)
        same => n,Hangup()

기능은 정상적으로 작동하지만 뭔가 알아보기 힘들다. 다음과 같이 작성해보자.

exten => 208,1,NoOp()
        same => n,Answer()
        same => n,Set(TEST=1)
        same => n,GotoIf($[${TEST} = 1]?weasels,1:iguanas,1)    ; now we're going to extension,priority
exten => weasels,1,NoOp()
        same => n,Playback(weasels-eaten-phonesys)      ; this is NOT a label. It is different extension
        same => n,Hangup()
exten => iguanas,1,NoOp()
        same => n,Playback(office-iguanas)
        same => n,Hangup()

다음은 10부터 0까지 카운트 다운을 하는 Dialplan 이다.

exten => 209,1,NoOp()
        same => n,Answer()
        same => n,Set(COUNT=10)
        same => n(start),GotoIf($[${COUNT} > 0]?:goodbye)
        same => n,SayNumber(${COUNT})
        same => n,Set(COUNT=$[${COUNT} - 1])
        same => n,Goto(start)
        same => n(goodbye),Hangup()

 Time-Based Conditional Branching with GotoIfTime()

GotoIf() Application 이 표현식에 따른 분기였다면, GotoIfTime() Application 은 system time 에 따른 분기라고 말할 수 있다.

GotoIfTime(times,days_of_week,days_of_month,months?label)

짧게 말해서, GotoIfTime() 은 지정된 시간에 콜을 지정된 label 로 보내는 Application 이라고 할 수 있다.

times:
시간대 범위. 하나 혹은 여러개를 지정할 수 있다. 24-hour 형식을 사용함. 예를 들어 09:00 AM 부터 05:00 PM 까지의 시간대를 지정한다면 09:00-17:00 으로 표시할 수 있다. 하루를 통째로 입력한다면 00:00-23:59 로 표시한다.

days_of_week:
요일 범위. 하나 혹은 여러개를 지정할 수 있다. mon,tue,wed,thu,fri,sat,sun 으로만 표시가 가능하다. 월요일부터 금요일까지를 표시하고자 한다면 mon-fri 로 표시한다. 화요일과 목요일만 표시하고자 한다면 tue&thu 로 표시한다.

days_of_month:
일 범위. 하나 혹은 여러개를 지정할 수 있다. 1 부터 31 까지 지정하고자 하는 날짜를 입력하면 된다. 7일부터 12일까지라면 7-12, 15일과 30일 이틀만 지정하고자 한다면 15&30 으로 표시한다.

month:
달 범위. 하나 혹은 여러개를 지정할 수 있다. jan-apr 과 같이 지정 가능하며 jan&mar&jun 과 같은 지정도 가능하다. 물론 jan-apr&jun&oct-dec 와 같은 지정도 가능하다.

모든 범위:
만약 모든 날짜(1년 내내와 같이..)를 지정하고자 한다면 해당 입력 부분에 * 표시를 입력하면 된다.

label:
같은 extension 부분에 있는 priority. ex) time_has_passed
같은 context 에 있는 다른 extension, priority. ex) 123,time_has_passed
다른 context, extension, priority. ex) incoming,123,time_has_passed

예제를 보자. 매주 월요일부터 금요일까지 오전 9:00 부터 오후 05:59 사이에 오는 콜을 처리하는 Dialplan 이다.

exten => s,1,NoOp()
    same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)

만약 발신자가 해당 시간에 전화를 하게 되면 open context 내의 s extension 의 첫번째 priority 구문을 실행한다.

아래 예제는 참고로 보길 바란다.

exten => 212,1,NoOp()
        same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)

; If it's any hour of the day, on any day of the week,
; during the fourth day of the month, in the month of July,
; we're closed
        same => n,GotoIfTime(*,*,4,jul?closed,s,1)

; During business hours, send calls to the open context
        same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)
        same => n,GotoIfTime(09:00-11:59,sat,*,*?open,s,1)

Macro

만약 여러개의 Dialplan 을 편집해야 한다면? 그 수가 굉장히 많다면? Macro 가 그 해답일 수 있다.

모든 Macro 는 macro- 구문으로 시작한다. 만약 voicemail 을 위한 Macro 를 생성한다면 다음처럼 생성하면 된다.

[macro-voicemail]

다음은 예제로 작성된 voicemail macro 이다.

[macro-voicemail]
exten => s,1,NoOp()
        same => n,Dial(${JOHN},10)
        same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
        same => n(unavail),VoiceMail(101@default,u)
        same => n,Hangup()
        same => n(busy),VoiceMail(101@default,b)
        same => n,Hangup()

Calling Macros from the Dialplan

Dialplan 에서 Macro 를 사용하기 위해서는 Macro() application 이 필요하다. Macro() application 은 Macro 를 호출하고 인자값들을 넘겨주는 역할을 한다.
예를 들어 방금 생성한 voicemail macro 를 호출하기 위해서는 다음과 같이 작성하면 된다.

exten => 213,1,Macro(voicemail)

Macro() application 은 특수 변수들을 가지고 있다.

${MACRO_CONTEXT}
Macro 를 호출한 extension 의 context

${MACRO_EXTEN}Macro 를 호출한 Extension

${MACRO_PRIORITY}
Macro 를 호출한 Priority

${ARG n}
Macro 를 호출하면서 넘겨진 인자 값들. 첫번째 인자값은 ${ARG1}, 두번째 인자값은 ${ARG2} 와 같다.

자, 이제 조금전 생성한 voicemail macro 를 수정해보자. 조금전 생성한 voicemail macro 는 오직 101 extension 에 대해서만 voicemail 을 수행했었다.
이를 호출되는 extension 의 voicemail 로 수정해보자.

[macro-voicemail]
exten => s,1,NoOp()
        same => n,Dial(${ARG1},20)
        same => n,Goto(s-${DIALSTATUS},1)

exten => s-NOANSWER,1,VoiceMail(${MACRO_EXTEN}@default,u)
        same => n,Goto(incoming,s,1)

exten => s-BUSY,1,VoiceMail(${MACRO_EXTEN}@default,b)
        same => n,Goto(incoming,s,1)

exten => _s-.,1,NoOp()
        same => n,Goto(s-NOANSWER,1)

GoSub

GoSub() application 은 Macro() application 과 비슷하다. 하지만 Macro() 와는 달리 별도의 Naming rule 이 필요하지 않다. 하지만 GoSub 루틴임을 알리기 위해 prefix 를 붙이는 것이 관례적이다.
다음은 Subroutine 예제이다.

[subVoicemail]
exten => start,1,NoOp()
        same => n,Dial(${ARG1},10)
        same => n,VoiceMail(${ARG2}@default,${IF($[DIALSTATUS} = BUSY]?b:u)})
        same => n,Hangup()

[LocalSets]
exten => 217,1,GoSub(subVoicemail,start,1(${JOHN},${EXTEN}))
exten => 218,1,GoSub(subVoicemail,start,1(${JANE},${EXTEN}))
exten => 219,1,GoSub(subVoicemail,start,1(${JACK},${EXTEN}))

 

 

[Freeswitch] How to change Freeswitch ip address

Freeswtich 설치 이후, 테스트를 진행하는데 SIP 클라이언트 접속이 안되는 문제가 발생했다.

telnet/netstat 으로 확인해보니 포트가 안뚫려있었다. Freeswitch listen IP가 localhost 로만 설정되어 있는 상황.

따라서, Freeswitch Server Ip 설정을 변경해주니 잘 작동하였다.

/usr/local/freeswitch/conf/vars.xml 파일 내용에서 다음 부분을 수정해주었다.(local_ip_v4 항목을 추가)

  <X-PRE-PROCESS cmd="set" data="sound_prefix=$${sounds_dir}/en/us/callie"/>

  <!--
      This setting is what sets the default domain FreeSWITCH will use if all else fails.

      FreeSWICH will default to $${local_ip_v4} unless changed.  Changing this setting does
      affect the sip authentication.  Please review conf/directory/default.xml for more
      information on this topic.
  -->
  <X-PRE-PROCESS cmd="set" data="local_ip_v4=192.168.200.10"/>
  <X-PRE-PROCESS cmd="set" data="domain=$${local_ip_v4}"/>
  <X-PRE-PROCESS cmd="set" data="domain_name=$${domain}"/>
  <X-PRE-PROCESS cmd="set" data="hold_music=local_stream://moh"/>
  <X-PRE-PROCESS cmd="set" data="use_profile=internal"/>

보통은 위의 설정이 없이도, 자동으로 local_ip_v4 에 IP 가 설정이 된다. 그러나, 만약 두개 이상의 NIC 가 달려 있는 서버라면.. 문제가 발생한다. 이 경우 위의 설정이 필요하다.

참조: http://wiki.freeswitch.org/wiki/Getting_Started_Guide#Some_stuff_to_try_out.21