摘要

  • RFC 3515 中的 2xx 表示接收方接受处理 REFER,并在原始契约下建立隐式订阅;它不表示 Refer-To 指向的动作已经成功。
  • NOTIFY 观察流、被引用请求和最终现实结果各有生命周期。停止订阅不会取消动作,分叉产生的多个订阅也不能合并成一个状态。

Alice 让 Bob 去联系 Carol,是 RFC 3515 最容易记住的例子。界面上,这像一次“转接成功”。协议线上却至少有四件事:Bob 接受 Alice 的指令,Bob 发起另一项请求,Bob 报告那项请求的状态,Carol 或另一个资源最终产生结果。RFC 3515 的价值正在于没有把它们压成一个绿色按钮。

这份 2003 年 4 月发布的 Standards Track 文档共同定义了 REFER 方法、Refer-To 请求头和 refer 事件包。合法 REFER 必须恰好包含一个 Refer-To 值。接收方按该 URI 类型的正常机制联系资源:SIP URI 可能产生新的 INVITE,其他 URI 则进入相应协议。

REFER 可以带正文,但 RFC 3515 本身不赋予正文语义。接收方可以根据 Content-Type 处理它。这个限制意味着,额外数据不会因为放进 REFER 就自动变成标准化命令。

接收方首先检查格式、能力、认证、策略与用户批准。格式正确也不等于必须执行;用户可以交互批准,系统也可以依配置策略批准。如果没有其他最终响应,原始规范要求在 REFER 事务超时前返回 202 Accepted。

这里的 Accepted 只关闭一个问题:接收方愿意承担 REFER 的处理责任。它没有说明新的 INVITE 已经发出、目标返回最终 200、HTTP 资源可达、媒体已经建立、Carol 已经说话,或者业务转接完成。接收方甚至可能在 202 之后才得到用户的最终批准。

在 RFC 3515 的原始设计中,2xx 还会建立对 refer 事件的隐式订阅,并要求发出通知。NOTIFY 不是附属装饰;它正是因为初始响应不能真实表达后续结果而存在。

订阅建立后会立即产生 NOTIFY,而且这条 NOTIFY 可能在 REFER 事务完成之前到达。发送方必须处理这种时间次序。若状态仍是 pending,正文可以只有 SIP/2.0 100 Trying。它报告“当前还在尝试”,不能证明已经联系、接听或完成。

每条 NOTIFY 都带 Event: refer,正文类型是 message/sipfrag,并以 SIP Response Status-Line 开始。该状态码描述被引用动作在报告时点的状态。每个正文是当时的完整陈述,而不是必须叠加历史消息才能理解的增量。

最小实现可以用 100 表示等待、200 表示它所认定的成功、503 表示失败、603 表示 REFER 已接受但后来用户拒绝批准。603 特别说明接受与结果为何不能混同:系统可以先接受处理责任,再报告实际动作没有获准。

线上还可能出现两个意义完全不同的 200。收到 NOTIFY 的代理会对 NOTIFY 事务返回 200 OK,这只表示状态报告被收到。它不确认 sipfrag 正文中的状态,也不证明被引用动作。若日志只显示“200”而丢掉 CSeq、事务层次与正文,就会把报告收讫误写成动作成功。

对 SIP 动作,通知方可以在 sipfrag 中加入更多原始响应内容,帮助调试。RFC 3515 同时警告这可能产生严重安全后果:头字段、拓扑与目标信息可能泄露给无权知道的 referrer。可观察性越丰富,越需要明确授权。

对非 SIP 资源,状态仍要映射成 SIP 响应行。这给事件包提供统一外形,却不等于保存目标协议的全部证据。适配器报告的 SIP 200 可能没有原生对象标识、副作用回执或物理结果。

订阅还有独立的时钟。REFER 请求与响应不携带订阅时长;接受方选择时长,在首条 NOTIFY 中宣布,通常应长于被引用请求允许完成的时间。referrer 可以刷新订阅,也可以提前终止。

但停止观察不等于停止执行。RFC 3515 明说,显式退订或拒绝 NOTIFY,不表示被引用请求应撤回或放弃。接受方不应仅因 referrer 关闭 refer 订阅就向正在运行的 SIP 请求发送 CANCEL。监控控制与动作控制是两条不同的权限路径。

分叉又加入多条时间线。在既有对话内发送的 REFER 按该契约不会分叉;对话外 REFER 可能被多个代理接受,建立多个订阅。发送方必须分别管理,不能合并状态。一条分支 200、另一条分支 503,代表两个执行者的两次尝试,不是可以平均的单一结论。

授权决定谁可以让接收方去接触第三方资源。宽松策略可能借可信位置访问受保护的 SIP、HTTP 或其他目标。文档因此要求在目标需要保护时构造受限的 Refer-To,并把 referrer 身份、既有对话与用户同意纳入判断。

后来的 RFC 改变了观察方式,而没有消除证据阶梯。RFC 4488 允许请求不建立隐式订阅;RFC 7614 定义显式订阅;RFC 7647 澄清 REFER 与 RFC 6665 新事件框架的关系;RFC 8217 等文档又修正相关语法。分析一段抓包时,必须先知道实际协商的是哪份契约。

用 Heng Lu 的现实分层来读,202 是符号层上“接受一项责任”的回执;NOTIFY 是具名 notifier 在订阅中的报告;被引用请求在自己的协议里运行;媒体、人类对话和业务结果还需要更远一层的观察。较早层的正确消息不能替较后层制造证据。

因此,完整证据链应保留 REFER、授权依据、2xx、订阅身份或明确抑制、每条 NOTIFY 自身的响应与嵌入状态、实际发出的请求、最终协议响应以及应用结果。RFC 3515 没有让委托变得含糊;它只是拒绝把“已接单”写成“已完成”。

Sources