Asterisk的基本配置
摘錄<<Asterisk.The.Future.of.Telephony>>
先探討對模擬接口如FXS和FXO端口的基本配置.然后配置兩個VoIP接口:一個連接軟電話的本地SIP通道,一個通過Asterisk內部協議(Inter-eXchange protocol IAX)連接全球免費通信(Free World Dialup).
4.1 我到底需要什么
Asterisk可以連接的數目龐大的接口類型,包括:
模擬接口,如你的電話線(FXS)和模擬電話(FXO)
數字線路,如T-1和E-1線路
VoIP協議如SIP和IAX
4.2 使用接口配置文件
注意,這種硬件接口不是必須的,如果你想建立一個純IP的配置,你可以跳到SIP配置的章節.
配置文件如下:
zaptel.conf
做硬件接口的基層配置.我們將建立一個FXO和一個FXS通道.
zapata.conf
為硬件配置Asterisk的接口.
extensions.conf
創建的撥號方案會比較粗糙,但是將證明系統可用.
sip.conf
配置SIP協議的文件.
iax.conf
配置呼入和呼出IAX通道的文件.
以下章節中,將編輯幾個配置文件,並且將這些文件裝載到你的交換機上,使它們生效.編輯完zaptel.conf文件,需要使用/sbin/ztcfg -vv裝載配置到硬件.然而,改變信令方法需要重啟.在編輯iax.conf和sip.conf文檔后,分別需要裝載chan_iax2.so和chan_sip.so
4.3 FXO和FXS通道
FXO和FXS通道的區別簡單,就在於連接的哪端提供撥號音.FXO端口不生成撥號音,而是接受.通常的例子是撥號音由你的電話公司提供.
FXS端口提供撥號音和震鈴電壓,在有呼入的時候提醒用戶.兩種接口都提供雙向通訊.
如果你的Asterisk服務器有一個兼容的FXO端口,你可以把你的電話公司的電話線插入這個端口.Asterisk可以使用這根電話線呼出和接受電話呼叫(我的理解,此時的Asterisk服務器相當於電信公司的一部電話終端).同理,如果你的Asterisk服務器有一個兼容的FXS端口,你可以連接一部模擬電話,Asterisk就可以呼叫這部電話,同時你也可以進行呼叫(我的理解,此時的Asterisk服務器相當於電信公司的程控交換機).
端口是通過配置使用的信令進行定義的,而不會是物理端口類型.例如,一個物理的FXO(FXS)端口可以在配置中使用FXS(FXO)信令定義.FX_板卡不是通過他們是什么進行命名,而是根據他們連接的設備進行命名.因此FXS卡,是連接終端的,為了做它的工作,FXS卡必須像中心局(CO)進行運轉,使用FXO信令.同理,FXO卡連接CO,意味着它需要像終端那樣進行運轉,使用FXS信令.
在你的TDM400p上決定FXO和FXS端口
模塊1是綠色的FXS模塊,模塊2是橙紅色的FXO模塊,右下角是Molex連接器,從這里利用電腦提供電源.
注意,插入一個FXS端口(綠色模塊)到PSTN會損壞模塊和板卡.如果你有FXS模塊,一定要將你電腦的電源連接到TDM400P的Molex連接器,用於生成電話震鈴的電壓.如果你只有FXO模塊,那么不要求有Molex連接器.
4.4 配置FXO通道
Zaptel硬件配置
Zapata硬件配置
Dialplan配置
4.5 配置FXS通道
Zaptel硬件配置
Zapata硬件配置
Dialplan配置
4.6 SIP配置
會話初始協議(SIP),通常用於VoIP電話(硬件電話或者軟電話),進行呼叫建立和呼叫結束,和呼叫進程中的協商.基本上,它幫助兩個端點互相通話.SIP不處理媒體,當呼叫建立后,它通過實時傳輸協議(RTP)在電話A和電話B之間直接傳輸媒體.
SIP和RTP
SIP是一個應用層的信令協議,使用眾所周知的5060端口進行通信.SIP可以通過UDP或者TCP傳輸層協議進行傳輸.
RTP用於在端點之間傳輸媒體(例如語音).Asterisk中RPT使用大數字的無特權的端口(默認是10,000到20,000).
SIP配置
下面是基本的sip.conf文件:
[general]
context=default
srvlookup=yes
[tim]
type=friend
secret=welcome
qualify=yes ;Qualify peer is no more than 2000 ms away
nat=no ;this phone is not natted
host=dynamic ;this device registers with us
canreinvite=no ;Asterisk by default tries to redirect
context=internal ;the internal context controls what we can do
sip.conf文件開始是一個[general]section,包含通道設置,所有用戶和對端的默認選項.在一個端-用戶/端的基礎上,可以不考慮默認的配置,而在user/peer定義中重新進行配置.
域名系統服務記錄(DNS SRV records)是建立一個邏輯和可解析地址的方法,你可以到達這個地址.這種方法可以是呼叫傳輸到不同的地點,而不需要改變邏輯地址.使用SRV記錄,你可以獲取DNS的很多好處,然而禁止它們打破SIP RFC的規定,而且禁止了基於域名的SIP呼叫.(注意如果多個記錄返回,Asterisk只會使用第一個).
DNS SRV記錄查詢在Asterisk默認禁止,但是強烈建議你打開.啟動使用sip.conf中[general]section里面的srvlookup=yes.
每個連接都會定義為用戶,端或者朋友.用戶類型是用於認證呼入呼叫.端類型用於呼出呼叫.朋友類型兩種都用.擴展名用中括號定義([]).本例中我們已經定義了一個端點為朋友.
Secret是用於認證的密碼.我們的secret是welcome.我們可以監視Asterisk服務器和電話之間的延時,使用qualify=yes,確認遠端設備是否可達.可以用於監視任何遠端設備,包括其他的Asterisk服務器.默認情況是Asterisk認為時延在2,000ms(2 seconds)以內的設備可達,你可以配置Asterisk判斷對端是否可達的時間,通過將yes替換為毫秒.
如果一個號碼的網絡地址翻譯(NAT)設備后面,例如路由器或者防火牆,配置nat=yes,強迫Asterisk忽略號碼的聯系信息,使用收到的包的地址信息.
設置host=dynamic將要求號碼注冊,以便Asterisk可以知道如何找到電話.將一個端點綁定到一個單獨地址或者fully qualified domain name(FQDN),將dynamic替換IP地址或者域名.注意這只是限制你呼叫的目的地址,用戶允許從任何地點發起呼叫(假定它成功鑒權).如果你設置host=static,則終端設備不需要注冊.
我們已經設置了canreinvite=no.在SIP協議,邀請用於發起呼叫,重定向媒體.在初始邀請后相同對話中發起的任何邀請都被視作重邀請(reinvite).例如,假設雙方正在交換媒體信息,如果一方呼叫等待,Asterisk設置為播放呼叫等待音樂,Asterisk會發起到第二個客戶端的重邀請,告訴將他的媒體流定向到PBX,然后就開始傳輸音樂流,或者一個等待客戶的通知.
最開始的用戶再到PBX的重邀請中發起一個摘機的命令,然后PBX發起一個重邀請到第二方,要求它將媒體流重新定向到發起方,結束呼叫等待音樂,重新連接客戶端.
通常,當兩個端點建立起呼叫,他們直接從一端到另一端傳輸媒體.Asterisk通常在媒體通道打破這個規則,允許它聽到電話鍵盤上的撥號音.這是必須的,因為如果Asterisk不能確定呼叫長度,計費將不准確.配置canreinvite=no讓Asterisk媒體通道經過自己,而不允許RTP信息直接在端點之間傳送.
Asterisk在以下的任何情況下都不會發起重邀請:
如果客戶端的任何一方配置為canreinvite=no;
如果客戶端不能協商編碼,Asterisk需要執行語音編碼轉換;
如果客戶端的任何一方配置為 nat=yes;
如果Asterisk在呼叫中需要監聽雙音多頻(DTMF)音(用於呼叫前轉或者其他功能).
最后context=internal定義了指令的地點,用於控制電話的權限,以及如何處理此號碼的呼入呼叫. sip.conf中設置的context名稱和extensions.conf中的匹配.
如果你配置了相似的一組用戶,你可以使用相似的命令在[general]字段.Asterisk會使用默認的定義,除非他們在用戶的配置文檔中明確改變.
客戶端配置
下載軟電話X-ten的X-Lite客戶端 http://www.xten.com,配置客戶端.最重要的是注冊的用戶名和密碼,和你要注冊的Asterisk服務器的地址.
出現的問題:
(1) X-ten提示login timed out.但是網絡正常,進行本機呼叫.
解決:
不能設置成環回地址127.0.0.1
(2)CVsSocket::AsyncSend:send failed:拒絕連接,但是x-ten運行正常,可正常呼叫.
解決:
:(
(3) pbx.c:1738 pbx_extension_helper: Cannot find extension context 'internal'
解決:
在/etc/asterisk/extensions.conf文件中添加呼叫規則如下:
[internal]
exten=>100,1,Dial(SIP/tim)
exten=>611,1,Echo()
(4) NOTICE[2200]: res_musiconhold.c:507 monmp3thread: Request to schedule in the past?!?!
解決:
進入asterisk安裝目錄,重新安裝asterisk,安裝mpg123.
# cd /usr/src/asterisk- 1.2.7.1
# make clean
# make
# make mpg123
# make install
4.7 配置入局IAX連接
IAX(Inter-Asterisk eXchange)協議通常用於服務器間通信.IAX和SIP協議最大的區別在於媒體(語音)在端點之間傳輸的方式不同.
SIP協議中,相對於使用信令模式來說,RTP(媒體)流使用不同的端口進行傳輸.例如,Asterisk默認的情況是在5060端口接收SIP信令,在10000-20000端口接收RTP(媒體)流.IAX協議則不同,所有的信令和媒體流都通過一個4569端口進行傳輸.這種方式的好處是IAX協議能更適合在有NAT相關拓撲的應用.
IAX用戶習慣對進入PBX系統的呼叫進行鑒權和處理.對從PBX系統呼出的呼叫,Asterisk應用IAX的iax.conf文件的端點進入(條目)對遠端進行鑒權.
講解創建iax.conf和extensions.conf,使你可以接受從其它FWD(一個免費的Voip運營商)用戶發出的呼叫.呼出IAX連接的章節講述如何發起呼叫.
iax.conf配置
在iax.conf文件中,段落是由方括號定義的([]).每個iax.conf文件至少需要一個主要段落:[general].在這個段落中,定義使用IAX協議的相關設置,你可以不考慮在[general]段落中默認編碼,而在user or peer定義中進行設置.
略
4.9 調試
連接控制台
直接在控制台啟動Asterisk:
# /usr/sbin/asterisk -c
用遠程連接控制台,然后連接:
# /usr/sbin/asterisk
# /usr/sbin/asterisk -r
如果遇到某個模塊不能載入的問題,或者某個模塊導致Asterisk不能載人,用-c flag啟動Asterisk進程,監視模塊載人狀態.
啟動Verbosity和Debugging
Asterisk可以以WARNING,NOTICE和ERROR消息形式輸出調試信息.激活不同級別的verbosity,使用set verbose,附加一個數值.有效值從3-10,例如設置verbosity的最高數值,使用:
# set verbose 10
你也可以通過設置調試級別激活核心調試信息.激活控制台的DEBUG輸出,需要在logger.conf文件中增加debug到console=>文段,例如:
console=>warning,notice,error,event,debug
設置調試級別的有效值為3-10,例如:
# set debug 10
第5章 撥號方案基礎
摘錄<<Asterisk.The.Future.of.Telephony>>
撥號方案定義了Asterisk如何處理來話和去話,它由指令和步驟列表組成,Asterisk按步驟來執行這些指令.與傳統電話系統不同,Asterisk的撥號方案是完全可定制的.
5.1 撥號方案語法
撥號方案在文件extensions.conf中定義.文件extensions.conf通常在/etc/asterisk/目錄下.但是其位置可以改變,取決於Asterisk的安裝方式.其它常見的位置包括/usr/local/asterisk/etc/和/opt/asterisk/etc/.
撥號方案由4部分組成:contexts,extensions,priorities和applications.
Context
Dialplans被分成幾個段,這些段稱為context.Context用來對extension的組命名.在一個context中定義的extension完全獨立於另一個context中定義的extensiont,本章末尾將介紹如何允許context之間相互交織.
Contexts的表示方法是把名字放在方括號([])的中間.這個名字可以由A-Z,數字0-9,以及連字號和下划線組成.如: [incoming]
Extension
在每一個context內,可以定義一個或者多個extension. extension是Asterisk要執行的指令,由來電或者通道上所撥數字來觸發.
extension的語法是: exten=>
之后是extension的名字.在於電話系統打交道的時候,我們把extension看作是呼叫另一部電話所撥的號碼.在asterisk上,意味着更多的東西.
一個完整的extension由三部分組成:
Extension的名字或者號碼
Priority(每個extension可以有多個步驟,步驟的編號稱作Priority)
應用(或者命令),針對呼叫完成一些動作
這三個部分用英文逗號分開,如:
exten=>name,priority,application()
例如:
exten=>123,1,Answer()
在這個例子中,extension的名字是123, priority是1, 應用是Answer().
Priority
每個extension可以有多個步驟,稱作priorities. 每個priority都按順序編號,從1開始.每個priority執行一個規定的應用.下面給出一個例子,這個extension接聽電話(編號為1的priority),然后掛斷(編號為2的priority):
exten=>123,1,Answer()
exten=>123,2,Hangup()
注意:必須確保priority從1開始並且是連續的編號.對於特定的extension,Asterisk遵從priority的數字順序.
Application
無序號的priority
在Asterisk1.2版本里,Priority編號增加了新的變化,引入了n priority,表示"下一個"的意思.每次Asterisk遇n這個priority的時候,就取出前一個priority的編號加上1.例如:
extern=>123,1,Answer()
extern=>123,n,do something
extern=>123,n,do something else
extern=>123,n,do one last thing
extern=>123,n,Hangup()
1.2版也允許給priority分配一個文字標號.要給priority分配文字標號,只需要在priority后面的括號內加上這個標號,如:
extern=>123,n(label),do something
5.2 一個簡單的撥號方案
我們以一個簡單的例子來開始.在呼叫進來時,Asterisk應答這個呼叫,播放聲音文件,然后掛斷,用這個簡單例子來指出撥號方案基本原理.
為了工作正確,至少創建一個通道(Zap或Sip通道),並且作了配置.
s Extension
在着手撥號方案前,先介紹一個特別的extension,名字叫做s. 當沒有指定extension的呼叫(例如,正在振鈴的FXO線路)進入context的時候,就由這個s extension來處理.(s表示"start"開始,因為多數的呼叫都是從s extension開始).我們要在呼叫上完成三個動作(接聽,播放聲音文件,最后掛斷),所以要創建有三個priority的s extension. 我們把這三個priority放到[incoming]里,所有來話都應該從這個context開始:
[incoming]
exten=>s,1,application()
exten=>s,2,application()
exten=>s,3,application()
現在我們所要做的事情就是填寫應用.
Answer(),Playback()和Hangup()應用
Answer()應用用於接聽正在振鈴的通道,並不為接受來話的通道進行初始化設定(確有不少應用不需要先應答通道,但是在完成其它動作之前進行適當的應答是一個好習慣).Answer()不需要任何參量.
Playback()應用用於在通道上播放事先錄制好的語音文件.在使用Playback()應用時,系統不會理會來自用戶的輸入.Asterisk帶有很多專業錄制的語音文件,默認的目錄通常是/var/lib/asterisk/sounds/. 這些文件都是GSM格式.使用格式如下:
Playback(filename) ;將播放文件名為filename.gsm的語音文件,並假定這個文件 位於默認的語音文件目錄內.
Playback(/home/tim/sounds/filename) ;也可以包括完整路徑,將播放/home/tim/sounds/目錄下的filename.gsm文件.
Playback(custom/filename) ;將播放默認語音文件目錄內custom/子目錄中的filename.gsm文件.
Hangup()完成掛斷一個正在活動的通道.主叫方將收到通話掛斷的指示.當要結束通話時,可以在context的末尾使用這個應用,以確保主叫不會繼續停留在撥號方案內.這個應用不需要參量.
第一個撥號方案
方案如下:
[incoming]
exten=>s,1,Answer()
exten=>s,2,Playback(hello-world)
exten=>s,3,Hangup()
5.3 在撥號方案中加入邏輯
剛剛建立的撥號方案是靜態的,對每個呼叫總是作相同的事情,現在加入一些邏輯,讓它根據用戶的輸入來完成一些不同的動作.
Background()和Goto()應用
構建交互式Asterisk系統的關鍵是Background()應用.與Playback()相同的是,它也播放事先錄制好的語音文件;與Playback()不同的是,當主叫方按下電話鍵(1個或者多個)的時候,會中斷語音的播放,轉到與所按數字對應的extension. 例如,假設主叫方按下5, Asterisk停止播放語音,把呼叫的控制發送給extension 5的第一個priority.Background()語法與Playback()類似.
Background()應用通常用於創建語音菜單,以免接待員接聽每一個電話
另外一個有用的應用是Goto().它用於把呼叫發送到另一個context,extension,以及priority. Goto應用使得在撥號方案的不同部分有序的轉移非常容易.語法如下:
exten=>123,1,Goto(context,extension,priority)
看下面例子:
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>1,1,Playback(digits/1)
exten=>1,2,Goto(incoming,s,1)
exten=>2,1,Playback(digits/1)
exten=>2,2,Goto(incoming,s,1)
非法輸入和超時的處理
第一個語音菜單已經完成,我們在加入幾個附加的特殊extension.首先,需要一個用來處理非法輸入的extension,從而在主叫方按下一個無效輸入(比如在上面的例子中按下3),呼叫被送到 i extension. 其次,需要一個extension來處理主叫方沒有及時(默認的時間是10秒)輸入的情況.如果主叫方在Background()完成語音文件播放之后很久才按鍵,呼叫將被轉移到 t extension. 如下:
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>1,1,Playback(digits/1)
exten=>1,2,Goto(incoming,s,1)
exten=>2,1,Playback(digits/2)
exten=>2,2,Goto(incoming,s,1)
exten=>i,1,Playback(pbx-invalid)
exten=>i,2,Goto(incoming,s,1)
exten=>t,1,Playback(vm-goodbye)
exten=>t,2,Hangup()
現在功能還是有限,因為外面的主叫無法與實際的人聯系.為了做到這一點,我們還需要一個Dial()應用.
使用Dial()應用
Dial()需要4個參量.第1個是呼叫的被叫地,由呼叫所采用的(傳輸)技術,反斜線,遠地資源(通常是通道名稱或編號)等組成.例如,假定我們要呼叫名字為Zap/1的Zap通道(連接了普通模擬電話的FXS通道),那么技術是Zap,資源是1. 與此類似,到一個SIP設備的呼叫的被叫地是SIP/1234, 而到一個IAX設備的呼叫的被叫地是IAX/fred. 假如在extension123到達撥號方案時,要Asterisk對Zap/1通道振鈴,要加入下面這個extension:
exten=>123,1,Dial(Zap/1)
當這個extension被執行時,Asterisk會連接通道上Zap/1的電話振鈴,也可以同時撥多個通道,如下:
exten=>123,1,Dial(Zap/1&Zap/2&Zap/3)
Dial()會橋連來電,無論被叫地中的哪一個通道先接聽.
Dial()應用的第2個參量是超時,單位為秒.如果給定了超時參量,Dial()會一直對被叫地進行呼叫,直到超時后才放棄,然后轉移到該extension中的下一個priority. 如果沒有指定超時時間,Dial()會一直呼叫該通道,直到有人接聽,或者主叫掛機.我們把10秒超時加到extension中:
exten=>123,1,Dial(Zap/1,10)
如果呼叫在超時之前被接聽,通道就被橋連,撥號方案完成,如果被叫地沒有應答,Dial()會繼續到該extension的下一個priority.但是如果被叫通道忙,Dial()將轉到priority n+101, 如果其存在的話(其中的n是Dial()被調用的priority).這樣我們就能夠以不同於被叫地忙的方式來處理未接聽電話.如下:
exten=>123,1,Dial(Zap/1,10)
exten=>123,2,Playback(vm-nobodyavail)
exten=>123,3,Hangup()
exten=>123,102,Playback(tt-albusy)
exten=>123,103,Hangup()
正如你所看到的,在這個例子中,如果呼叫未被接聽,將播放vm-nobodyavail.gsm語音文件,如果Zap/1通道正忙,則播放tt-allbusy.gsm語音文件.
Dial()應用的第3個參量是可選擇的字符串.它包含一個或多個能夠影響Dial()應用行為的字符.最常用的是字母r.如果把r作為第3個參量,在通知被叫通道有來電的這段時間內,主叫方會聽到振鈴聲音.
此時,已經知道如何使用Dial()應用,撥號方案中編號為1和2的extension變得沒有用了.我們把它們用extension101和102來代替,這樣就允許外部的主叫方把電話打給tim和david:
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>101,1,Dial(Zap/1,10)
exten=>101,2,Playback(vm-nobodyavail)
exten=>101,3,Hangup()
exten=>101,102,Playback(tt-allbusy)
exten=>101,103,Hangup()
exten=>102,1,Dial(SIP/david,10)
exten=>102,2,Playback(vm-nobodyavail)
exten=>102,3,Hangup()
exten=>102,102,Playback(tt-allbusy)
exten=>102,103,Hangup()
exten=>i,1,Playback(pbx-invalid)
exten=>i,2,Goto(incoming,s,1)
exten=>t,1,Playback(vm-goodbye)
exten=>t,2,Hangup()
Dial()應用的最后一個參量是URL.如果被叫通道支持在呼叫的同時接受URL,那么所指定的URL將被發送,這個參量很少使用.
如果要在FXO Zap通道上產生一個去話,可以使用下面的語法在那個通道上撥號:
exten=>123,1,Dial(Zap/4/5551212)
這個例子在Zap/4通道上撥號碼555-1212.對於其它類型的通道,如SIP和IAX,簡單的把被叫地作為資源,見下:
exten=>123,1,Dial(SIP/1234)
exten=>124,1,Dial(IAX2/tim@asteriskdocs.org)
注意:任何參量為空,如保留超時參量為空,如下:
exten=>123,1,Dial(Zap/1,,r)
給內部呼叫增加Context
context的一個重要功能是為不同的主叫用戶區分特權(如長途通話,或者呼叫特定的extension).在下面例子中,我們建立兩個內部電話的extension,加到撥號方案里去,然后配置這兩個extension可以彼此呼叫.為達到這個目的,創建一個新的叫做[internal]的context.
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>101,1,Dial(Zap/1,10)
exten=>101,2,Playback(vm-nobodyavail)
exten=>101,3,Hangup()
exten=>101,102,Playback(tt-allbusy)
exten=>101,103,Hangup()
exten=>102,1,Dial(SIP/david,10)
exten=>102,2,Playback(vm-nobodyavail)
exten=>102,3,Hangup()
exten=>102,102,Playback(tt-allbusy)
exten=>102,103,Hangup()
exten=>i,1,Playback(pbx-invalid)
exten=>i,2,Goto(incoming,s,1)
exten=>t,1,Playback(vm-goodbye)
exten=>t,2,Hangup()
[internal]
exten=>101,1,Dial(Zap/1,,r)
exten=>102,1,Dial(SIP/david,,r)
在這個例子中,我們在[interanl]context中加了兩個新的extension.這樣,使用通道Zap/1的人可以拿起電話撥102來撥打通道channel SIP/david上的人,同樣,注冊為SIP/david的電話可以撥打101來撥打Zap/1的電話.
如果你認為你的用戶可能通過支持名字的VoIP來傳輸撥號,添加使用名字的extension也不是什么不好的事情.如下修改:
[internal]
exten=>101,1,Dial(Zap/1,,r)
exten=>tim,1,Dial(Zap/1,,r)
exten=>102,1,Dial(SIP/david,,r)
exten=>david,1,Dial(SIP/david,,r)
使用變量
例如,建立一個叫做TIM的變量,並給其賦予值Zap/1.這樣,在寫撥號方案時,可以利用名字來引用Tim的通道,不需要直接記住Tim使用的Zap/1.為了把指賦給變量,只需要輸入變量名稱,等號和值,如下所示:
TIM=Zap/1
引用變量有兩種方法.若要引用變量的名字,僅僅需要輸入變量的名字就可以了,例如:TIM;但如果要引用變量的值,則必須輸入美元符號,緊接着是大括號,在大括號內輸入變量名.下面的例子說明了如何在應用中引用變量:
exten=>555,1,Dial(${TIM},,r)
在撥號方案中有三種變量可以使用:全局變量,通道變量和環境變量.
1.全局變量
全局變量適用於所有context里的所有extensions.全局變量的好用之處在於它可以用於撥號方案中的任何地方,能夠增加可讀性和可管理性.
全局變量應該在extensions.conf文件的開始利用[globals]context定義.也可以使用編程的方式定義,利用SetGlobalVar()應用.如下:
[globals]
TIM=Zap/1
或
[internal]
exten=>123,1,SetGlobalVar(TIM=Zap/1)
2.通道變量
通道變量與特定的呼叫相關的變量(如Caller*IDnumber),與全局變量不同,通道變量只能在當前呼叫存在期間定義,並只能用於參與該呼叫的通道.
有很多的預先定義的通道變量可以用於撥號方案,在Asterisk源程序的doc子目錄下README文件中有詳細的說明.通道變量使用Set()應用來設置:
exten=>123,1,Set(MAGICNUMBER=42)
3.環境變量
環境變量是一種在Asterisk中訪問操作系統環境變量的方法.這些變量以${ENV(var)}形式引用,其中的var是所要引用的操作系統環境變量.
4.在撥號方案中加入變量
我們為兩個人,Tim和David加入變量:
[globals]
TIM=SIP/tim
DAVID=Zap/1
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>101,1,Dial(TIM,10)exten=>101,2,Playback(vm−nobodyavail)exten=>101,3,Hangup()exten=>101,102,Playback(tt−allbusy)exten=>101,103,Hangup()exten=>102,1,Dial({DAVID},10)
exten=>102,2,Playback(vm-nobodyavail)
exten=>102,3,Hangup()
exten=>102,102,Playback(tt-allbusy)
exten=>102,103,Hangup()
exten=>i,1,Playback(pbx-invalid)
exten=>i,2,Goto(incoming,s,1)
exten=>t,1,Playback(vm-goodbye)
exten=>t,2,Hangup()
[internal]
exten=>101,1,Dial(TIM,,r)exten=>102,1,Dial({DAVID},,r)
模式匹配
模式匹配可以使用一段代碼來對應許多不同的extensions.
1.模式匹配語法
使用模式匹配的時候,用不同的字母和符號來代表肯恩個要匹配的數字.模式總是用一個下划線(_)開始,它告訴Asterisk要做模式匹配,這不是一個extension名字.(這意味着不能用下划線作為extension名字的開始字符)
在下划線之后,可以使用一個或者多個下面列出的字符:
X
匹配0-9的任何數字.
Z
匹配1-9的任何數字
N
匹配2-9的任何數字
[15-7]
匹配任何數字或者指定的數字范圍.在這個例子中,匹配1,5,6或7.
.(句號)
通配符,匹配一個或多個字符.
應該在匹配了其他數字之后在使用通配符,如:
_.
實際上,如果你試圖使用它,Asterisk會警告你.如果可能,盡量使用下面的模式:
_X.
若要在撥號方案中使用模式匹配,只要把模式放在extension名字的位置:
exten=>_NXX,1,Playback(auth-thankyou)
在這個例子中,模式會匹配3位的extension,從200到999,這就是說,在這個context中,如果主叫撥200-999之間的任何extension,都會聽到聲音文件auth-thankyou.gsm的聲音.
必須了解的一件事情是,如果Asterisk發現有多個模式與所撥的extension匹配,它會使用最接近的那一個模式.比如說定義了下面的兩個模式,主叫方撥的號碼是888-555-1212:
exten=>_555XXXX,1,Playback(digits/1)
exten=>_55512XX,1,Playback(digits/2)
在這個例子中,會選擇第2個extension,因為它更接近.
2.模式匹配的實例
NANP與話費欺詐
略
3.使用EXTEN通道變量一旦撥了某個extension,Asterisk會把通道變量{EXTEN}設置為所撥的數字.可以使用應用SayDigits()來檢測出來:
exten=>_XXX,1,SayDigits(EXTEN)在這個例子中,SayDigits()應用會把所撥的3位extension讀出來.通常,把extension的前面幾位去掉對於處理{EXTEN}是很有用的.可以利用這樣的語法來實現: EXTEN:x,其中x是要去掉的位數.例如,假設EXTEN的值是95551212,那么{EXTEN:1}等於5551212. 再來看另外一個例子:
exten=>_XXX,1,SayDigits(EXTEN:1)在這個例子中,SayDigits()應用把所撥的extension的最后兩位讀出來.如果x是負數,SayDigits()給出所撥的extension的最后x位.在下面的例子中,SayDigits()只讀出所撥的extension的最后1位:exten=>XXX,1,SayDigits({EXTEN:-1})
開啟去話撥號
允許用戶向外撥打電話,首先要做的一件事情是給[globals]context加一個變量,用於定義那一個通道可以用來向外撥打電話:
[globals]
TIM=SIP/tim
DAVID=Zap/1
OUTBOUNDTRUNK=Zap/4
接下來,在撥號方案中添加一個用於去話的context.使用一個單獨的context的目的是能夠規定和控制誰可以撥打電話,以及可以撥打什么樣的去話.
首先,建立一個用於本地電話的context.為了與傳統電話交換機保持一致,我們在模式之前放上9,因此用戶必須在呼叫外部號碼之前撥9:
[outbound-local]
exten=>_9NXXXXXX,1,Dial(OUTBOUNDTRUNK/{EXTEN:1})
exten=>_9NXXXXXX,2,Congestion()
exten=>_9NXXXXXX,102,Congestion()
注意: 撥9並沒有立即給你外線,這和傳統的PBX系統不同.一旦在FXS線路上撥9,撥號音會停止.如果在撥9之后還希望有撥號音,加入下面一行(就在context定義之后):
ignorepat=>9
這個指令告訴Asterisk繼續提供撥號音,即便是在主叫方已經撥了指示的模式.
回顧一下我們剛剛所做的事情.增加了一個全局變量OUTBOUNDTRUNK,它會控制使用哪一個通道用於去話,還增加了一個用於本地去話的context.在priority1中,取出所撥的extension,用EXTEN:1語法去掉9,然后試圖在變量OUTBOUNDTRUNK所指定的通道上撥這個號碼.如果呼叫成功,主叫方就與去話通道建立橋連.如果呼叫不成功(要么是通道忙,要么是因為某種原因不能撥這個號碼,調用Congestion()應用,播放"快忙音"(擁擠聲音)讓主叫方知道呼叫不成功.在進一步往下走之前,先確認一下這個撥號方案允許撥打緊急電話號碼:[outbound−local]exten=>9NXXXXXX,1,Dial({OUTBOUNDTRUNK}/${EXTEN:1})
exten=>_9NXXXXXX,2,Congestion()
exten=>_9NXXXXXX,102,Congestion()
exten=>911,1,Dial(OUTBOUNDTRUNK/911)exten=>9911,1,Dial({OUTBOUNDTRUNK}/911)
下面,給撥號方案加一個用於長途電話的context:
[outbound-long-distance]
exten=>_9NXXXXXX,1,Dial(OUTBOUNDTRUNK/{EXTEN:1})
exten=>_91NXXNXXXXXX,2,Congestion()
exten=>_91NXXNXXXXXX,102,Congestion()
現在有了兩個新的context,如何允許內部用戶利用它們?我們需要一種辦法來使得一個context能夠使用另一個context.
INCLUDES
Asterisk允許在一個context中使用另一個context,通過include指令來實現.這用來授予訪問給不同的撥號方案段.我們使用include功能來讓[internal]context中的用戶能夠撥打去話.首先介紹一下語法.
include語句的形式如下所示,其中的是我們要包含在當前context的遠地context:
include=>context
在當前context包含另外的context時,必須注意包含的順序.Asterisk首先試圖在當前context中匹配extension.如果不成功,會去嘗試第一個包含進來的context,然后按照包含順序再去嘗試其他的context.
到目前為止,撥號方案有兩個context用於去話.但是[internal]context中的人還不能夠使用它們.我們用在[internal]context包含兩個去話context來實現使用,如下所示:
[globals]
TIM=SIP/tim
DAVID=Zap/1
OUTBOUNDTRUNK=Zap/4
[incoming]
exten=>s,1,Answer()
exten=>s,2,Background(enter-ext-of-person)
exten=>101,1,Dial(TIM,10)exten=>101,2,Playback(vm−nobodyavail)exten=>101,3,Hangup()exten=>101,102,Playback(tt−allbusy)exten=>101,103,Hangup()exten=>102,1,Dial({DAVID},10)
exten=>102,2,Playback(vm-nobodyavail)
exten=>102,3,Hangup()
exten=>102,102,Playback(tt-allbusy)
exten=>102,103,Hangup()
exten=>i,1,Playback(pbx-invalid)
exten=>i,2,Goto(incoming,s,1)
exten=>t,1,Playback(vm-goodbye)
exten=>t,2,Hangup()
[internal]
include=>outbound-local
include=>outbound-long-distance
exten=>101,1,Dial(TIM,,r)exten=>102,1,Dial({DAVID},,r)
[outbound-local]
exten=>_9NXXXXXX,1,Dial(OUTBOUNDTRUNK/{EXTEN:1})
exten=>_9NXXXXXX,2,Congestion()
exten=>_9NXXXXXX,102,Congestion()
exten=>911,1,Dial(OUTBOUNDTRUNK/911)exten=>9911,1,Dial({OUTBOUNDTRUNK}/911)
[outbound-long-distance]
exten=>_9NXXXXXX,1,Dial(OUTBOUNDTRUNK/{EXTEN:1})
exten=>_91NXXNXXXXXX,2,Congestion()
exten=>_91NXXNXXXXXX,102,Congestion()
這兩個include語句讓[internal]context內的主叫方可以撥打去話.應該注意到,出於安全的考慮,要確保[inbound]context永遠不要允許撥打去話.(如果一旦給了這樣的機會,外面的人可以撥入你的系統,然后在撥打收費電話出去,讓你來承擔通話費用!)