赞
踩
FreeSwtich默认的配置体系是XML文件,修改配置后需要reloadxml生效。这对于大型线上系统,是不可接受的。FreeSwitch本身提供了几种不同的动态配置接口,比如mod_xml_curl,本文介绍利用mod_lua动态配置FS的方法。
通过mod_lua模块,你可以利用lua实现动态配置。绑定一个脚本处理XML请求,就像mod_xml_curl那样,动态地把所需要的XML片段喂给FS,指示FS的执行。实现应用与数据的分离。FreeSWITCH需要某种XML信息时,它查询注册的钩子,调用指定的脚本。在脚本中,你可以为所欲为,只是不要忘记返回XML就行了。
FreeSwitch启动时会加载conf/autoload_configs/lua.conf.xml配置。
以下是一个极简配置实例:
- <configuration name="lua.conf" description="LUA Configuration">
- <settings>
- <param name="xml-handler-script" value="dp.lua"/>
- <param name="xml-handler-bindings" value="dialplan"/>
- </settings>
- </configuration>
编辑lua.conf.xml之后,FreeSWITCH控制台命令reloadxml不能识别 "xml-handler-script" 参数,你必须重启FS才会生效 FreeSWITCH.
对于"xml-handler-bindings"参数,可配置值有:"dialplan" "directory" "configuration" "dialplan|directory|configuration"
在Lua脚本中,可以访问XML_REQUEST对象获取必要的信息。比如:
freeswitch.consoleLog("notice", "SECTION " .. XML_REQUEST["section"] .. "\n")
如果mod_lua加载时有如下配置:
- <configuration name="lua.conf" description="LUA Configuration">
- <settings>
- <param name="xml-handler-script" value="configuration.lua"/>
- <param name="xml-handler-bindings" value="configuration"/>
- </settings>
- </configuration>
那么之后加载的模块,可以把mod_lua当成配置服务器,需要配置信息时,调用绑定的lua实时查询。
查询模块配置的lua脚本中,隐含一个XML_REQUEST对象,其典型的属性值:
'params' event object | ||
---|---|---|
acl.conf | no | N/A |
event_socket.conf | no | N/A |
post_load_switch.conf | no | N/A |
sofia.conf | yes | |
switch.conf | no | N/A |
syslog.conf | no | N/A |
在启动初始化过程中,会读取profile配置,为网关和别名域读取目录信息。
在模块加载时,Lua脚本中的XML_REQUEST对象的属性值:
此外,"params" 携带一个event 对象。
对sofia中的每个profile,directory都会读取一次。The directory is read once for each profile in the sofia configuration
注意上面的变量值有“空字符串”,不是nil
对于External profile:
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2014%3A04%3A40
- Event-Date-GMT: Fri,%2006%20Aug%202010%2018%3A04%3A40%20GMT
- Event-Date-Timestamp: 1281117880813532
- Event-Calling-File: sofia.c
- Event-Calling-Function: config_sofia
- Event-Calling-Line-Number: 3481
- purpose: gateways
- profile: external
重要字段:
|
对于 Internal profile
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2014%3A04%3A41
- Event-Date-GMT: Fri,%2006%20Aug%202010%2018%3A04%3A41%20GMT
- Event-Date-Timestamp: 1281117881174514
- Event-Calling-File: sofia.c
- Event-Calling-Function: config_sofia
- Event-Calling-Line-Number: 3481
- purpose: gateways
- profile: internal
重要字段:
|
启动初始化过程中,还会从directory中读取网络列表,但这时的XML_REQUEST属性值有些差异:
Event 报文
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2014%3A04%3A43
- Event-Date-GMT: Fri,%2006%20Aug%202010%2018%3A04%3A43%20GMT
- Event-Date-Timestamp: 1281117883173795
- Event-Calling-File: sofia_reg.c
- Event-Calling-Function: sofia_reg_parse_auth
- Event-Calling-Line-Number: 1797
- action: sip_auth
- sip_profile: internal
- sip_user_agent: IP-Phone-V3.2.49T5.13%20-%20G729
- sip_auth_username: 1000
- sip_auth_realm: 192.168.1.11
- sip_auth_nonce: <auth_nonce_uuid>
- sip_auth_uri: sip%3A192.168.1.11
- sip_contact_user: 1000
- sip_contact_host: 192.168.88.202
- sip_to_user: 1000
- sip_to_host: 192.168.1.11
- sip_to_port: 5060
- sip_from_user: 1000
- sip_from_host: 192.168.1.11
- sip_from_port: 5060
- sip_request_host: 192.168.1.11
- sip_auth_qop: auth
- sip_auth_cnonce: 829326
- sip_auth_nc: 00000001
- sip_auth_response: <auth_response - md5sum?>
- sip_auth_method: REGISTER
- key: id
- user: 1000
- domain: 192.168.1.11
- ip: 192.168.88.202
重要字段:
|
FreeSWITCH以特定域标签查找用户,这时XML_REQUEST对象的属性值:
and 'params' will have an event object
Event 报文:
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2014%3A04%3A43
- Event-Date-GMT: Fri,%2006%20Aug%202010%2018%3A04%3A43%20GMT
- Event-Date-Timestamp: 1281117883173795
- Event-Calling-File: sofia_reg.c
- Event-Calling-Function: sofia_reg_parse_auth
- Event-Calling-Line-Number: 1797
- action: sip_auth
- sip_profile: internal
- sip_user_agent: IP-Phone-V3.2.49T5.13%20-%20G729
- sip_auth_username: 1000
- sip_auth_realm: 192.168.1.11
- sip_auth_nonce: <auth_nonce_uuid>
- sip_auth_uri: sip%3A192.168.1.11
- sip_contact_user: 1000
- sip_contact_host: 192.168.88.202
- sip_to_user: 1000
- sip_to_host: 192.168.1.11
- sip_to_port: 5060
- sip_from_user: 1000
- sip_from_host: 192.168.1.11
- sip_from_port: 5060
- sip_request_host: 192.168.1.11
- sip_auth_qop: auth
- sip_auth_cnonce: 829326
- sip_auth_nc: 00000001
- sip_auth_response: <auth_response - md5sum?>
- sip_auth_method: REGISTER
- key: id
- user: 1000
- domain: 192.168.1.11
- ip: 192.168.88.202
重要字段:
|
Event 报文
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2016%3A28%3A08
- Event-Date-GMT: Fri,%2006%20Aug%202010%2020%3A28%3A08%20GMT
- Event-Date-Timestamp: 1281126488274011
- Event-Calling-File: sofia_reg.c
- Event-Calling-Function: sofia_reg_parse_auth
- Event-Calling-Line-Number: 1797
- action: sip_auth
- sip_profile: internal
- sip_user_agent: IP-Phone-V3.2.49T5.13%20-%20G729
- sip_auth_username: 1001
- sip_auth_realm: 192.168.1.11
- sip_auth_nonce: 1fe3d1fa-a199-11df-b392-b105e374638e
- sip_auth_uri: sip%3A1000%40192.168.1.11
- sip_contact_user: 1001
- sip_contact_host: 192.168.88.99
- sip_to_user: 1000
- sip_to_host: 192.168.1.11
- sip_to_port: 5060
- sip_from_user: 1001
- sip_from_host: 192.168.1.11
- sip_from_port: 5060
- sip_request_user: 1000
- sip_request_host: 192.168.1.11
- sip_auth_qop: auth
- sip_auth_cnonce: 10560d0
- sip_auth_nc: 00000001
- sip_auth_response: b99d1213022480a2b6c4e14432661821
- sip_auth_method: INVITE
- key: id
- user: 1001
- domain: 192.168.1.11
- ip: 192.168.88.99
重要字段:
|
Event 报文
- Event-Name: REQUEST_PARAMS
- Core-UUID: <uuid>
- FreeSWITCH-Hostname: hostname
- FreeSWITCH-IPv4: 192.168.1.11
- FreeSWITCH-IPv6: %3A%3A1
- Event-Date-Local: 2010-08-06%2016%3A28%3A09
- Event-Date-GMT: Fri,%2006%20Aug%202010%2020%3A28%3A09%20GMT
- Event-Date-Timestamp: 1281126489462522
- Event-Calling-File: mod_dptools.c
- Event-Calling-Function: user_outgoing_channel
- Event-Calling-Line-Number: 2662
- as_channel: true
- action: user_call
- key: id
- user: 1000
- domain: 192.168.1.11
重要字段:
|
- <configuration name="lua.conf" description="LUA Configuration">
- <settings>
- <param name="xml-handler-script" value="dp.lua"/>
- <param name="xml-handler-bindings" value="dialplan"/>
- </settings>
- </configuration>
Lua 脚本 dp.lua示例
- -- params is the event passed into us we can use params:getHeader to grab things we want.
- io.write("TEST\n" .. params:serialize("xml") .. "\n");
-
- mydialplan = [[
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <document type="freeswitch/xml">
- <section name="dialplan" description="LUA Dial Plan For FreeSwitch">
- <context name="default">
- <extension name="lua_dp_ext">
- <condition field="destination_number" expression="^10086$">
- <action application="sleep" data="1000 "/>
- <action application="answer"/>
- <action application="playback" data="ivr/8000/ivr-welcome_to_freeswitch.wav"/>
- </condition>
- </extension>
- </context>
- </section>
- </document>
- ]]
-
- XML_STRING = mydialplan
- -- comment the following line for production:
- freeswitch.consoleLog("notice", "Debug XML:\n" .. XML_STRING .. "\n")
同一功能的另一个版本:
- -- LUA dialplan
-
- DIALPLAN = {}
- freeswitch.consoleLog("notice", "SECTION " .. XML_REQUEST["section"] .. "\n")
-
- table.insert(DIALPLAN, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]])
- table.insert(DIALPLAN, [[<document type="freeswitch/xml">]])
- table.insert(DIALPLAN, [[ <section name="dialplan" description="LUA Dial Plan For FreeSwitch">]])
- table.insert(DIALPLAN, [[ <context name="default">]])
- table.insert(DIALPLAN, [[ <extension name="lua_dp_ext">o]])
- table.insert(DIALPLAN, [[ <condition field="destination_number" expression="^10086$">]])
- table.insert(DIALPLAN, [[ <action application="sleep" data="1000 "/>]])
- table.insert(DIALPLAN, [[ <action application="answer"/>]])
- table.insert(DIALPLAN, [[ <action application="playback" data="ivr/8000/ivr-welcome_to_freeswitch.wav"/>]])
- table.insert(DIALPLAN, [[ </condition>]])
- table.insert(DIALPLAN, [[ </extension>]])
- table.insert(DIALPLAN, [[ </context>]])
- table.insert(DIALPLAN, [[ </section>]])
- table.insert(DIALPLAN, [[</document>]])
-
- XML_STRING = table.concat(DIALPLAN, "\n")
-
- mydialplan = [[
-
- <document type="freeswitch/xml">
- <section name="dialplan" description="LUA Dial Plan For FreeSwitch">
- <context name="default">
- <extension name="lua_dp_ext">
- <condition field="destination_number" expression="^10086$">
- <action application="sleep" data="1000 "/>
- <action application="answer"/>
- <action application="playback" data="ivr/8000/ivr-welcome_to_freeswitch.wav"/>
- </condition>
- </extension>
- </context>
- </section>
- </document>
- ]]
-
-
- -- comment the following line for production:
- freeswitch.consoleLog("notice", "Debug XML:\n" .. XML_STRING .. "\n")
上述实例,展示了lua是怎样生成XML片段并喂给FS执行的。但是拼接XML的过程显得有些繁琐。有没有办法简单一点呢?Dialplan的描述本质上无非就是一组的Action加上参数而已。
lua_dialplan_hunt的实现中,允许使用ACTIONS表来传递这些信息,换句话说,在脚本里,构建一个ACTIONS table并传回给FS就可以了。那么我们需要怎样做呢?
编辑sip profile配置文件,比如说freeswitch/sip_profiles/internal.xml,修改以下两个属性:
- <param name="context" value="luadp.lua"/>
- <param name="dialplan" value="LUA"/>
修改用户的context属性为“luadp.lua”,比如说freeswitch/directory/default/1000.xml:
<variable name="user_context" value="luadp.lua"/>
在脚本目录下,添加一个名为luadp.lua的脚本,内容如下:
- -- LUA dialplan
-
- ACTIONS = {}
- freeswitch.consoleLog("notice", "from your script")
-
- table.insert(ACTIONS, {"sleep", "1000"})
- table.insert(ACTIONS, "answer")
- table.insert(ACTIONS, {"playback", "ivr/8000/ivr-welcome_to_freeswitch.wav"})
- table.insert(ACTIONS, {"log", "NOTICE after your script"})
这个实例是前面dialplan的第三个版本,脚本逻辑是不是简单得多了。
|
|
如果LUA 收到一个dialplan查询请求,但没有相应处理逻辑,那么应当返回 "not found" 结果(如下所示),不能返回空串:
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <document type="freeswitch/xml">
- <section name="result">
- <result status="not found" />
- </section>
- </document>
如果返回一个空串,FS将处理报错:
|
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。