Bootstrap

kamailio的路由模块由lua脚本实现

以下是 将原 Kamailio 路由逻辑转换为 Lua 脚本 的完整实现:


一、Lua 路由脚本

创建文件 /usr/local/kamailio/etc/kamailio/kamailio-test.lua,内容如下:

-- kamailio-test.lua

-- 主请求路由函数
function request_route()
    -- 初始检查:最大跳数
    if KSR.maxfwd.process_maxfwd(10) < 0 then
        KSR.sl.send_reply(483, "Too Many Hops")
        return
    end

    -- 处理 CANCEL 请求
    if KSR.pv.is_method("CANCEL") then
        if KSR.tm.t_check_trans() > 0 then
            KSR.tm.t_relay()
        end
        return
    end

    -- 处理 REGISTER 请求
    if KSR.pv.is_method("REGISTER") then
        if KSR.registrar.save("location") < 0 then
            KSR.sl.reply_error()
        end
        return
    end

    -- 仅允许 INVITE 请求
    if not KSR.pv.is_method("INVITE") then
        KSR.sl.send_reply(405, "Method Not Allowed")
        return
    end

    -- 查找用户位置
    if KSR.registrar.lookup("location") < 0 then
        KSR.sl.send_reply(404, "User Not Found")
        return
    end

    -- 转发请求到目标(UAS)
    KSR.tm.t_relay()
end

二、修改 Kamailio 配置文件

更新 /usr/local/kamailio/etc/kamailio/kamailio-test.cfg,主要内容如下:

#!KAMAILIO

####### 全局参数 #########
debug=3
log_stderror=no
memdbg=5
memlog=5
children=4
listen=udp:192.168.1.70:5060

####### 加载模块 #########
loadmodule "app_lua.so"     # 关键:加载 Lua 模块
loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "registrar.so"
loadmodule "usrloc.so"

####### 模块参数配置 #########
modparam("usrloc", "db_mode", 0)
modparam("siputils", "rpid_avp", "$avp(s:rpid)")
modparam("app_lua", "load", "/usr/local/kamailio/etc/kamailio/kamailio-test.lua")  # 指定 Lua 脚本路径

####### 路由逻辑 #########
# 主路由直接调用 Lua 脚本
request_route {
    lua_exec("request_route");
}

三、关键改动说明

1. 模块加载
  • 新增 app_lua.so 模块:用于支持 Lua 脚本执行。
  • 调整模块顺序:确保 app_lua 先于其他模块加载。
2. Lua 脚本绑定
  • modparam("app_lua", "load", "..."):指定 Lua 脚本路径。
  • lua_exec("request_route"):在 request_route 中调用 Lua 函数。
3. Lua 逻辑对照
原配置逻辑Lua 实现
mf_process_maxfwdKSR.maxfwd.process_maxfwd()
is_methodKSR.pv.is_method()
t_check_transKSR.tm.t_check_trans()
t_relayKSR.tm.t_relay()
save("location")KSR.registrar.save("location")
lookup("location")KSR.registrar.lookup("location")

四、测试验证

1. 启动 Kamailio
/usr/local/kamailio/sbin/kamailio -f /usr/local/kamailio/etc/kamailio/kamailio-test.cfg -DD -E
2. 观察日志

正常启动后应输出:

DEBUG: app_lua [lua_support.c:64]: lua_sr_init_mod(): Lua script loaded: /usr/local/kamailio/etc/kamailio/kamailio-test.lua
3. 测试 SIP 请求
  • 注册请求

    sipp -sn uac 192.168.1.70:5060 -s 1001 -m 1 -r 1 -d 1000 -inf users.csv
    
    • users.csv 示例:
      SEQUENTIAL
      1001;[authentication username=1001 password=123456]
      
  • INVITE 请求

    sipp -sn uac 192.168.1.70:5060 -s 1001 -i 192.168.1.62 -m 1 -r 1 -d 1000
    

五、高级调试

1. Lua 脚本日志

在 Lua 脚本中添加调试日志:

KSR.log(LOG_NOTICE, "INVITE received from " .. KSR.pv.get("$si"))
2. 查看用户位置

通过 Kamailio 控制台检查注册状态:

kamcmd ul.dump

六、常见问题

1. Lua 模块未加载

错误日志:

ERROR: module app_lua not found

解决方法:

  • 确保编译时启用了 Lua 支持:
    make include_modules="app_lua" cfg
    
2. Lua 脚本权限问题

错误日志:

ERROR: app_lua [lua_support.c:101]: lua_sr_load_script(): failed to load script

解决方法:

  • 检查脚本路径是否正确:
    ls -l /usr/local/kamailio/etc/kamailio/kamailio-test.lua
    

总结

通过将路由逻辑迁移到 Lua,您可以:

  1. 灵活扩展:利用 Lua 的完整编程能力实现复杂逻辑。
  2. 热更新:修改 Lua 脚本后无需重启 Kamailio(部分场景支持)。
  3. 代码复用:共享 Lua 库函数跨多个 Kamailio 实例。

知识补充

在 Kamailio 的 Lua 脚本中,KSR 是一个 全局对象,它是 Kamailio 提供的 Lua API 的核心接口。通过 KSR,Lua 脚本可以调用 Kamailio 的核心功能、模块函数以及访问 SIP 消息的变量和属性。


KSR 的作用

KSR 是 Kamailio 与 Lua 脚本之间的桥梁,提供了以下功能:

  1. 访问 Kamailio 模块函数
    • 例如:KSR.tm.t_relay() 调用 tm 模块的 t_relay 函数。
  2. 访问 Kamailio 变量
    • 例如:KSR.pv.get("$si") 获取 SIP 消息的源 IP 地址。
  3. 执行 Kamailio 核心功能
    • 例如:KSR.maxfwd.process_maxfwd(10) 检查最大跳数。
  4. 日志记录
    • 例如:KSR.log(LOG_NOTICE, "Log message") 输出日志。

KSR 的结构

KSR 是一个分层的对象,其结构如下:

  • 模块命名空间
    • 每个 Kamailio 模块在 KSR 中有一个对应的命名空间。
    • 例如:tm 模块的函数通过 KSR.tm 访问。
  • 核心功能
    • 核心功能(如日志、变量访问)通过 KSR 直接访问。
    • 例如:KSR.log() 用于日志记录。

KSR 的常用方法

以下是一些常用的 KSR 方法:

1. 核心功能
  • 日志记录

    KSR.log(LOG_NOTICE, "This is a log message")
    
    • LOG_NOTICE 是日志级别,其他级别包括 LOG_DEBUGLOG_ERROR 等。
  • 变量访问

    local src_ip = KSR.pv.get("$si")  -- 获取源 IP
    local method = KSR.pv.get("$rm")  -- 获取 SIP 方法
    
2. 模块功能
  • tm 模块

    KSR.tm.t_relay()          -- 转发请求
    KSR.tm.t_check_trans()    -- 检查事务
    
  • sl 模块

    KSR.sl.send_reply(200, "OK")  -- 发送 SIP 响应
    
  • maxfwd 模块

    if KSR.maxfwd.process_maxfwd(10) < 0 then
        KSR.sl.send_reply(483, "Too Many Hops")
    end
    
  • registrar 模块

    if KSR.registrar.save("location") < 0 then
        KSR.sl.reply_error()
    end
    
  • pv 模块

    if KSR.pv.is_method("INVITE") then
        KSR.log(LOG_NOTICE, "INVITE received")
    end
    

KSR 的底层实现

KSR 是通过 Kamailio 的 Lua 模块 (app_lua.so) 实现的。它封装了 Kamailio 的核心功能和模块函数,使其可以在 Lua 脚本中直接调用。

  • 模块加载

    • 在 Kamailio 配置文件中加载 app_lua.so 模块:
      loadmodule "app_lua.so"
      
    • 指定 Lua 脚本路径:
      modparam("app_lua", "load", "/path/to/script.lua")
      
  • 函数映射

    • Kamailio 的 C 函数通过 Lua API 暴露给 Lua 脚本。
    • 例如:t_relay() 函数在 Lua 中通过 KSR.tm.t_relay() 调用。

示例:KSR 的使用

以下是一个完整的 Lua 脚本示例,展示了 KSR 的常见用法:

-- kamailio-test.lua

function request_route()
    -- 获取 SIP 方法
    local method = KSR.pv.get("$rm")
    KSR.log(LOG_NOTICE, "Received " .. method .. " request")

    -- 检查最大跳数
    if KSR.maxfwd.process_maxfwd(10) < 0 then
        KSR.sl.send_reply(483, "Too Many Hops")
        return
    end

    -- 处理 REGISTER 请求
    if KSR.pv.is_method("REGISTER") then
        if KSR.registrar.save("location") < 0 then
            KSR.sl.reply_error()
        end
        return
    end

    -- 处理 INVITE 请求
    if KSR.pv.is_method("INVITE") then
        if KSR.registrar.lookup("location") < 0 then
            KSR.sl.send_reply(404, "User Not Found")
            return
        end
        KSR.tm.t_relay()
    end

    -- 其他请求返回 405
    KSR.sl.send_reply(405, "Method Not Allowed")
end

总结

  • KSR 是 Kamailio 提供的 Lua API 接口,用于访问 Kamailio 的核心功能和模块函数。
  • 通过 KSR,Lua 脚本可以实现与原生 Kamailio 配置相同的功能,同时具备更高的灵活性和可扩展性。
  • 熟悉 KSR 的使用是编写 Kamailio Lua 脚本的关键。
;