0

我有一个运行注册商和 tm 的 Kamailio 4.0.4 代理 (K)。一些 AOR 有多个客户端,它们都自动接受某些导致竞争条件的 INVITE,并且来自多个分支的 200 个 OK 被发送到被调用者。

场景:- A 向 B 发送邀请

  • K 在 uloc 中为 B 找到 2 个联系人,我们称他们为 B1 和 B2
  • INVITE 被分支发送到 B1 和 B2 注意:B1 的链路延迟为 100ms,B2 延迟为 150ms

  • B1 和 B2 收到后立即自动接受 200 OK

  • 分支 INVITE 后 200ms,K 从 B1 获得 200 OK 并将其中继给 A

  • K 也取消了对 B2 的邀请
  • A 实际上是一个本地 AS,它立即将 200 OK ACK 回 B1

  • 现在的问题是 B2 已经在 50 毫秒前发送了 200 OK 并且在另外 150 毫秒内不会收到 CANCEL

  • 因此,来自 B2 的 200 OK 来到 K,但呼叫已经在 A 和 B1 之间建立

  • 发生的情况是 200 OK 被转发给 A,此时 A 变得完全混乱,因为老实说它不是一个很好的 AS。

现在到实际的问题,我如何阻止额外的 200 OK 转到 A?

我可以看到它应该如何工作的一些选项:

  • 放下200 OK,扔掉它。B2 不应该重新发送它,因为 CANCEL 很快就会击中它
  • ACK + BYE 来自 Kamailio 内部的 200 OK,但这将导致媒体会话被 B2 立即启动和拆除

我什至找不到涵盖这种竞争条件的 RFC。

4

1 回答 1

1

IIRC,根据 rfc,必须始终转发 200ok 响应,这是呼叫者选择一个并为另一个发送 ACK+BYE 的决定。

使用 kamailio 的简单解决方案是在获得 200ok 后放弃任何 200ok。即使 CANCEL 到达,被调用方也可能不会停止重新发送它,将等待 ACK 并最终等待 BYE。

根据 rfc,TM 模块将始终转发 200ok。如果你想加入 kamailio.cfg,一个可能的解决方案:

  • 使用 reply_route { ... } 块来拦截 200ok 的邀请
  • 收到第一个 200ok 时使用 htable 存储(key 可以是 call-id)
  • 使用 cfgutils 获取锁,以防止竞争访问/更新 htable
  • 处理逻辑:如果是INVITE是200ok,就给htable加锁,检查是否有那个callid的key。如果是,解锁并丢弃。如果没有,添加一个以 call-id 作为键的项目,解锁并让响应继续
于 2013-10-31T13:45:28.807 回答