Dialplan :对电话进行路由,决定和影响通话的流程。
XML Dialplan
由一系列的 XML 配置文件组成,可以是静态配置的,也可使用动态配置方式从其他服务器或脚本中动态获取。
配置文件的结构
默认位置: conf/dialplan,在freeswitch.xml 中定义,由X-PRE-PROCESS 预处理指令装入:
dialplan 由多个Context 组成。每个Context 中有多个Extension。
dialplan 的完整结构
Extension 相当于路由表中的表项,每一个Extension都有一个name属性,name 可以是任意合法的字符串。
在Extension中对condition进行判断,如果满足,则执行对应的Action。
例如:将Extension 配置加入到 conf/dialplan/default.xml 中,并作为第一个 Extension
放在第一个Extension的位置(13~14行)
在freeswitch控制台上执行 reloadxml。按F8(等于console loglevel debug)将log级别设置为Debug,以显示详细日志,注册软电话,拨叫1234或echo。
第一行 Processing 说明是在处理 Dialplan,Seven是SIP名字,1000是分机号(主叫号码)1234是被叫号码。
第二行 parsing(解析XML)阶段
第三行 该 Extension 中有一个condition(destination_number)是否与配置文件中的正则表达式相匹配。匹配成功会显示
第四行 第一个执行的Action 是 answer(App),用于对来话进行应答,然后执行 echo,相当于一个回音壁。
产生的log:
默认的配置文件简介
系统默认提供的配置文件包含三个 Context :default、features、public;分别在三个XML文件中。
default是默认的dialplan,注册用户一般都可以通过它来打电话;public 一般用于接受外来呼叫。
正则表达式
dialplan 使用与 Perl 兼容的正则表达式(Perl-Compatible Regular Expression,PCRE)匹配算法。
freeswitch 提供了简单的API 可以来测试正则表达式:
通道变量
在freeswitch 中,每一次呼叫由一条或多条腿(Call Leg)组成,其中的一条腿又称为一个Channel(通道),每个channel都有很多属性,用于标识channel的状态、性能等,这些属性称为Channel Variable(通道变量)。
info(App)查看所有的通道变量;先修改dialplan,在default.xml中加入下列Extension:
在freeswitch控制台执行reloadxml,从软电话呼叫1235或info.
所有的通道变量都可以在dialplan中访问,使用格式是:${变量名},如 ${destination_number}。
将下列配置加入到dialplan中:
呼叫123456789
在所有的dialplan解析完成后,channel状态才进入执行(standard EXECUTE)。
日志级别
一个Action通常有两个属性(attribute):一个是Application,代表要执行的app,另一个是data,就是app的参数,当app没有参数时,data可以省略。
一个Action必须是一个合法的xml标签。
部分info中显示的变量与通道变量的对于关系
测试条件
测试条件:针对被叫号码
<condition field="destination_number" expression="^1234$">
针对IP
dialplan中的测试条件
针对用户,在用户目录中设置变量,必须使用${}对变量进行引用:
用户目录中的设置
dialplan中的测试条件
一般来说,测试条件不能嵌套,但可以叠加。
错误示例
正确示例
break参数(假设两个条件分别为 A和B)
假设呼叫1234,如果来自192.168.7.7,就播放早上好;如果来自192.168.7.8,就播放晚上好。
使用break参数
动作与反动作
使用反动作(AntiAction)
如果呼叫来自192.168.7.2,播放早上好,否则播放晚上好(不管是否来自192.168.7.8)。
工作机制深入剖析
Channel状态机
当新建(NEW)一个channel时,首先会初始化(INIT),然后进入路由(ROUTING)阶段,Hunting(选线)后会执行(EXECUTE)一系列动作,最后无论谁挂机,都会进入挂机(HANGUP)阶段。报告(REPORTING)用于统计、计费等,最后将Channel销毁(DESTROY)释放系统资源。
在EXECUTE状态,可以会发生转移(Transfer),可以转移到同一context下其他的extension或其他context下的extension,会重新进行路由。
用户呼叫1234,如果来自192.168.7.7,则播放早上好,如果来自192.168.7.8,则播放晚上好;否则,什么都不做。
有些情况下,dialplan中会有多个extension满足匹配规则,我们希望所有的匹配规则都能执行,使用continue="true"参数。
绝对条件(Absolute Condition):空的condition,没有匹配规则。
实际上两者不等价;而等价于:
内联执行
在Action上增加了一个inline属性
适合inline执行的app必须能很快的执行流程,一般是很多地存取某个变量,并且不能改变当前channel的状态。满足
案例
案例解析
1.Local_Extension
conf/dialplan/default.xml 中的Local_Extension部分:
刚才省略的”many actions“
其中,set和export都是设置一个变量,dialed_extension=1001。set是将变量设置到当前的channel上,即a-leg。export还设置了一个特殊的变量,叫export_vars=dialed_extension。
bind_meta_app :在该channel上绑定DTMF。绑在b-leg。
如果发生呼叫转移,用户听到的回铃音。
call_timeout 是设置呼叫超时的变量
接下来
hash是内存中的哈希表数据结构。可以设置一个键·值对(key-value pair)。
set的将变量存绑到channel上,以通道变量的形式存在;hash保存到内存的哈希表数据结构中。
设置通道变量:
nolocal:告诉export只将该变量设置到b-leg上,而不要设置到a-leg上。
往哈希表中插入数据:
bridge的最关键的部分。把两条腿1000和1001给桥接起来。
bridge的参数是一个标准的呼叫字符串(dial string)。domain和domain_name都是预设的变量,默认就是服务器的ip地址。user是一个特殊的endpoint,指本地用户。
等价于以下的export:
振铃后的情况
下面的设置只在用户忙或无应答的情况下才会继续呼叫流程:
answer app首先会使freeswitch给主叫1000回送应答消息,以建立真正的媒体流,准备对其播放声音。
sleep 表示暂停,1000表示暂停的毫秒数(1s),然后转到1001的语言信箱。
2.回声和延迟回声
拨打9196,就能听到自己的回声。
dialplan如下
与echo类似,delay_echo可以使用回声有一定延迟:
3.会议
nb_conference :narrow band conference,默认的8000Hz的窄带电话会议。
conference是一个app,假设呼叫3000,IP地址是192.168.7.2。
3000-ip地址是会议的名字,@后面的default表示一个会议的profile。
4.将通话的双方转入会议
bind_meta_app是一个app,3表示绑定DTMF按键3,b表示要绑到b-leg上,s表示Same。
features这个context在 conf/dialplan/features.xml中定义,很容易找到匹配cf的这个extension:
transfer是一个app,它会将当前通话重新转移到ROUTING阶段,重新去dialplan中进行路由。第一个参数是-both,表示要将它自己和a-leg都转到dialplan中重新路由。类型仍然是xml,context是default,被叫号码30${dialed_extension:2}中的dialed_extension的变量
用export把变量设置到b-leg上,就是最初的被叫号码1001,${dialed_extension:2} 从1001的第二个位置开始截取,一直截取到字符串结尾的字符串,由于是从0开始计数,结果是01。
transfer 一行等价于:
-both表示将两条腿都分别转到3001这个extension上。所有,重新路由后就到了会议的情况。最终1000和1001都进入名为3001-192.168.7.2的会议。