OpenSIPS 注册终端 30s 自动挂断问题

1. 背景

在开发呼叫中心应用时,使用 OpenSIPS 作为 SIP 注册服务器,测试发现偶现电话接通后 30s 左右自动挂断的问题。一个正常的 SIP 呼叫流程如下所示,可以看到 OpenSIPS 作为转发层只负责代理转发请求

在这里插入图片描述

2. 问题分析

首先需要明确一点,对于被呼叫的 SIP 终端来说,如果一直收不到 SIP 服务器发送过来的 ACK 则认定会话异常,通常会在 30s 后主动发 BYE 结束会话。根据以上流程图,具体分析时可知道可能存在的问题点有两个:

  1. OpenSIPS 未收到 FreeSWITCH 发送过来的 ACK
    这种情况可能存在的问题是 FreeSWITCH 和 OpenSIPS 之间存在网络故障,进而导致 ACK 丢失。比较大的可能是 NAT 没有处理好,或者是网络协议不匹配等,可通过 sngrep 等工具抓包确认
  2. OpenSIPS 未正确转发 ACK
    OpenSIPS 收到了 FreeSWITCH 发送的 ACK,但是由于自身的问题,未正确将其转发到目标 SIP 终端。这种情况需要检查 OpenSIPS 脚本中处理 ACK 请求的部分,确认脚本逻辑是否存在问题

在这里插入图片描述

3. 案例解决

虽然终端 30s 自动挂断问题的根因毫无疑问,但在实践过程中导致 ACK 丢失的原因千差万别,非常复杂。在笔者的案例中,开发的应用需要保持坐席侧的会话常驻,当坐席的软电话被挂断时,需要自动的重新拨打坐席分机,以实现常驻的特性。在这个前提下,偶现坐席分机软电话 30s 自动挂断的问题,经过长时间的探索,笔者终于找到了必现步骤

  1. 坐席分机注册在 OpenSIPS 后,FreeSWITCH 呼叫坐席分机,坐席接通并常驻
  2. 此时使坐席分机所在网络 IP 漂移,如切换 WIFI 网络
  3. 挂断坐席软电话,让系统自动重新拨打坐席分机
  4. 坐席分机接通后,必现 30s 自动挂断

重新拨打坐席分机的 SIP 信令流程如下图所示,其中可以看到两个异常点:

  1. OpenSIPS 将 INVITE 信令转发给了两个不同的 IP 地址。这里之所以有两个不同的地址,是因为切网操作导致本地 IP 地址漂移,SIP 终端在当前网络下注册到 OpenSIPS 产生了一个新的 location。而对 OpenSIPS 来说,收到 INVITE 信令后会将请求同时送达被叫分机号的两个 location,一个 location 上的终端接通后取消其他 location 上的会话即可。真正的问题在于,在这个场景中一个分机号的两个 location 并没有真实对应两个 SIP 终端,其中一个 location 实际上并没有终端设备存在,所以发往该 location 的 INVITE 信令没有响应,只能不断重试
  2. SIP 终端接通响应 200 后,FreeSWITCH 将 ACK 发往 OpenSIPS,但 OpenSIPS 并没有将 ACK 转发到 SIP 终端真实所在的 location 上,而是将 ACK 发往了没有终端设备存在的 location,导致真实 location 位置上的 SIP 终端没有收到 ACK,最终造成 30s 自动挂断

基于以上分析,可以得出案例的解决方案:

  1. 将分机注册的 location 限制为 1 个,可以参考 max_contacts 参数
  2. 修改 OpenSIPS 脚本中 ACK 的转发逻辑,将 ACK 转发到正确的 location

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45505313/article/details/132475260