Kamailio SIP脚本编程核心概念总结

一、有状态与无状态转发的区分

1. 在请求处理中区分

  • 有状态转发 :显示调用 t_relay()t_newtran(),创建事务状态,支持重传、超时处理

  • 无状态转发 :调用 forward(),简单转发SIP请求,不创建事务状态

  • 不转发/拒绝 :调用 dropexit终止处理,可配合 sl_send_reply()发送拒绝响应

2. 在响应处理中区分

  • 有状态处理 :在 onreply_route中调用 t_reply()修改响应,关联特定事务

  • 默认处理:Kamailio自动发现匹配的transaction对象并进行转发

  • 无状态处理 :使用 sl_send_reply()立即发送响应,不关联事务

二、核心函数功能解析

请求处理函数

函数 状态 功能 典型场景
**t_relay()**​ 有状态 创建事务状态,转发请求到下一目的地 INVITE、BYE等需要状态跟踪的呼叫
**forward()**​ 无状态 简单转发SIP请求,不维护状态 OPTIONS探测、特定场景快速转发
**sl_send_reply()**​ 无状态 立即发送响应,不关联事务 认证失败、方法不支持等错误响应
**drop/exit**​ - 终止当前消息处理 处理完成、错误退出

响应处理函数

函数 状态 功能 使用位置
**t_reply()**​ 有状态 发送与特定事务关联的SIP响应 onreply_route
自动转发 有状态 Kamailio自动匹配事务并转发响应 系统自动处理

判断函数

函数 功能 返回值
**is_method()**​ 判断具体请求或响应方法 布尔值
**t_check_trans()**​ 判断是否为有状态事务 布尔值
**t_is_set("onreply_route")**​ 判断是否配置了响应路由 布尔值
**t_check_status("4[0-9][0-9]")**​ 判断是否为负面响应 布尔值

三、转发目标确定机制

1. sl_send_reply()

  • 不需要寻找目标:直接回复给请求来源

  • 自动使用$si(来源IP)和 $sp(来源端口)

  • 示例sl_send_reply("401", "Unauthorized")

2. forward()

  • 明确指定目标

    • 在函数参数中:forward("udp:192.168.1.100:5060")

    • 通过 $du变量:$du = "sip:target@domain:5060"; forward()

3. t_relay()

  • 通过 $du指定$du = "sip:192.168.1.100:5060"; t_relay()

  • 通过 $ru的目标域:自动解析域名,DNS查询SIP服务器

  • 负载均衡模块lb_start()ds_select_dst()自动设置 $du

4. t_reply()onreply_route

  • 目标自动确定:由事务管理器(tm模块)自动确定

  • 不手动指定:只决定回复内容,不控制转发目标

  • 返回路径

    • SIP Via头机制:响应沿Via链自动返回

    • 事务状态:tm模块记录原始请求来源信息

四、有状态与无状态模式对比

1. 无状态模式(不使用tm模块)

特性 说明
事务跟踪 无事务状态,tm模块不介入
响应匹配 Via头自动匹配
目标确定 完全依赖Via头机制
函数调用 不能调用 t_reply()
性能 高,无状态管理开销
可靠性 低,无重传机制
典型场景 OPTIONS探测、简单转发

示例

复制代码
route {
    if (is_method("OPTIONS")) {
        forward("udp:monitor.server:5060");
        exit;
    }
}

2. 有状态模式(使用tm模块)

特性 说明
事务跟踪 完整事务状态管理
响应匹配 事务branch参数匹配
目标确定 事务状态 + Via头共同确定
函数调用 可调用 t_reply()等事务函数
性能 中,有状态管理开销
可靠性 高,支持重传、超时
典型场景 INVITE、BYE等呼叫控制

示例

复制代码
route {
    t_on_reply("MY_REPLY_ROUTE");
    t_relay();  # 创建事务
}

onreply_route[MY_REPLY_ROUTE] {
    t_reply("488", "Modified");  # 修改响应
}

五、tm模块工作机制

1. 事务创建时

复制代码
int t_newtran(struct sip_msg* msg) {
    // 保存来源信息
    trans->uac_sock = msg->rcv;      // 接收socket
    trans->via1 = msg->via1;         // 保存Via头
    trans->branch = msg->branch;     // 保存branch参数
}

2. 响应匹配时

复制代码
struct tm_transaction* t_check_trans() {
    // 通过Via的branch参数匹配事务
    // 返回对应的事务结构
}

3. 响应发送时

复制代码
int t_reply(struct sip_msg* msg, int code, char* reason) {
    // 从匹配事务获取:
    // 1. 目标地址 (uac_sock)
    // 2. 原始Via头
    // 3. 发送socket信息
    // 构造并发送响应
}

六、关键变量说明

预定义变量

变量 含义 是否自动设置
**$ru**​ Request-URI(请求目标) ✅ 自动解析
**$du**​ Destination URI(转发目标) ❌ 需手动设置
**$fu**​ From URI(主叫) ✅ 自动解析
**$tu**​ To URI(被叫显示) ✅ 自动解析
**$si**​ 来源IP地址 ✅ 自动设置
**$sp**​ 来源端口 ✅ 自动设置

七、最佳实践建议

1. 请求处理选择

  • 需要状态跟踪 :使用 t_relay()+ tm模块

  • 简单快速转发 :使用 forward()

  • 立即错误响应 :使用 sl_send_reply()+ exit

2. 响应处理选择

  • 需要修改响应 :在 onreply_route中使用 t_reply()

  • 只需记录日志 :在 onreply_route中记录但不修改

  • 无状态场景:让响应自动透传

3. 目标设置策略

  • 固定目标 :直接设置 $du = "sip:target:port"

  • 动态路由:使用负载均衡模块

  • 域名解析:依赖DNS SRV/NAPTR记录

  • 响应返回:依赖Via头/事务状态,不手动设置

八、总结

Kamailio通过不同的函数和模式提供了灵活的SIP消息处理能力:

  1. 有状态与无状态分离t_relay()用于完整事务处理,forward()用于简单转发

  2. 目标确定多样化:从明确指定到自动发现,适应不同场景需求

  3. 响应处理自动化:通过Via头和事务状态,实现响应的自动正确返回

  4. 模块化设计:tm模块提供完整的事务管理,无状态模式提供高性能简单转发

相关推荐
考虑考虑6 小时前
maven项目使用指定JDK版本打包
java·后端·maven
咕白m6256 小时前
使用 C# 设置 Word 段落对齐样式
后端·c#
Kiri霧7 小时前
Go切片详解
开发语言·后端·golang
0和1的舞者7 小时前
SpringBoot配置文件
java·spring boot·后端·web·配置·spirng
多则惑少则明7 小时前
SpringAI框架接入-jdk升级21后报错“run failed: Unsupported class file major version 65”
java·后端·spring·springai
CadeCode7 小时前
SpringBoot 封装 starter
spring boot·后端·架构
LSL666_7 小时前
7 RESTful 规范
后端·restful
狂奔小菜鸡7 小时前
Day30 | Java集合框架之Collections工具类
java·后端·java ee
Robet7 小时前
Zig 模块和C 头文件包含
后端