asterisk的基本配置
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永远不要允许拨打去话.(如果一旦给了这样的机会,外面的人可以拨入你的系统,然后在拨打收费电话出去,让你来承担通话费用!)