由于在网上不难找到实用的安装教程,在这里先跳过 FreeSWITCH 的安装介绍。有需要的话可以下载附件里的《FreeSWITCH 权威指南》样章,里面有比较详细的安装教程。
本章将对 FreeSWITCH 的框架进行简单介绍,让大家对 FreeSWITCH 有一个简单的了解。
内容确实枯燥、抽象了一点,心急的读者不妨先阅读第三章《启动 FreeSWITCH》,来试一试用 FreeSWITCH 打电话的功能。
总体架构
FreeSWITCH 的核心短小精悍,绝大部分应用层的功能都在外围的模块中实现。在实际应用中,可以动态加载、卸载外围模块。外围模块通过核心提供的 Public API 与核心进行通信,而核心则通过回调(钩子)机制执行外围模块中的代码。
目录结构
在类 Unix 系统上,FreeSWITCH 默认的安装目录是 /usr/local/freeswitch,在 Windows 上默认是 C:\Programming Files\FreeSWITCH。但 FreeSWITCH 的目录结构还是大致相同的。
目录 | 说明 |
bin | 可执行程序目录 |
db | 系统数据库(SQLite)目录,将呼叫信息存放到数据库中,查询时无须对核心数据结构加锁 |
htdocs | Http Server 根目录 |
lib | 库文件目录 |
mod | 可加载模块目录 |
run | 运行目录,存放 FreeSWITCH 运行时的 PID |
sounds | 声音文件目录,使用 playback() 时默认寻找此目录 |
grammar | 语法目录,用于 ASR(语音识别) |
include | 头文件目录 |
log | 日志文件目录,CDR(Call Detail Record)等 |
recordings | 录音文件目录,使用 record() 时默认的存放路径 |
scripts | 嵌入式语言脚本目录,如使用 lua()、luarun()、jsrun() 等默认的寻找路径 |
storage | 语音留言(Voicemail)的录音文件目录 |
conf | 配置文件目录 |
配置文件
配置文件(位于 /conf 目录下)由许多 XML 文件组成。在 FreeSWITCH 装载时,XML 解析器会将所有 XML 文件组织在一起装入内存,组成一个 XML 大文档,称为 XML 注册表。FreeSWITCH 还允许在某些 XML 节点上安装回调函数,当节点的数据变化时(如 reloadxml 时),FreeSWITCH 便自动调用这些回调函数,以更新 FreeSWITCH 的内部数据或状态等。
先来看看配置文件的目录结构吧。
├── freeswitch.xml | 主配置文件,它会使用 include 语句装入其他文件 |
├── vars.xml | 全局变量文件,定义了 FreeSWITCH 中常用的变量 |
├── autoload_configs | 自动装载配置目录,存放了外围模块的配置文件 |
│ ├──modules.conf.xml | 模块装载配置文件,指定了 FreeSWITCH 启动时自动装载哪些模块 |
│ ├──*.xml | 一般来说每个模块都有一个配置文件 |
├── chatplan | 聊天计划配置目录 |
├── dialplan | 拨号计划配置目录 |
│ ├── default.xml | 默认拨号计划配置文件,一般用于内部用户路由 |
│ ├── public.xml | 默认拨号计划配置文件,一般用于外部来话路由 |
├── directory | 用户配置目录 |
│ └── default | 默认的用户配置目录 |
│ ├── *.xml | SIP 用户,每个用户一个文件 |
├── ivr_menus | IVR 菜单配置目录 |
├── jingle_profiles | 连接 Google Talk 的相关配置目录 |
├── lang | 多语言支持文件目录 |
│ ├── en | 英语 |
│ └── fr | 法语 |
├── mrcp_profiles | MRCP 的相关配置目录,用于跟第三方语音合成和语音识别系统对接 |
├── sip_profiles | SIP 配置目录 |
│ ├── internal.xml | 一个 SIP profile,或称作一个 SIP-UA,监听在本地 IP 及端口 5060, 一般供内网用户使用 |
│ ├── externa.xml | 另一个 SIP-UA,用作外部连接,监听端口 5080 |
└── skinny_profiles | 思科 SCCP 协议话机的配置文件 |
freeswitch.xml
freeswitch.xml 是所有 XML 文件的黏合剂。
<?xml version="1.0"?>
<document type="freeswitch/xml">
<!-- #comment 这是一个配置文件,本行是注释 -->
<X-PRE-PROCESS cmd="include" data="vars.xml"/>
<section name="configuration" description="Various Configuration">
<X-PRE-PROCESS cmd="include" data="autoload_configs/*.xml"/>
</section>
</document>
freeswitch.xml 的根是 document,在 document 中有许多 section,每个 section 都对应一部分功能。通过 X-PRE-PROCESS 预处理指令,可以将 data 参数指定的文件内容包含(include)到当前文件中来。
需要注意的是,在 FreeSWITCH 进行预处理时,还没有到达 XML 解析阶段,也识别不了 XML 语法。因此在freeswitch.xml 中注释是无效的,甚至会引发错误。
vars.xml
vars.xml 主要通过 X-PRE-PROCESS 指令来定义一些全局变量。
<X-PRE-PROCESS cmd="set" data="domain=$${local_ip_v4}"/>
vars.xml 中设置的变量,在 FreeSWITCH 运行期间是永久有效的,称为全局变量。而局部变量(临时变量)常常出现在拨号计划中,只在一个呼叫的生命周期中有效。全局变量以 $${var} 表示,临时变量以 ${var} 表示。
在加载 vars.xml 之前,FreeSWITCH 中就已经隐含地计算并设置了一些全局变量。
变量 | 说明 |
hostname | 主机名 |
local_ip_v4 | 本地 IP(IPv4) |
local_mask_v4 | 本地掩码(IPv4) |
local_ip_v6 | 本地 IP(IPv6) |
switch_serial | 随机产生的序列号 |
base_dir | FreeSWITCH 的安装目录 |
recordings_dir | 录音文件存放目录,可以在启动时用 -recordings 参数指定 |
sound_prefix | 声音文件路径前缀,默认是 /usr/local/freeswitch/sounds/en/us/callie |
sounds_dir | 声音文件目录,默认是 /usr/local/freeswitch/sounds |
core_uuid | 自动生成的 uuid 字符串,用于标志本 FreeSWITCH 实例,每次启动都会改变 |
zrtp_enabled | 是否启用zrtp |
nat_public_addr | 检测到的 NAT 公网地址 |
nat_private_addr | NAT 私网地址 |
nat_type | NAT 类型 |
在 FreeSWITCH 中,可以使用 global_getvar 命令来查看这些变量的值。如果想要修改这些变量的值,可以在 vars.xml 文件中手动设置一下,覆盖掉原来的值。
autoload_configs 目录
autoload_configs 目录下的配置文件会在 FreeSWITCH 启动时装入。各模块的配置文件不尽相同,在此不一一介绍。
autoload_configs 目录下有一个特殊的 modules.conf.xml 文件,它决定了 FreeSWITCH 启动时自动加载哪些模块。与 freeswitch.xml 文件不同,modules.conf.xml 配置文件不用进行预处理,可以识别 XML 语法。需要的模块可以添加或者取消注释,不需要的模块可以注释或者直接删除。
此外 autoload_configs 目录下还有一个 post_load_modules.conf.xml 文件,其格式和用法与 modules.conf.xml 文件相似,不同的是在 post_load_modules.conf.xml 中定义的模块加载时间比较晚。
其它配置文件
dialplan 目录下的文件,定义了 XML 拨号计划(Dialplan)。拨号计划是 FreeSWITCH 中很重要的一部分,笔者会在后续的帖子中进行详细的介绍。
ivr_ menus 目录下存放了默认的 IVR(语音服务台)菜单的例子。
directory 目录下的配置文件决定了当 FreeSWITCH 作为注册服务器时的用户信息,其中的配置信息称为用户目录。
XML 用户目录
用户目录(/conf/directory 目录下)决定了哪些用户可以注册到 FreeSWITCH 上。虽然 SIP 并不要求一定要注册才可以打电话,但是通话前的用户认证参数仍然需要在用户目录中进行配置。
用户目录的配置文件默认放在 conf/directory/ 下,系统自带的配置文件为 default.xml。该配置文件决定了哪些用户能注册到 FreeSWITCH 中。
<include>
<domain name="$${domain}">
<params>
<param name="dial-string" value="{^^:sip_invite_domain=${dialed_domain}:presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(*/${dialed_user}@${dialed_domain})}"/>
</params>
<variables>
<variable name="record_stereo" value="true"/>
<variable name="default_gateway" value="$${default_provider}"/>
<variable name="default_areacode" value="$${default_areacode}"/>
<variable name="transfer_fallback_extension" value="operator"/>
</variables>
<groups>
<group name="default">
<users>
<X-PRE-PROCESS cmd="include" data="default/*.xml"/>
</users>
</group>
</groups>
</domain>
</include>
$${domain} 这个全局变量是在 vars.xml 中设置的,默认为主机的 IP 地址,可以修改为使用一个域名。
params 中定义了该 Domain 中所有用户的公共参数。在用户呼叫时 FreeSWITCH 会根据 username(以及 domain),找到对应的 dial-string,扩展成用户实际的 SIP 地址。
variables 则定义了一些公共变量,在用户主叫或被叫时,这些变量会绑定到相应的 Channel 上形成 Channel Variable。
group(组)中包含了很多用户。组名 default 没有什么特殊意义。在 users 标签中,通过预处理指令装入了 default 目录中的所有 XML 文件。组并不是必须要设置的,不打算使用组的话,也可以把 users 节点直接放在 domain 标签下。但通过使用组可以支持群呼、代接之类的业务。
<include>
<user id="somebody">
<params>
<param name="password" value="$${default_password}"/>
<param name="vm-password" value="somebody"/>
</params>
<variables>
<variable name="accountcode" value="somebody"/>
<variable name="user_context" value="default"/>
。。。。。。
</variables>
</user>
</include>
事实上,params 和 variables 可以出现在 user、group 和 domain。当它们重复的时候,优先级由高到低依次为 user、group、domain。