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

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模块提供完整的事务管理,无状态模式提供高性能简单转发

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐