摘要

  • 初始 INVITE 中的 SDP 服务于创建者与会议服务器的 offer/answer;接收者名单则让服务器对每个目标启动独立邀请。两个正文同包传输,不会把创建者的协商结果复制给名单成员。
  • 200 OK 只证明会议已创建、发起请求的 UAC 已进入会议、服务器理解了名单;它不证明名单中的任何人被成功邀请、通过准入、建立对话或获得可用媒体。
  • 名单语义属于会议工厂 URI 的初始 INVITE。Contact 返回的会议 URI 是另一项资源;re-INVITE 中的名单没有已定义语义,要求该扩展会得到 420。

multipart 缩短了时间,没有合并权威

RFC 5366 面对的是建立时间。按照较长路径,客户端先请求创建临时会议,等服务器返回会议 URI,再用后续操作加入初始成员。该规范允许客户端在第一次 INVITE 里同时交出名单,于是服务器能在创建会议后立即开始邀请。

为了让创建者本身建立会话,INVITE 还可能携带 SDP。结果是一个 multipart 里出现两个看似同属“建会”的正文:一份描述媒体,一份列出目标 URI。

物理邻近很容易诱发错误模型。系统可能把整个请求标为成功,再把成功状态发给两个正文下面的所有对象。实际上,SDP 与名单在离开解析器后走向不同的执行面。

初始 SDP 参与创建者和会议服务器之间的 offer/answer。它能够证明双方针对这一对话选择了某些媒体参数。名单要求服务器为其他目标执行加入流程。每个目标随后拥有自己的 SIP 事务、认证、focus 决策、会话描述和媒体路径。

因此,一条记录不能写成“INVITE 200,八人音视频会议成功”。它最多能写“工厂请求成功;创建者对话建立;名单被理解”。另外八人的状态必须从另外八条链上取得。

审计设计应在接收 multipart 时就分叉。共同保存请求字节、工厂 URI、事务标识和名单摘要;然后为创建者保存 offer/answer 与对话,为每个规范化目标保存邀请操作。共享父事件,但不共享结果字段。

200 OK 列出了三件已经发生的事

RFC 5366 对初始响应的说明非常具体。200 表示会议成功创建,发送 INVITE 的 UAC 已在会议中,服务器理解了 URI 名单。规范随即说明,该状态码不提供服务器是否把名单中的其他用户带入会议的信息。

“理解名单”是有限命题。它说明服务器把该正文识别成此服务的接收者列表,并能按机制处理。它不等于每个 URI 都有效,也不等于附加结构都保留,更不等于下游动作全部完成。

“创建会议”也不是人数声明。只有创建者的会议仍然是一个已创建的会议。所有外呼同时失败,不会让最初的 200 在其既定范围内变成谎言。

“创建者已进入”同样只属于创建者。它不能沿名单传播。被列出的人尚可能处于未尝试、呼叫中、重定向、拒绝、超时、认证失败、策略拒绝、对话建立或已离开等不同状态。

面向读者的页面如果只显示“会议成功”,应至少解释这个成功的主语。更严谨的模型分别显示 conference_created、creator_dialog_established 与 initial_list_understood,再展开逐目标结果。

这不是挑字眼。若一次会议需要某位审批人,组织者收到 200 后开始讨论,而审批人的邀请在下游失败,初始响应无法证明对方有参与机会。没有逐目标收据,就无法在事后补出这个事实。

创建者的媒体不能替别人完成协商

offer/answer 本身也是逐对话的。初始 INVITE 的 SDP 面向会议服务器,描述创建者希望在自己的会话中发送和接收什么。服务器随后向其他目标发送 INVITE 时,需要为那些对话提供相应的会话描述。

创建者选中了某个音频编码,不说明受邀者支持它。创建者的安全上下文建立成功,不说明其他对话使用了同一机制。创建者的视频路径可用,也不说明另一端穿过了 NAT、防火墙或策略检查。

focus 还可能允许某人进入但限制媒体类型。RFC 5366 的安全讨论明确指出,会议通常有关于谁能加入、哪些媒体可用的授权规则。身份准入和媒体权限必须由 focus 依据潜在参与者的认证结果来判断。

因此,“入会”和“可听见”也不能合并。SIP 对话建立提供信令证据,offer/answer 提供参数一致性,传输遥测说明数据包路径,客户端事件才可能说明解码或播放。至于人是否理解内容,又是协议之外的结果。

运营记录可以不拥有所有层,但必须坦白缺口。最危险的做法是从创建者绿色的媒体指标推导整场会议绿色。

名单写的是请求,不是准入证

创建者有权请求邀请某个 URI,不意味着该 URI 指向的主体自动取得入会权。会议服务器创建完成后“应尝试”加入名单成员;尝试是动作,准入是 focus 的决定。

这一链条至少涉及四个身份:经过认证的创建者、名单中的目标 URI、实际响应外呼的终端,以及 focus 最终认证并准入的主体。呼叫转移、共享地址、多设备和代理都可能让它们不相同。

如果数据库只保留最后一个身份,就无法回答创建者原本邀请了谁。如果只保留原始 URI,就无法证明谁实际进入。正确做法是保留转换边,并附上认证方法、策略版本、决定时间和理由。

RFC 5363 对 URI-list 服务的调用者认证、授权与 opt-in 要求仍然适用。它防止任何人把一个短请求变成未经控制的大规模外呼。但“允许创建者使用名单服务”不等于“每个被写入名单的人都通过会议策略”。

名单属于意图层。邀请事务属于执行层。focus 属于准入层。对话与媒体属于运行层。会议状态包属于观察层。把它们逐层连接,才能看到拒绝发生在哪里。

工厂 URI 和会议 URI 不是同一个能力面

最初的 INVITE 发往会议工厂 URI。服务器创建资源后,在 Contact 中返回实际会议 URI,并表明它是 focus。后续 re-INVITE 发往这个会议 URI。

两者可能位于同一主机,也可能由同一产品实现,但规范赋予它们不同职责。工厂支持 recipient-list-invite,因为它能把初始名单与创建操作绑定。已经存在的会议 URI 在 re-INVITE 中没有这项名单语义。

所以能力探测必须带地址。对工厂发 OPTIONS 并看到 Supported,只能证明那个工厂资源在那个时刻宣告支持。资产台账若把它升级成“整台服务器支持”,客户端就可能把名单错误地发给每个会议 URI。

反过来,会议 URI 拒绝扩展也不能证明产品未实现 RFC 5366。它可能恰好在正确执行范围限制。判断兼容性必须同时看到资源与阶段。

工厂到会议的绑定也要留证。应保存初始事务、返回的 Contact、focus 标识、内部会议 ID 和后续订阅使用的 URI。如果这个映射丢失,逐人邀请和状态通知即使各自存在,也无法证明属于哪次创建请求。

re-INVITE 中的名单没有第二批含义

对话建立后,re-INVITE 常用于修改创建者与服务器之间的媒体特征。RFC 5366 在发布时没有给其中的 recipient-list 正文定义语义,并要求客户端不应发送。

若客户端同时用 Require 声明 recipient-list-invite,会议资源按照 SIP 扩展处理返回 420 Bad Extension,并在 Unsupported 中列出标签。这个响应很有价值:它拒绝了一个没有合同的动作,而不是猜测客户端想加人。

自动修复很容易破坏这种清晰。删掉 Require 再发并不会创造名单语义;服务器可能忽略正文,也可能按别的规则处理。把请求重新发到工厂更危险,因为工厂的操作是创建资源,结果可能是第二间会议。

恢复程序必须先选择业务动作。要给现有会议加人,就使用 RFC 4579 所描述的会议控制机制;要新建会议,才回到工厂;只调整媒体,就发送不带名单的 re-INVITE。

每种选择都要产生新的操作类型,而不能被日志压成“第 2 次重试成功”。否则幂等性与重复资源都无法判断。

会议状态是后来的版本化观察

想知道其他用户状态,RFC 5366 建议使用一般会议机制,例如 RFC 4575 的 conference event package。这承认初始事务没有答案,需要另一观察面。

状态通知比原始名单更接近实际会议,但仍有边界。通知可以是完整或部分文档,有版本顺序,订阅也会中断。部分更新必须建立在有效基线上;丢失中间版本后,不能把剩余片段当成完整名单。

时间也会改变含义。某人在版本 12 出现,不代表版本 13 仍在。最初外呼失败的人可以稍后从别的入口加入。没有列在初始名单的人,也可能被主持人用其他机制加入。

因此应维护三个集合:初始请求集合、focus 操作与决定集合、状态观察集合。它们的差异不是噪声,而是解释会议演化的材料。

即使状态显示某端点在会,也不等于真人听见或参与。状态由 focus 产生,证明它所表示的逻辑关系。媒体与人类结果仍需其他证据。

列表被理解,不代表附加结构都被执行

RFC 4826 能表达层级列表和相对 XCAP 根的引用。RFC 5366 的会议服务只需要平面 URI 列表,建议客户端不要使用多余功能;工厂收到额外信息时可以丢弃。

这让“名单被理解”与“原始结构被完整保留”明确分开。客户端应该提交规范定义的最小形状;服务器应记录原始哈希、解析器版本、规范化结果、被丢弃元素和实际启动操作的集合。

to、cc、bcc 与匿名属性影响出站邀请携带的接收者历史。其优先级和逐接收者投影属于 RFC 5364 的专门文章。对本篇而言,关键只是:历史正文不能代替实际会议成员状态。

证据边界

冻结来源证明标准文本、协议角色、规范要求和 IANA 词汇。它们没有证明任何现有厂商部署了 RFC 5366,没有证明某场真实会议发生,也没有证明某个故障或安全事件。RFC 中的消息流程是示例,不是抓包。

可以确认的原则更窄:同一个封装可以承载多项请求,却不能让一项结果替另一项背书;同一服务可以拥有多个 URI,却不能让能力在 URI 之间无证据迁移。