第三章 测试驱动演示配置
缺省安装完成后,开箱即用,你会发现FreeSWTCH已经能够完成许多令人惊讶的事情了!我们花费很多精力在编写演示模板,缺省情况下,安装完成后,FreeSWITCH就已经配置为一个强大的演示原型。当我们添加一个新的特性时,编写一个新的模块时,或者有人提出一个新颖的用法时,我们都会把它们添加到演示配置实例中。请注意,稍后我们会再重复强调,演示配置实例并不打算用于生产系统!在其中,您会发现有大量的代码片段等着您复用;有许多实现技术;有许多方式可用于组织各种信息,包括用户信息、网关信息、应用信息、上下文信息和脚本信息等。它是一个巨大的FreeSWITCH相关知识库,它能在安装结束后正常运转。所以,在您觉得熟悉FreeSWITCH基础知识之前,可以尽情享用它;之后,在您添加一个特性或执行一项任务时,也可以回头来参考它。
在本章中,我们将讨论以下主题:
- VoIP和FreeSWITCH的重要概念
- FreeSWITCH命令行接口(fs_cli)的使用
- 配置一部话机与FreeSWITCH协同工作
- 呼叫系统提供的各种分机
需要理解的重要概念
FreeSWITCH是各种实时通信服务和操作的终极工具集:从支持WebRTC的视频会议、聊天、桌面共享到企业统一通信;多云端的多租户PBX到运营商级别的VoIP媒体服务器。这意味着极大的灵活性。FreeSWITCH可以完成很多事情,有很多现成的功能,可以通过多种方式完成很多不同的任务。
我们实现了许多种方式来利用这促灵活性。一个重要的方面就是FreeSWITCH遵循良好的实践,让行为与预期相符。在实时通信世界里,有许多相互冲突的需求。此外,还有很多软件和设备,它们中的大多数都有自己的怪癖。它们曲解和扩展官方协议(比如IETF的RFC标准)。或者充满BUG和错误,相互不兼容。请注意,我们的交互世界是许多专有世界的继承者,每个供应商都试图用与竞争对手不兼容的特性来锁定客户。FreeSWITCH实现了一种宽进严出的策略:接受输入时是非常开放和宽容,输出时严格遵守协议。因此,我们完全可以容忍SIP、WebRTC、TDM以及所有其他协议、标准和媒体的多种解释。我们实现了大量的变通方案来自动透明地管理每个设备或软件的所有怪癖。同时,我们一丝不苟地恪守开放标准的精神,力求实现普遍的兼容性和互操作性。大多数情况下,FreeSWITCH的功能适用于任何连接它的软件和设备。在极少数情况下,会出现意外,您可以确信调整某个参数就能解决问题,这时只需要查阅文档,或在线咨询。
在本章中,我们将通过演示配置展开一段旅程,进而理解了解FreeSWITCH的功能,并掌握一些基本概念。本书的其余部分将从这里开始构建,并扩展深化各种实现,管理你的FreeSWITCH所涉及的各个方面。
本书通篇都会碰到的重要概念有XML配置、正则表达式和call legs。
XML 配置
FreeSWITCH依据一棵完整的XML树的内容来理解它的配置文件。只要FreeSWITCH在运行,就不断地搜索查询XML树。每次FreeSWITCH内核或某个模块需要从配置中提取某个信息时,它们都会查询特定的片段。例如,假设一个SIP话机(或WebRTC客户端)使用账号user 1010@mydomain.org发起一路呼叫。当发起呼叫的第一条信令抵达FreeSWITCH时,mod_sofia模块(负责SIP信令)或mod_verto模块需要核实主叫用户的鉴权信息。这时,模块会查询:在用户目录中,1010@mydomain.org帐号对应的用户密码是什么?每次呼叫都会通过FreeSWITCH内部API寻问,相应的API会从XML配置的指定片段中(本例是目录片段)获取数据值。获取XML配置片段的任务可以通过多种方式完成:数据库查询、通过HTTP、脚本语言,等等。所有方法都会返回请求的XML片段。缺省演示配置首先从硬盘读取一个主XML文件,然后读取其中包含的所有XML文件。这个过程在FreeSWITCH启动时就执行,因此,每次你修改过某个XML文件,都需要刷新内存中的XML树才能生效。通常执行reloadxml命令就够了。FreeSWITCH每次请求信息都会从XML树中提取,但这棵树是启动时加载到内存的,因此,如果硬盘中的XML文件有任何的改动,都需要重构内存XML树。其它诸如数据库查询,HTTP查询的方法则是动态的,它们直接查询数据库或WEB服务器。
正则表达式
正则表达式(regexes)在FreeSWITCH配置文件中无处不在。它们是用于描述文本字符串的“公式”。例如,使用正则表达式,你可以用一条语句描述以下所有短语:“cats”、“cat”、“supercat”、“cat”和“anycAts”,它就是:^.*c[aA]t.?$。说明:插入符("^")表示字符串的开头,接下来的点(.)表示“任意字符“。星号(*)表示匹配前一个字符0次或多次(本例中是任意字符)。字符c没有特殊含意,就是匹配字符c。接下来用方括符括起的一段内容表示匹配方括符内所列举元素表中的一个(本例中就是小写a或大写A)。接下来的字符t就是字符t的点位符。接下来的点和前面一样,匹配一位任意字符。问号(?)表示匹配前面一子表达式零或一次,在本列中,就是字符t后面的内容是可选的,即匹配任意字符一次或零次。最后,美元符($)表示字符串结束。当然,你可以用一个更简单的表达式:"cat.*,它将匹配"cat", "cats", "catharsis",等等。
说明: 那么这个点的意思就是“随便什么角色”。星号表示前一个字符的不定数量(零或多个)——在本例中是“任意字符”。字符“c”表示……字符“c”。然后方括号(及其内容)表示一个字符,该字符可以是方括号内枚举的列表中的一个(因此,在本例中,字符可以是“small a”或“capital a”)。那么字符“t”是一个占位符…字符“t”。然后是“任意字符”。
此外,使用正则表达式,你还可以从一个字符串中截取一个或多个子串 。假设现在有一个字符串:“francesca bella ballerina”(特点是三个单词间以空格为分割符),你可以对这个串执行这样的正则解析:"([a-z]*) ([a-z]*) ([a-z]*)"。执行成功后,字符串将会被拆分成三个标记段,每个段包含一串由小写字母组成的子串,换句话说,原字符串以空格为分割符进行拆分了。这些序列串(从原字符串中拆分得来的子串),将自动放入内部的占位符$1、$2和$3中。因此,你可以利用这些占位符和正则表达式来构建新的字符串:"$1 $3 molto $2"将得到一个新字符串:"francesca ballerina molto bella",事实上,她是一个非常漂亮的舞者。
这一节向你展示了FreeSWITCH配置文件中正则表达式的强大功能 。你可以用模式表达分机、DID、用户、主叫、被叫网关待。你可以对它们选择、切片或混合。无论表达式匹配成功,还是失败,都可以构建逻辑。我们还将见到更多相关的内容。
Call Legs
对实时通信领域的人士而言,call leg是生死攸关的大事。起初,这个概念会让人迷惑,但随着时间的推移,和你对FreeSWITCH工作的深入,它会成为你的第二天性。
让我们从一个实例开始:我们在办公室里部署了一台PBX。Francesca想要打电话给Giovanni。她拨打了Giovanni的分机。在Francesca的话机和PBX间,建立了一路通话,这时Francesca将会听到回铃音(如果Giovanni不在,听到的可能是留言提示音)。在电信术语里,从Francesca到PBX这一路通话被称为"A" leg。随后,PBX从它的配置中得知它必须把A leg连接到Giovanni的话机,这样Francesca 和Giovanni才能通话。这时,PBX将会发起一路新的呼叫去连接Giovanni的话机,这一路通话称为B leg。如果Giovanni接机应答,PBX会把A leg和B leg连接在一起(电信术语叫桥接),最后,媒体流(音视频)将在两端间交换。
因此,站在FreeSWITCH的角度看,"A leg"是原始的入局呼叫;"B leg"是衍生的,由PBX发起的出局呼叫。从终端用户(Francesca)的角度看,如果PBX成功桥接A leg和B leg,只有在B leg被Giovanni接听之后,她们才能交谈,她的呼叫才算成功。
让我们假设Giovanni正好不在,Francesca的呼叫被连接到主意邮件系统(因此,她仍然与办公室PBX保持着联系),那么这时的呼叫就只有"A leg",它只有一组,那就是Francesca<=>PBX间的媒体流。
还有多于两条leg的案例,比如:Francesca呼叫Giovanni,接通后,她邀请第三个人加入,组成三方通话。这时,从Francesca到PBX的呼叫叫"A leg"。其它所有由这路通话衍生出来的通话统称B leg(换句话说,没有"C leg"、"D leg"的说法,它们统统是"B" leg)。
IVR交互式语音应答 (系统)
IVR是一些语音(很快会包含视频)菜单系统,当我们试图建立类似手机运营商的客服服务时经常用到,看起来像这样的“了解我们的最新报价,请按1;听取我们CEO的圣诞祝福,请按2;联系技术部门请按3;行政部门,账单发票请按4,重播菜单,请按5。好吧,IVR让人讨厌,但也很有用。
呼叫IVR,最初至少有一条leg,但经过一段时间后,可能会变成两个或三条,比如说转移到接线员,然后她邀请一个销售代表参与通话。
IVR与用户间的“交互性”,几乎都是通过用户按键还完成的。现在ASR(自动语音识别)系统发展迅速,它能够理解用户所说的话。这种识别通常是在有限的知识领域里实现的,比如在询问“您是从哪个州打电话过来的?”之后,嵌入ASR的IVR系统能够识别用户所说的州名。未来可能会提供可靠的ASR服务,能够“自由”地人机交谈,但目前技术还做不到。
在任何情况下,IVR逻辑都被实现为一棵树,从根节点开始,用户可以在导航分支间来回切换(通过拨号盘按键或语音切换),通常每个分支都会添加返回上层菜单的选项。
Extension, Context和Profile
这又是另一个造成巨大大困惑的源头。如果你是FreeSWITCH的初学者,那么,请忘掉过去你对“extension”这个单词所理解含义。在FreeSWITCH里,"extension"是一个非物理概念。它可以理解为:“一组context相关的指令”。好,引申出来的问题就是什么是context?context是一个有名字的extension集合。在某种程度上,我们在这里给了一个循环定义,context和extension互相定义对方。
请耐心听我说,接下来几段我们会继续解释所有这些概念。
FreeSWITCH有一个概念叫"profile"。一个profile指一个特定IP地址和端口对相关的配置集。例如:192.168.1.12:5060是一个profile;192.168.1.13:5060是另一个profile;192.168.1.12:5061是第三个profile。每个profile可以包含其它profile完全不同的配置。Profile里有一个是非常重要的配置项,说明呼入的电话是属于哪个context的。一路通话总是要归属到一个profile,比如呼叫到一个特定的地址:端口对。因此,我们说地址:端口对是profile的入口。一旦呼叫进入某个profile,FreeSWITCH首先要做的是查找profile的配置并确定context的配置值,以决定下一步路由。
假设呼叫的地址与端口是192.168.1.12:5060,我们把这个profile命名为"myprofile",在XML配置文件里,这个profile定义的context是"mycontext"。这意味着,入呼到"myprofile"的话务,只处理"mycontext"下所指定的extensions(指令集)列表。换句话说,入呼话务路由给profile所指定的context处理,它没办法访问这个context之外的任何东西。
Context就是话务的牢笼。这具有明显的安全性、逻辑性和实用性优势:例如,配置一个内部局域网可以访问profile,电话打到这里将被引导到一个提供内部办公电话功能的context,此外,它还可能连接PSTN网络,因为我们可能希望授权一些同事拨打国内和国际长途。另外配置一个拥有公网IP的profile,它处理经过路由器从外部网络访问内部局域网的话务,这些话务将被引导到一个只能拨打内部分机的context。这个profile只处理外部呼入电话,并且只能连接内部话机,没有访问PSTN的能力。这样,陌生人不能使用我们的付费网关连接PSTN。不同的地址:端口对,对应不同的profile,不同的PSTN。事实上它就是这么简单。
现在,是时候看看"extensions"到底是什么东西了。前面我们说过,每个extension就是一系列指令。当话务到达一个context(一个context就是一个extension的集合)时,对于每个extension来说,最重要的事情是:判断这个extension是否应该应用于这路呼叫?或者,从呼叫的角度来看问题:我应该执行这个extension吗?这个extension适用于我吗?每个extension都拥有一个"condition"属性,它定义了这个extension和这通话务是否匹配。如果匹配,话务将进入这个extension,并逐步执行这个extension所定义的指令。一个extension可以看成一个指令容器,呼叫必须满足"condition"限定的条件,才能进入容器内部并执行其中的指令。
重要的事情说三遍:extension==指令列表。一路呼叫想进入extension,必须满足"condition"限定条件。
引申的问题是:"condition"到底是什么鬼东西?一个"condition"就是一条正则表达式,它将应用于呼叫的某个属性。如果正则表达式匹配成功(也就是与呼叫属性的要求相符),那么话务将进入extension并执行其中的指令。
让我们看个例子:一个呼叫到达"myprofile"监听的地址192.168.1.12:5060,在"myprofile"的XML配置中,定义了"mycontext"的context;在"mycontext"中指定了许多extension;每个extension有它自己的"condition"。第一个extension有一个很简单的condition:对"destination_number"检查正则表达式"^1010$"是否匹配。因此,如果这路电话的"destination_number"属性值 正好是"1010"(正则展开的结果),那么匹配成功。既然入局话务的目标号码指向1010,那话务将进入这个extension并执行里边的指令。
在FreeSWITCH的术语中,这些指令被称作"action",它可以是任何东西:或是创建一个变量并为之赋值;或是读取一个变量,应用一个正则表达式将所有字母转换为大写,并创建一个新的变量来保存它;或是应答电话(摘机);或是向主叫播放一条预先录制好的消息;或是发起一个新的出局呼叫,然后把主叫桥接起来让双方通话;或是直接挂机;或是查询数据库;或是访问WEB服务器;或是读写文件,等等等等。这些action(通常包含在一个extension内部,松散结合,逐条执行),组合起来,直的什么事都能完成。
剩下的全部,profiles、contexts、extensions、正则表达式,都是你组织action,建立execution的逻辑和控制流的良好方式。此外,一路呼叫可以匹配多个extension(同时满足多个extension的限定条件),而且在很多场景中,是允许进入多个匹配的extension并执行每个extension所包含的action的。我们将会看到更多的相关信息。
变量
FreeSWITCH中的变量几乎与任何事物相关联。你可以把变量看成某事物的属性。比方说:之前我们定义一个入局呼叫("A leg")的属性叫"destination_number",而且我们把它当成一个字符串,与一个extension的"condition"作正则匹配,如果匹配成功则执行里面的action,否则跳过。“变量”是所有这些呼叫或会话属性的正式名称。
一个入局的呼叫有大量的关联变量,有通道变量;有call leg变量;有简单的变量。通道变量描述了大量的通道相关属性,从“目标号码”(我们之前已经见过)到“主叫源网络”;从“使用哪种音频编码”到“收到呼叫的时间”;从“呼叫的用户代理类型”到INVITE消息中包含了哪些SIP头域”。而不仅仅是那些“自然”,“描述性”,“客观”的变量。我们还可以创建和分配所有类型的任意变量,并将它们与我们的呼叫相关联。比如这些信息:呼叫是“销售部”发起的;呼叫被引导给“支持组”;呼叫每分钟花费5美分;这路通话允许的最大持续时长是600秒,等等。
所有这些变量(不论是原始的还是分配的),都可以由extension的condition正则表达式检查。因此,我们可以定制这样的逻辑:如果是工作日,工作时间,并且呼叫目标是销售部,那么让John、Rehan和Giovanni的话机同时振铃,并且把电话桥接给第一个接听者。
主叫配置变量
某些变量在整个电话续存期间都始终可见(我们也称这些变量是主叫配置的部分):
username
dialplan
caller_id_name
caller_id_number
callee_id_name
callee_id_number
network_addr
ani
aniii
rdnis
destination_number
source
uuid
context
现在,你可能对一些主叫配置里的变量名感到陌生,在本书后续内容中,你可以找到大量的相关信息,你也可以查寻在线文档(我们的开发人员也会经常查询在线文档,没有人能够记清几百个变量的具体含义)。
主叫配置变量的特殊之处在于:你可以在"condition"的"field"中通过纯粹的变量名引用它们,而不需要任何的特殊语法。我们之所以特别提到这一点,是因为在FreeSWITCH中,变量是通过特殊语法标识的,格式是${varname} 或 $${othervarname}(稍后我们会解释它们之间的差异)。因此,使用主叫配置变量时,你可以节约一点输入工作,并得到一份可读性更强的拨号方案。
<extension name="Local_Extension_Skinny"><condition field="destination_number" expression="^(11[01][0-9])$"><action application="bridge" data="skinny/internal/${destination_number}"/></condition></extension>
正如你所见,在condition的field域中,我们写的是"destination_number",而在别处,我们不得不写出完整的变量引用语法"${destination_number}"(实例中,action的变量数据)。所有主叫配置变量都是只读的(换句话说,你不能修改它们),并且在呼叫起始就被自动赋值了。它们描述的呼叫自身属性。
普通变量
FreeSWITCH大部分变量都用这样的语法表示:${varname}。变量可以被创建、赋值和重新赋值。事实上,赋值语句执行时,如果变量不存在,会先创建,如果已经存在,则把新值赋给它。
<action application="set" data="mystring='Rehan Allahwala'"/><action application="set" data="mystring2=SuzanneBowen"/><action application="set" data="mystring2=${mystring}"/>
“Set” app用于为变量赋值。这里我们展示了它在拨号方案的"action"中是如何工作的。我们创建或为变量重新赋值时,直接使用变量名(不使用${}语法)。在"set"的"data"参数内部,用等号(=)连接变量名和它的值。如果新值中包含空格,那么使用单引号以防止截断。
当我们希望引用变量值时,需要用到美元符格式的语法。因此,在前例中,我们首先把一串值赋给变量"mystring"(如果变量不存在会自己创建)。然后把另一串值赋给变量"mystring2"。最后,提取"mystring"变量的值并赋给"mystring2"变量。这时,${mystring2}的值是'Rehan Allahwala'。
FreeSWITCH的所有模块都可以使用变量。这有什么用?举例说明:一个销售问的成员发起一路呼叫时,你可以设置一个变量来存储部门名称。然后,在CDR模块里,可以提取这个变量值,并在CDR中记录这个信息,用于公司的成本分摊计算。
变量可以由我们凭空创建,也可以由FreeSWITCH自动创建,变量素材可以来自呼叫、环境、时间信息等等。
一些变量反映来自不同配置文件的值。这类变量大部分是可写的。例如:发传真时,我们可以设置一个缺省的站点标识符(通常是公司名称),但是,当同一台FreeSWITCH充当客户的传真服务器时,可以在拨号方案中把站点标识符替换为客户的标识。
预处理变量
这些变量由语法$${varname}表示。在某种程度上,它们不是真正的变量,而是只读的变量。它们由一个FreeSWITCH配置文件(/usr/local/freeswitch/conf/vars.xml)分配,然后在启动时替换。实际上,它和C预处理宏#define,或文本编辑器里的“查找并替换”命令的功能完全一样。
<X-PRE-PROCESS cmd="set" data="hold_music=local_stream://moh"/>
在上面例子中,可以通过编辑vars.xml文件,修改变量的值。配置中碰到$${hold_music} "的地方(包括拨号方案),都会被替换为“local_stream://moh”。如果拨号方案里有这么一行:
<action application="set" data="mystring=$${hold_music}"/>
它实际上等价于下面写法:
<action application="set" data="mystring=local_stream://moh"/>
因为这实际上就是FreeSWITCH启动时的一个文本查找与替换过程,所以,如果修改了vars.xml里的预处理变量值,你必须重启FreeSWITCH才能让它生效(只是重载XML配置而没有重启FreeSWITCH是不够的)。
FS_CLI与控制台控制FreeSWITCH
有许多种方法可以实时控制FreeSWITCH,让它执行你的意愿。你可以写程序、脚本,让FreeSWITCH与数据库交互。无论你用什么方法集成你的平台,你都将发现你会不时地回到FreeSWITCH的命令行。许多FreeSWITCH管理员只用CLI完成他们的日常任务。
/usr/local/freeswitch/bin/freeswitch -u freeswitch -g freeswitch -c
如果你的FreeSWITCH启动在前台(启动时加了-c选项),在一段短暂的暂停之后,所有的滚动信息都会被卷起,然后,界面就停留在FreeSWITCH的命令行控制台了:
更普遍的是,你不需要debug启动信息,你可以以另一种方式启动FreeSWITCH,让它在后台运行,成为一个服务进程,这时是没有控制终端的。
生产系统里通常这样启动:
/usr/local/freeswitch/bin/freeswitch -u freeswitch -g freeswitch
-nonat -ncwait
几秒钟后,命令执行结束,会告诉我们FreeSWITCH的进程ID,然后就什么也没有了。是的,FreeSWITCH运行在后台,并准备好提供服务,而我们可以使用fs_cli与它交互,模拟FreeSWITCH的天然控制台。
/usr/local/freeswitch/bin/fs_cli
在FreeSWITCH已经运行的系统上使用fs_cli,我们立刻能控制它:
退出控制台与FreeSWITCH
实际FreeSWITCH控制台(运行在前台)与fs_cli间最重要的区别是:退出实际控制台的唯一方式只能是关闭FreeSWITCH。这很棘手,因为对于几乎所有其他方面(fs_cli和freeswitch实际控制台),它们的外观和行为都是相同的。问题是,如果你退出fs_cli,FreeSWITCH继续运行在后台,可以接受呼叫。你始终可以重启fs-cli并重新连接FreeSWITCH(就像SSH连接远程服务一样)。小心:如果你退出实际FreeSWITCH控制台,相当于终止FreeSWITCH自身,而你需要重启FreeSWITCH才能继续提供服务。
问题是,如果退出fs-cli,freeswitch将继续在后台运行,接受调用等,并且您始终可以重新启动fs-cli并重新连接到它(如ssh终端到远程服务器)。小心,如果您退出实际的Freeswitch控制台,您将终止Freeswitch本身,并且需要重新启动它。
一些有用的CLI命令
以下大多数命令,既可以在实际控制台上执行,也可以在fs_cli上执行。输入命令后,请按回车键:
命令 |
作用 |
... (连续的三个点) |
退出fs_cli,如果在实际控制台上使用,关闭FreeSWITCH |
ctrl-d |
退出fs_cli |
fsctl shutdown |
关闭 FreeSWITCH |
hupall |
挂断所有呼叫 |
fsctl loglevel [0-7] |
更改日志显示级别 |
status |
告诉你一些基本的统计数据 |
version |
代码版本信息 |
show channels |
逐个显示所有的call leg |
show calls |
显示所有call leg,并以桥接分组(A+B) |
help |
其实没多少帮助。求人不如求己! |
最终,你将会经常使用"fsctl loglevel"命令,它允许你选择FreeSWITCH的日志输出级别。FreeSWITCH会在自己的内部工作上产生大量的信息,其中大部分在正常运行时是没有意义的。通常你可以选择级别3"ERROR",所有这一级别或更重要的(比如级别2"CRITICAL")信息才会显示。许多管理员喜欢让FreeSWITCH运行在级别4上,输出"WARNING"及以上级别的信息。但是,当你想要了解问题的原因,或报告BUG时,你需要把日志级别设置为7"DEBUG",反馈问题可以从终端滚动拷贝或从日志文件提取。
Log行缺省按日志级别区分颜色输出,训练你的眼睛,你将能够从输出是迅速捕获各种有效信息:红色表示错误信息或更严重信息(ERROR),紫色表示告警信息(WARNING),蓝色的(NOTIFY)信息,绿色的INFO信息,黄色的DEBUG信息。
配置SIP并呼叫演示拨号方案
当一些东西响起和闪烁时,我们几乎准备好面对激动人心的时刻。FreeSWITCH安装完成后,带有一个演示示例配置,其中包含许多功能。一个是非常复杂的拨号方案已经呈现在你眼前,尽情玩耍吧,感受FreeSWITCH的力量。
注意:这个拨号方案仅是一个示例,不要在生产环境中使用它。它太复杂了,拥有太多功能,你不了解它,所以无法控制它。
演示示例拨号方案和配置文件它只是Demo。当你完成与它的游戏后,请删除它们,并自己构建适用你的用例。如果你没有这个能力,那么请别人帮助你,请你的朋友或顾问都可以。从法律和财务角度来看,任何其他行为都是愚蠢和危险的。你被警告了!:)
修改演示实例的密码
对于刚安装的FreeSWITCH,首先要做的是修改演示用户的缺省密码(在本书的第四章和后续内容中,会解释用户、密码和其它相关概念)。编辑文件/usr/local/freeswitch/conf/vars.xml:
把“1234”改成其它值。如果你选择一个简单或中等强度的密码,那么你将在20分钟空被黑。如果你不使用PSTN网关,这或许不是问题,财务上被盗打的可能比较小,但如果有人使用您的服务器发起某种流量(比如恐怖分子的SIP呼叫),请考虑你的法律风险。然后,在接下来的三年里,慢慢地向联邦调查局解释这一切。别着急,他们有的是时间。因此,选择一个健壮的随机字符串很重要。如果拿不准主意,安装并使用uuidgen,它会帮你生成良好的密码。在Debian的root命令行中执行:
因此,选择一个鲁棒长度的随机字符串。值得怀疑的是,安装和使用uuidgen,它是非常好的密码。在Debian中,从根命令行:
apt-get install uuid-runtime
然后执行uuidgen:
uuidgen
a6333e94-0608-4abf-ba82-b0f0f13ef986
这是一个强度良好的密码,不是吗?无论如何,你不需要记住它,你仅需要把它剪切下来将粘贴一下:
然后保存文件并重启FreeSWITCH (这里修改的是一个预处理变量,必须重启FreeSWITCH才能使之生效)。
从fs_cli或FS控制台,执行命令:
fsctl shutdown
并且像往常一样,重新启动FreeSWITCH。
在台式机上配置Linphone
Linphone是一个很棒的SIP应用程序,完全跨平台(支持Windows、OSX、Linux、Android、iOS),有数百万安装和深度测试,是开源的,由法国公司Belledonne的友好人士开发和提供商业支持。
演示配置里提供了20个连续的用户帐号配置:1000-1019。它们的密码就是我们刚才在vars.xml中编辑的那一个:a6333e94-0608-4abf-ba82-b0f0f13ef986。在Linphone上配置SIP账号,需要FreeSWITCH的服务地址,我这里用的是192.168.1.111。请注意,我们将在同一个局域网内运行FreeSWITCH和SIP终端,我们会在所有所涉及到的机器上开启防火墙。稍后您将学习如何处理更复杂的拓扑
在Linphone上创建一个SIP帐号(Menu -> Options -> Preferences -> Manage SIP Accounts),用户必须在1000到1019间选择一个,这里就选1010吧(注意,在SIP identity和SIP Proxy Address选项中,必须加上sip:前缀):
上面这个是Windows的示例,如果是其它平台,配置界面可能会有些许不同。当您单击OK时,会弹出另一个对话框将询问您的密码。准备好,在超时之前把SIP帐号密码剪切并粘贴到对话框中。如果超时了,重新编辑SIP账号,保存它,它将会再次要求你输入密码。
如果一切顺利,Linphone 将注册到FreeSWITCH ,并准备好拨打和接听电话。
配置SNOM SIP话机
当一台 SNOM (或其它品牌)的SIP话机开机后,一般会显示它获取到的IP地址。可以使用浏览器配置SIP账号(SNOM 里的"Identity")
点击页面底部的"Apply"。现在,切换到“RTP”tab页,并关掉RTP encryption开关(后续我们会讨论加密话题),然后点击“Apply”。
如果一切顺利,SNOM话机现在已经注册到FreeSWITCH上了。最后,当UI询问是否保存时,请不要忘记选择保存,以持久化配置SNOM,否则,一旦话机重启,你将不得不重新配置一次。
配置Android版Linphone
通过触摸菜单或"Assistant"创建一个新账号。填写所有必须的字段内容:
"Proxy"字段将会自动填充。接着,点选"Password"字段并输入密码(我是把密码写到一个文件并传送到智能手机上,然后拷贝粘贴的)。
点OK
如果一切顺利,安卓版Linphone 已经注册到FreeSWITCH上了,会随时听从你的命令。
现在…演示有趣,有趣,有趣的拨号方案
演示拨号方案的主文件是/usr/local/freeswitch/conf/dialplan/default.xml。它的排版是阅读变得有趣。显然,如果你是第一次接触FreeSWITCH,您将无法理解其中的大部分内容,但是,里面的直白注释会让你弄明白其中的许多内容的。
9386, 有趣的提示
用文本编辑器打开拨号方案主文件,查找“9386”
你会在文件末尾找到它。它的"condition"是精确匹配"destination_number"属性,值为"9386",没有前缀,没有后缀(插入符是正则开始,美元符是结束)。如果呼叫的destination_number(它是一个主叫配置变量,所以我们可以在condition的"field"中直接引用它,而不需要使用${}语法)是9386,那么FreeSWITCH将应答这路呼叫(摘机并开始交换媒体),然后休眠1.5秒,然后,向呼叫者播放一个名为"phrase:funny_prompts"的实体(我们将在后面了解到,"phrase"定义了一个命名的音频文件集)。如果所有文件播放完毕,主叫并没有挂机,那么FreeSWITCH将会挂断通话。(顺便提一下截图中的最后一行,它表示子目录"default"下的所有XML文件将会被读取并添加到主拨号方案中,这是一种方便的层级组织方式)。
现在,是尝尝鲜的时候了,用注册的话机向FreeSWITCH拨打9386试试,你会听到一系列有趣的提示音。
1000...1019内部分机通话
下一个自然步骤就是用一部话机呼叫另一部,即内部用户间的呼叫。处理这类呼叫的"extension"是非常复杂的,因为它涉及许多 功能特性。
用文本编辑器打开拨号方案的主文件/usr/local/freeswitch/conf/dialplan/default.xml,并搜索"Local_Extension"。
这里我们不会逐行解释这个extension,因为 对于本书的这一部分来说,它实在是太复杂,太高级了。但我们需要重点看一下condition的写法。"expression"字段的正则表达式,匹配"destination_number"属性值为1000到1019,和我们所知的的示例用户范围完全相同。因此,如果用一部话机呼叫另一部,入局的call leg(A leg,描述话机侧发起的这一路呼叫)抵达FreeSWITCH时,在拨号方案中,将会匹配到这个extension,这个extension的内部机制将检查被叫是否注册到FreeSWITCH,如果注册了,那么FreeSWITCH就会发起一个新的call leg (即 B leg)来呼叫被叫的话机。
如果被叫应答,FreeSWITCH将两个call leg桥接在一起,并在双向间交换媒体流数据包。如果被叫没有应答,或者他的话机压根就没注册,那么FreeSWITCH会把入局的呼叫(A leg)引导到被叫的语音信箱中(这时不会发起新的leg,语音信箱是FreeSWITCH的模块,不涉及其它外部实体)。
现在,你已经了解了大体情节,可以自己测试各种不同的场景了:呼叫一部话机,让它接听、拒接;呼叫一个错误的号码;呼叫没有注册的号码;呼叫没有配置终端话机的号码。祝你玩得开心。
5000,接入演示 IVR
IVR,交互式语音应答,自助服务,私人服务,语音菜单,语音树,是过去几十年,这个奇怪的社会让我们所有人都非常熟悉的事情之一。从呼叫中心到语音邮件系统,从叫醒服务到机场信息系统,我们已经习惯于通过拨号板上的按键与合成语音间的交互。
现在,用一部话机呼叫5000,你将会与一个简单但完成的IVR互动,它有许多选项、菜单和子菜单。演示IVR的一些跳转选项,会转接到演示配置的其它extension去。比如,如果你选择3,会被转接到extension “9664”听一段MOH;如果选择“2”,会转到extension“9196”,它类似一个回音壁,会把你说的话原封不动地回传回来(在评估网络时延时,这个小功能非常给力)。
本书的后续章节,我们介介绍更多构建IVR的内容,并解释演示IVR示例是如何组织的。现在你先玩玩就可以了。
3000,会议
如果你用不同的话机同时呼叫3000,他们都会被连接到同一个“会议室”中。我们没有限制同一个会议室可以容纳多少人,你也可以同时并行开启多个会议室。同一会议室的成员间可以互相听到彼此的声音,但不能听到别的会议室的声音。此外,会议室还有很多特性,比如主持人、密码验证等等。在我们演示实例的会议中,你可以在拨号板上按几个键试式,看有什么事情发生。本书后面会介绍更多会议相关的内容。
演示拨号方案快速索引
有关extension 号码及其功能,请参考下表:
Extension |
功能 |
1000 - 1019 |
本地分机 |
** +分机号 |
拦截响铃中的电话(呼叫代答) |
2000 |
呼叫组实例:销售组 |
2001 |
呼叫组实例:支持组 |
2002 |
呼叫组实例:账单组 |
3000 - 3399 |
会议室实例 |
4000 或 *98 |
提取语音留言 |
5000 |
IVR演示实例 |
5900 |
FIFO队列停泊 |
5901 |
FIFO队列拾回 |
6000 |
Valet park/retrieval, manual |
6001-6099 |
Valet park/retrieval, automatic |
7243 |
RTP广播寻呼 |
0911 |
Group intercom example #1 |
0912 |
Group intercom example #2 |
0913 |
Emergency outbound conference example |
9178 |
接收传真 |
9179 |
发送传真 |
9180 |
铃音测试,远端产生回铃音 |
9181 |
铃音测试,发送英国制式回铃音 |
9182 |
铃音测试,发送音乐彩铃 |
9183 |
摘机,然后发送英国制式回铃音 |
9184 |
摘机,然后播放音乐 |
Extension |
功能 |
9191 |
ClueCon 登记 |
9192 |
信息转储 |
9195 |
延迟回声测试 |
9196 |
回声测试 |
9197 |
Milliwatt tone (test signal quality) |
9198 |
Tetris |
9664 |
音乐保持音MOH |
总结
这章我们介绍了FreeSWITCH的缺省配置文件。主要包括这些主题:
- 在呼叫过程中的重要概念
- 基础fs_cli使用知识,介绍FreeSWITCH接口工具的用法
- 如何用预配置帐号配置SIP设备连接 FreeSWITCH
- 拨打一些不同的extension测试缺省的拨号方案
现在,我们将目光转向FreeSWITCH的另一个重要方面:用户目录。下一章,我们将详细介绍FreeSWITCH用户目录。
第三章 测试驱动演示配置相关推荐
- 物联网技术概论 第三章测试答案 桂小林 西安交通大学 2021智慧树
第三章测试 全套答案均有收录,可以在我的主页查看 1.[单选题](2分) 下列不属于按传感器的工作原理进行分类的传感器是 A.压电式传感器 B.化学型传感器 C.热电式传感器 D.应变式传感器 参考答 ...
- Linux设备驱动——第三章字符驱动
当对幸福的憧憬过于急切,那痛苦就在人的心灵深处升起.--加缪 本章的目的是编写一个完整的字符设备驱动.我们开发一个字符驱动是因为这一类适合大部分简单的硬件设备.字符驱动也比块驱动易于理解.本章的最终目 ...
- 第三章 BIRT数据源的配置
转载自:https://blog.csdn.net/z1012890225/article/details/37815947 选择数据资源管理器(Data Explorer).如果使用缺省报表设计透视 ...
- 第三章 最小化SpringXml 配置
自动装配(autowiring):有助于减少甚至消除<property>元素和<constructor-arg>元素,让spring自动识别如何装配Bean的依赖关系. 自动检 ...
- [Django学习]第三章 视图和url配置
2019独角兽企业重金招聘Python工程师标准>>> 在上一章使用django-admin.py startproject tests制作的项目中的tests文件夹里,创建一个vi ...
- 连接网络-第三章测试
哪种协议可以让 ISP 通过 DSL 网络发送 PPP 帧? 选择一项: PPPoE CHAP ADSL LTE 反馈 Refer to curriculum topic: 3.2.1 为了让想通过 ...
- 【STM32CubeMx你不知道的那些事】第三章:STM32CubeMx串口配置(中断接收)
在嵌入式环境中,串口通信是必不可少的通信方式,这一章我们主要是讲解一下HAL库怎么应用串口外设做收发功能. 一.准备工作 1.使用我们第一章配置好工程文件.如图 2.明确原理图上面所需要的串口,这里我 ...
- 中国大学MOOC 人工智能导论第三章测试
1 单选(2.5分) 以下关于正向推理的说法正确的是 得分/总分 A. 正向推理以某个假设目标作为出发点 B. "如果P->Q为真,但Q不成立,则P也不成立"是假言推理 C. ...
- 计算机基础知识第三章测试,计计算机应用基础第三章测试题
22.Word2000提供了哪几种视图方式? 23.Word的段落对齐方式有哪几种? 24.在Word中的创建表格有哪些方法? 三.应用题(每小题10分,共2题,计20分) 25.对以下素材按要求排版 ...
最新文章
- “学在清华”清华大学本科教育主题展在校史馆开展
- 级联下拉框效果,动态加载图片
- Android PopupWindow 隐藏软键盘的方法
- 2009年岁末年总结
- c语言实参和形参占用存储单元_必须知道的C语言知识细节:函数形参和实参的区别...
- Codeforces Round 546 (Div. 2)
- 分区表理论解析(下):SQL Server 2k52k8系列(二)
- easyswoole数据库连接池_Swoole Redis 连接池的实现
- Adobe Premiere Rush最新升级 终于支持M1芯片了
- 完美世界年营收85亿:同比降17% 影视业务整体产生亏损2亿
- 台式电脑添加共享计算机,台式电脑怎么设置wifi共享
- 计算机在段前加项目符号,word中给段落添加项目符号的方法
- HTML中Table去掉两边的边框
- 如何查看电脑有几个内存条插槽
- Java,php,运维工程师转型大数据开发怎么样?你属于哪一类?
- 毕马威《2021年中国证券业调查报告》:金融科技和数字化将成为发展核心
- leetcode每日一题—781.森林中的兔子
- 电脑强制关机会有什么影响
- 关于色光三原色与颜料三原色
- 如何让区块链获得人工智能的能力
热门文章
- 数字集成电路设计(一、Verilog HDL数字集成电路设计方法概述)
- QT+ObjectARX 2022
- MOOC数据结构(下)(自主模式)-平均气温(Temperature)
- android平板 跑分软件,新人看过来 安卓平板装机必备软件推荐
- windows arm linux,Windows服务器搭载ARM,人生大赢家不是微软而是Linux
- 关于自然常数e的来源与应用(超初级,也超恐怖)
- 计算机考研有哪些值得推荐的院校?能否具体讲讲?
- Java算法罗马数字转整数
- 电脑垃圾清理 -windows电脑裸奔必知技巧
- 分享一份技术书籍《Java 8 》PDF版,可自行下载