XSwitch进阶文档

XSwitch怎么编写xlonglive脚本

xlonglive万岁脚本,指的是一系列长期运行在XSwitch内部的lua脚本,你可以在脚本内订阅FreeSWITCH产生的事件,从而驱动你的脚本去做你想做的事情。

由于lua内没有类的概念,因此我们使用表与原表的形式,实现了一个假类,如:

---@class xlonglive
local xlonglive = {}
xlonglive.new = function(name)
	local self = {
		name = name,
		event_name = "xlonglive::" .. name,
	}

	setmetatable(self, { __index = xlonglive })
	return self
end

以上代码表示在其他脚本中调用xlonglive.new('test')时,会生成一个表,其中包含name,值为test;还包含event_name,值为xlonglive::test。并使用setmetatable设置表的元素。

示例

假设新建一个my_test.luaxlonglive脚本,内容如下:

  1 -- 获取lua一些环境信息
  2 local cur_dir = debug.getinfo(1).source;
  3 cur_dir = string.gsub(debug.getinfo(1).source, "^@(.+/)[^/]+$", "%1")
  4 if cur_dir:sub(1,1) == '/' then -- plain Lua
  5 package.path = package.path .. ";/etc/xtra/?.lua"
  6 package.path = package.path .. ";" .. cur_dir .. "?.lua"
  7 package.path = package.path .. ";" .. cur_dir .. "vendor/?.lua"
  8 end
  9 -- 获取XSwitch内部工具函数组件
 10 local utils = require 'utils'
 11 -- 和获取XSwitch config.lua内的配置组件
 12 local config = require 'xtra_config'
 13 -- 获取XSwitch连接数据库组件
 14 local xdb = require 'xdb'
 15
 16 -- 新建连接数据库实例
 17 local dbh = xdb.new()
 18 if config.db_auto_connect then dbh:connect(config.fifo_cdr_dsn or config.dsn) end
 19
 20 -- 声明本lua脚本
 21 xlonglive = (require 'xlonglive').new('my_test')
 22
 23 -- 根据argv[1]来决定具体的动作,其值可以为stop/start/check/purge
 24 if not xlonglive:start(argv[1]) then
 25     goto donedone
 26 end
 27
 28 function recv_heartbeat(event)
 29     freeswitch.consoleLog("INFO", "so good, we received a HEARTBEAT event!\n")
 30 end
 31
 32 -- 在FreeSWITCH内打印一行日志
 33 freeswitch.consoleLog("INFO", "BINDING to HEARTBEAT\n")
 34
 35 -- 订阅HEARTBEAT事件
 36 con = freeswitch.EventConsumer("HEARTBEAT")
 37 -- 订阅xlonglive产生且名为`xlonglive::my_test`的事件
 38 con:bind('CUSTOM', xlonglive.event_name)
 39
 40 -- 开始循环取事件
 41 while true do
 42     ::continue::
 43     -- 一直阻塞等待下一个订阅事件的产生
 44     local event = con:pop(1)
 45     -- pop超时1秒,若1秒内未收到订阅的事件,则继续向下进行
 46     -- local event = con:pop(1, 1000)
 47     -- 以上两种pop任选其一即可
 48
 49     if event and event:getHeader("Event-Subclass") == xlonglive.event_name then
 50         -- 获取到xlonglive产生的事件, Event-Subclass是"xlonglive::my_test"
 51         local action = event:getHeader('Action')
 52         -- xlonglive产生的rpc事件,可通过xlonglive:new_rpc_event(method)生成
 53         if action == 'rpc' then
 54             reply = xlonglive:new_rpc_reply_event(event)
 55             reply:addBody("Reply Body")
 56             freeswitch.consoleLog("INFO", reply:serialize())
 57             reply:fire()
 58         end
 59         if not xlonglive:check(event) then
 60             -- 若收到停止脚本事件,则退出循环
 61             freeswitch.consoleLog("INFO", "Stopping my_test ...\n")
 62             break
 63         end
 64         goto continue
 65     end
 66
 67     -- 调用自定义函数,打印一行日志
 68     recv_heartbeat(event)
 69 end
 70
 71 -- 取消事件订阅
 72 con:cleanup()
 73
 74 -- 释放数据库链接
 75 if dbh then
 76     dbh:release()
 77 end
 78
 79 freeswitch.consoleLog("INFO", "my_test script down\n")
 80 ::donedone::

运行

默认XSwitch自带的xlonglive脚本位于XSwitch容器内的/usr/local/freeswitch/xui/lua/xui/xui/xlonglive目录下,你可将自己的脚本放在XSwitch容器内的任何位置。

假设本次my_test.lua脚本放置于XSwitch容器内的/usr/local/freeswitch/xui/lua/xui/xui/xlonglive目录下。

启动

启动时,脚本将一直处于while循环内等待事件的产生。同时xlonglive会向FreeSWITCH内的xui hash表插入一条数据,keyxlonglive-my_testvalue1,此动作是为后续检查脚本是否运行做准备。

进入fs_cli前台,执行如下命令:

luarun /usr/local/freeswitch/xui/lua/xui/xui/xlonglive/my_test.lua start

有如下输出,则表示脚本启动成功:

2024-02-04 08:36:28.917391 98.87% [INFO] switch_cpp.cpp:1477 BINDING to HEARTBEAT
2024-02-04 08:36:28.917391 98.87% [DEBUG] switch_cpp.cpp:86 bound to HEARTBEAT
2024-02-04 08:36:28.917391 98.87% [DEBUG] switch_cpp.cpp:86 bound to CUSTOM xlonglive::my_test

以后每隔20秒,你写的xlonglive脚本就会向FreeSWITCH输出一行日志,如下:

2024-02-04 08:36:41.152365 98.60% [INFO] switch_cpp.cpp:1477 so good, we received a HEARTBEAT event!
2024-02-04 08:37:01.233497 98.63% [INFO] switch_cpp.cpp:1477 so good, we received a HEARTBEAT event!
2024-02-04 08:37:21.372955 98.63% [INFO] switch_cpp.cpp:1477 so good, we received a HEARTBEAT event!

检查

若你不清楚my_test.lua是否已经通过xlonglive启动,可进入fs_cli前台,执行如下命令:

luarun /usr/local/freeswitch/xui/lua/xui/xui/xlonglive/my_test.lua check

若有如下输出,则表示该脚本已经正在运行:

2024-02-04 08:38:43.552360 98.57% [ERR] switch_cpp.cpp:1477 my_test Already Running -ERR key already exists
2024-02-04 08:38:43.552360 98.57% [INFO] switch_cpp.cpp:1477 =?:0: my_test is running

若脚本未运行,则此命令的执行结果与start相同,即启动脚本。

停止

若你想停止my_test.lua脚本,可进入fs_cli前台,执行如下命令:

luarun /usr/local/freeswitch/xui/lua/xui/xui/xlonglive/my_test.lua stop

有如下输出,则表示脚本停止成功:

2024-02-04 08:41:12.795791 98.63% [INFO] switch_cpp.cpp:1477 Stopping my_test ...
2024-02-04 08:41:12.795791 98.63% [DEBUG] switch_event.c:2507 Event Binding deleted for src/switch_cpp.cpp:HEARTBEAT
2024-02-04 08:41:12.795791 98.63% [DEBUG] switch_event.c:2507 Event Binding deleted for src/switch_cpp.cpp:CUSTOM
2024-02-04 08:41:12.795791 98.63% [INFO] switch_cpp.cpp:1477 my_test script down

若你想停止一个没有运行中的xlonglive脚本,则此命令将无任何输出。

此停止只是告知你的my_test.lua脚本退出while循环(见my_test.luaL59-L63),但仍未删除xui hash表内的数据。

清理

清除xui hash表内关于my_test.lua的数据。

注意,若脚本正在运行中,执行此动作,则只会清除hash内的数据,而不会停止脚本

XSwitch中都有什么