前几天有网友问黑名单怎么做,我说自己写个Lua脚本查数据库吧。后来又查了一下,FreeSWITCH竟然有一个mod_blacklist
,这不就是黑名单嘛。
说实话我以前从来没注意过这个模块。遇到一个新模块怎么办呢?当然是查FreeSWITCH的Wiki。那如果Wiki上也没有呢?Wiki上一般都会有,如果没有的话,也不怕,下面,我就带大家在不看Wiki的情况下如何了解一个模块。
当然,这个模块比较简单。首先,这个模块默认是不编译的,要手动编译
$ cd src/mod/applications/mod_blacklist
$ make install
然后,就可以在FreeSWITCH里加载模块了:
freeswitch> load mod_blacklist
显示日志如下:
2016-04-28 09:12:29.508192 [CONSOLE] switch_loadable_module.c:1538 Successfully Loaded mod_blacklist]
2016-04-28 09:12:29.508192 [NOTICE] switch_loadable_module.c:338 Adding API Function 'blacklist'
从日志中可以看出,该模块好像仅实现了一个API: blacklist
直接输入这个命令试下
freeswitch@seven.local> blacklist
2016-04-28 16:53:23.913138 [ERR] mod_blacklist.c:182 Invalid usage
出错啦,继续试:
freeswitch@seven.local> blacklist test
-ERR: No such command: test (see 'blacklist help')
有门,继续:
freeswitch@seven.local> blacklist help
blacklist check <listname> <item>
blacklist add <listname> <item>
blacklist del <listname> <item>
blacklist save <listname>
blacklist reload
blacklist help
+OK
从命令行中看,它好像支持多个列表(listname),每个列表中都有相关的条目(item
)。看配置文件,blacklist.conf.xml
里有这么一行:
list name="example" filename="$${conf_dir}/blacklists/example.list"/> <
创建
/usr/local/freeswitch/conf/blacklists/example.list
里面的内容怎么写呢?不知道,蒙一把,输入
1000
1001
就是把电话号码每个一行。至于蒙的对不对,实际上可以看源代码的。在源代码中,有一个load_list()
函数,看样子是用于加载这个列表的,主要内容如下:
while (fgets(buf, 1024, f)) {
(buf);
trim(bl->list, buf, (void *)SWITCH_TRUE);
switch_core_hash_insert}
很明显,它加从文件中依次读取每一行,然后插入一个内容哈希表中。看样子我们蒙的还比较靠谱。
重新加载一下模块:
freeswitch@seven.local> reload mod_blacklist
2016-04-28 15:09:18.868148 [INFO] mod_blacklist.c:104 Loaded list [example]
2016-04-28 15:09:18.868148 [CONSOLE] switch_loadable_module.c:1538 Successfully Loaded mod_blacklist]
哈哈,Loaded list [example] 显示名为 example 的列表已经加载了。试试检查(check)命令
freeswitch@seven.local> blacklist check example 1000
true
freeswitch@seven.local> blacklist check example 1001
true
freeswitch@seven.local> blacklist check example 1002
false
由于1002
不在列表中,返回了false
。
看看能不能手工加
freeswitch@seven.local> blacklist add example 1002
+OK
2016-04-28 16:54:02.593169 [INFO] mod_blacklist.c:228 Added [1002] to list [example]
freeswitch@seven.local> blacklist check example 1002
true
这次是true
了。试试save
命令:
freeswitch@seven.local> blacklist save example
2016-04-28 16:54:17.973176 [INFO] mod_blacklist.c:280 Saving example to /usr/local/freeswitch/conf/blacklists/example.list
+OK
$ cat /usr/local/freeswitch/conf/blacklists/example.list
1000
1002
1001
可以看到1002
已经加到列表里了。但由于内部实现是哈希表,没有排序,因次并没有特定的次序。
好了,但在实际打电话时怎么用呢?
创建如下Dialplan,这个例子来自FreeSWITCH的Wiki
extension name="blacklist_check">
<condition field="${blacklist(check example ${destination_number})}" expression="^true$">
<action application="bridge" data="sofia/external/sip:lenny@sip.itslenny.com:5060"/>
<condition>
</extension> </
上面的意思是说,测试条件是一个动态条件,该动态条件是由blacklist check listname item
完成的。上面的例子测试了被叫号码(destination_number
)是否在黑名单,若否则继续呼。
我们再来个稍复杂点的例子:
extension name="echo">
<condition field="destination_number" expression="^9196$">
<condition field="${blacklist(check example ${caller_id_number})}" expression=“^true$">
<<action application="answer"/>
<action application="echo"/>
condition>
</condition>
</</extension>
其实很简单,我们只不过是在默认的9196
基础上增加了一层blacklist
的判断。如果主叫号码是一个不在名单中的号码,则匹配失败,呼叫失败,打印日志如下:
Dialplan: sofia/internal/1004@192.168.7.6 Regex (PASS) [echo] destination_number(9196) =~ /^9196$/ break=on-false
|--- Dialplan: Processing recursive conditions level:1 [echo_recur_1] require-nested=TRUE
|--- Dialplan: sofia/internal/1004@192.168.7.6 Regex (FAIL) [echo_recur_1] ${blacklist(check example ${caller_id_number})}(false) =~ /^true$/ break=on-false
如果是在名单中的号码,则呼叫成功,日志显示如下:
Dialplan: sofia/internal/1000@192.168.7.6 Regex (PASS) [echo] destination_number(9196) =~ /^9196$/ break=on-false
|--- Dialplan: Processing recursive conditions level:1 [echo_recur_1] require-nested=TRUE
|--- Dialplan: sofia/internal/1000@192.168.7.6 Regex (PASS) [echo_recur_1] ${blacklist(check example ${caller_id_number})}(true) =~ /^true$/ break=on-false
|--- Dialplan: sofia/internal/1000@192.168.7.6 Action answer()
|--- Dialplan: sofia/internal/1000@192.168.7.6 Action echo()
读到这里,细心的读者可能会问:你上面说错了吧?明明上面的逻辑是白名单……,呵呵,是的,天使跟恶魔只是一念之差,你也可以用黑名单来做白名单
;)。当然,如果你确实需要黑名单,试试把上面的true
改成false
就行了,这个,留给读者自己练习吧?