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

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

1. 在请求处理中区分

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

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

  • 不转发/拒绝 :调用 drop或 exit终止处理,可配合 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模块提供完整的事务管理,无状态模式提供高性能简单转发

相关推荐
高频因子挖掘机1 小时前
实时行情为什么不应该逐只股票请求?批量查询与标的池管理实践
后端·github·api
程序猿DD6 小时前
OctaFuse Gateway 2.15.0:MCP 聚合、向量 Embeddings 与官方目录同步
后端·agent
余槐i8 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8269 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
凤山老林10 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne11 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF11 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
pride.li12 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
upala12 小时前
【仓颉语言入门 · 第二篇 第 6 课】
后端
罗丹丹Luna12 小时前
移动端显示“已提交”以后:SAP 与低代码集成该怎样暴露真实状态
后端·架构