众所周知,RFC3262 协议定义了 SIP 临时响应消息的可靠性。这是个非常古早的特性,miniSIPServer(无论是本地版本,还是云端版本)在很久以前就已经支持这个特性。在与传统电信运营商的 IMS 网络对接时,往往必须要支持可靠的临时响应消息,如果设备不具备此能力,运营商通常会直接拒绝所有的呼叫。
RFC3262 定义了“100rel”参数来指示临时响应消息的可靠性,因此我们在此将其称为“100rel”能力。通常情况下,主叫在发起呼叫时应明确指示出自己是否支持“100rel”能力,被叫也同样需要明确要求采用“100rel”能力,因此呼叫双方才能建立临时响应消息的可靠性。
在 RFC3262 标准中,我们可以明确以下细节:
…… the initial request contained a Supported or Require header field listing 100rel, and that there is a provisional response to be sent reliably. ……
UAS core … MUST contain a Require header field containing the option tag 100rel, and MUST include an RSeq header field.
上图描述了可靠临时响应消息的基本流程。UAC 在收到可靠的临时响应 18x 消息时,应当向 UAS 方发送 PRACK 消息,告诉 UAS 自己已经收到了 18x 消息。
这不是一个很复杂的流程,我们一直都认为如此。然而几天前一位云通信用户向我们反映,他无法呼叫外部电话。我们跟踪了他的呼叫,得到以下图描述的呼叫流程:
难以置信…… 这家 VoIP 运营商升级系统后,在 183 消息中要求采用“100rel”能力确保临时响应的可靠性,然而在 miniSIPServer 发送 PRACK 消息进行确认时,它居然返回“405 method not allowed”。这种情况下当然会导致所有的外呼呼叫都失败了。
这是为什么?!如果不能接受、或者不支持 PRACK 消息,它为什么在临时响应消息(也就是183消息)中明确要求“100rel”呢?
要解决这个问题本来也相当简单。只要在临时响应消息中移除“100rel”、即不要求可靠性保证即可,那样 miniSIPServer 就不会发出 PRACK 消息。但是不幸的是,这家运营商的团队居然不知道该怎么做。
我们的客户就被耽搁在这了,他的业务被迫停滞下来。另一方面,我个人猜测这家(以及某些)运营商采用了开源的服务器,例如 Asterisk、FreeSwitch 等,来构建自己的解决方案,但是他们也许没有足够的专家来理解自己究竟构建了什么。
因此我们更新了 miniSIPServer,在外线的配置中增加一个选项用于关闭“100rel”能力,如下图所示:
一旦勾选了这项, miniSIPServer 向外线发出 INVITE 消息时,将不会再携带“100rel”参数。如果您对接了类似荒谬的运营商,请试试这个选项。