跳到主要内容

9. 后续 Offer/Answer 交换 (Subsequent Offer/Answer Exchanges)

任一 agent 可以在 RFC 3264 [RFC3264] 允许的任何时间生成后续 offer. 第 8 节中的规则会使 controlling agent 在 ICE 处理结束时发送更新的 offer, 前提是 ICE 选择了不同于 default pairs 的 candidate pairs. 本节定义构造后续 offers 和 answers 的规则.

如果后续 offer 被拒绝, ICE 处理会继续, 就像该后续 offer 从未发出过一样.

9.1. 生成 Offer

9.1.1. 所有实现的过程

9.1.1.1. ICE Restarts

agent 可以为现有媒体流 restart ICE 处理. 顾名思义, ICE restart 会清除 ICE 处理的所有先前状态, 并重新开始 checks. ICE restart 与全新媒体会话之间唯一的区别是, 在 restart 期间, 媒体可以继续发送到先前已验证的 pair.

如果满足以下条件, agent 必须为媒体流 restart ICE:

  • 生成 offer 的目的是改变媒体流的目标. 换言之, 如果 agent 希望生成一个更新的 offer, 而在未使用 ICE 的情况下, 该 offer 会导致媒体 component 的 destination 出现新值.

  • agent 正在改变其 implementation level. 这通常只发生在 third party call control 用例中, 其中执行信令的实体不是接收媒体的实体, 并且它在会话中途将媒体目标改变为另一个具有不同 ICE 实现的实体.

这些规则意味着, 将 c line 中的 IP 地址设置为 0.0.0.0 会导致 ICE restart. 因此, ICE 实现 不得将此机制用于 call hold, 而 必须使用 [RFC3264] 中描述的 a=inactivea=sendonly.

为 restart ICE, agent 必须在 offer 中同时改变该媒体流的 ice-pwd 和 ice-ufrag. 注意, 在一个 offer 中使用 session-level 属性, 但在后续 offer 中以 media-level 属性提供相同的 ice-pwd 或 ice-ufrag 是允许的. 这不是 password 的变化, 只是其表示方式的变化, 不会导致 ICE restart.

agent 像为该媒体流的初始 offer 设置 SDP 字段一样设置该媒体流 SDP 中的其余字段 (见第 4.3 节). 因此, candidate 集合 可以包含该流先前 candidates 中的一些, 没有任何先前 candidates, 或全部先前 candidates, 并且 可以包含按第 4.1.1 节描述收集到的一组全新 candidates.

9.1.1.2. 移除媒体流

如果 agent 通过将端口设置为零来移除媒体流, 它 不得为该媒体流包含任何 candidate attributes, 并且 不应该为该媒体流包含第 15 节中定义的任何其他 ICE-related attributes.

9.1.1.3. 添加媒体流

如果 agent 希望添加新媒体流, 它会像该媒体流的初始 offer 一样设置该媒体流 SDP 中的字段 (见第 4.3 节). 这将导致该媒体流开始 ICE 处理.

9.1.2. full 实现的过程

本节描述 full 实现的附加过程, 覆盖现有媒体流.

username fragments, password 和 implementation level 必须与先前使用的保持相同. 如果 agent 需要改变其中任何一项, 它 必须为该媒体流 restart ICE.

额外行为取决于该媒体流的 ICE 处理状态.

9.1.2.1. ICE Running 的现有媒体流

如果 agent 生成一个更新的 offer, 其中包含先前已建立, 且 ICE checks 处于 Running 状态的媒体流, 则 agent 遵循此处定义的过程.

agent 必须为其先前为该媒体流信令的所有 local candidates 包含 candidate attributes. 该 candidate 在 SDP 中信令的属性, 即 priority, foundation, type 和 related transport address, 应该保持相同. 从根本上标识该 candidate 的 IP 地址, 端口和 transport protocol 必须保持相同 (如果它们改变, 那就是新的 candidate). component ID 必须保持相同. agent 可以包含其先前未 offer, 但自上一次 offer/answer 交换以来已收集到的额外 candidates, 包括 peer reflexive candidates.

agent 可以改变媒体的 default destination. 与初始 offers 一样, offer 中 必须有一组与该 default destination 匹配的 candidate attributes.

9.1.2.2. ICE Completed 的现有媒体流

如果 agent 生成一个更新的 offer, 其中包含先前已建立, 且 ICE checks 处于 Completed 状态的媒体流, 则 agent 遵循此处定义的过程.

媒体的 default destination (即用于该媒体流的 m 和 c lines 中 IP 地址和端口的值) 必须是 valid list 中每个 component 的最高优先级 nominated pair 的 local candidate. 这将媒体的 default destination "固定" 为等于 ICE 为媒体选择的 destination.

agent 必须为匹配该媒体流每个 component 的 default destination 的 candidates 包含 candidate attributes, 并且 不得包含任何其他 candidates.

此外, 如果 agent 是 controlling, 它 必须为其 check list 处于 Completed 状态的每个媒体流包含 a=remote-candidates 属性. 该属性包含该媒体流每个 component 在 valid list 中最高优先级 nominated pair 的 remote candidates. 它用于避免 race condition: controlling agent 选择其 pairs, 但更新的 offer 先于 connectivity checks 到达 controlled agent, 而 controlled agent 甚至还不知道这些 pairs 是有效的, 更不用说已被选择. 关于此 race condition 的详细说明见附录 B.6.

9.1.3. lite 实现的过程

9.1.3.1. ICE Running 的现有媒体流

本节描述 lite 实现针对 ICE 正在运行的现有流的过程.

lite 实现 必须在任何后续 offer 中, 为每个媒体流的每个 component, 在 a=candidate 属性中包含其所有 candidates. 这些 candidates 的形成方式与第 4.2 节描述的初始 offers 过程完全相同.

lite 实现不得在后续 offer 中添加额外 host candidates. 如果 agent 需要 offer 额外 candidates, 它必须 restart ICE.

username fragments, password 和 implementation level 必须与先前使用的保持相同. 如果 agent 需要改变其中任何一项, 它 必须为该媒体流 restart ICE.

9.1.3.2. ICE Completed 的现有媒体流

如果某个媒体流的 ICE 已完成, 则该媒体流的 default destination 必须设置为 valid list 中该 component 的 candidate pair 的 remote candidate. 对于 lite 实现, 媒体流的每个 component 在 valid list 中始终只有一个 candidate pair. 此外, agent 必须为每个 default destination 包含一个 candidate 属性.

此外, 如果 agent 是 controlling (这只会在两个 agents 都是 lite 时发生), agent 必须为每个媒体流包含 a=remote-candidates 属性. 该属性包含 valid list 中 candidate pairs 的 remote candidates (每个媒体流的每个 component 一个 pair).

9.2. 接收 Offer 并生成 Answer

9.2.1. 所有实现的过程

当在现有会话中收到后续 offer 时, agent 必须重新应用第 5.1 节中的验证过程, 不考虑任何先前 offer/answer 交换的验证结果. 实际上, 先前 offer/answer 交换可能导致未使用 ICE, 但后续交换可能导致使用 ICE.

9.2.1.1. 检测 ICE Restart

如果 offer 中的 a=ice-ufraga=ice-pwd 属性相对于 peer 先前 SDP 发生变化, 这表示该媒体流正在 restart ICE. 如果所有媒体流都在 restart, 则 ICE 整体正在 restart.

如果某个媒体流正在 restart ICE:

  • agent 必须在 answer 中改变 a=ice-ufraga=ice-pwd 属性.

  • agent 可以在 answer 中改变其 implementation level.

agent 像为该媒体流的初始 answer 设置 SDP 字段一样设置该媒体流 SDP 中的其余字段 (见第 4.3 节). 因此, candidate 集合 可以包含该流先前 candidates 中的一些, 没有任何先前 candidates, 或全部先前 candidates, 并且 可以包含按第 4.1.1 节描述收集到的一组全新 candidates.

9.2.1.2. 新媒体流

如果 offer 包含新媒体流, agent 会像收到包含该媒体流的初始 offer 一样设置 answer 中的字段 (见第 4.3 节). 这将导致该媒体流开始 ICE 处理.

9.2.1.3. 已移除媒体流

如果 offer 包含端口为零的媒体流, agent 不得在其 answer 中为该媒体流包含任何 candidate attributes, 并且 不应该为该媒体流包含第 15 节中定义的任何其他 ICE-related attributes.

9.2.2. full 实现的过程

除非 agent 已从 offer 检测到 ICE restart, username fragments, password 和 implementation level 必须与先前使用的保持相同. 如果 agent 需要改变其中任何一项, 它 必须通过生成 offer 为该媒体流 restart ICE; ICE 不能在 answer 中 restart.

额外行为取决于该媒体流的 ICE 处理状态.

9.2.2.1. ICE Running 且没有 remote-candidates 的现有媒体流

如果某个媒体流的 ICE 正在运行, 且该媒体流的 offer 缺少 remote-candidates 属性, 则 answer 的构造规则与第 9.1.2.1 节中对 offerer 描述的规则相同.

9.2.2.2. ICE Completed 且没有 remote-candidates 的现有媒体流

如果某个媒体流的 ICE 处于 Completed 状态, 且该媒体流的 offer 缺少 remote-candidates 属性, 则 answer 的构造规则与第 9.1.2.2 节中对 offerer 描述的规则相同, 但 answerer 不得在 answer 中包含 a=remote-candidates 属性.

9.2.2.3. 现有媒体流和 remote-candidates

当 peer 已结束某个媒体流的 ICE 处理时, controlled agent 会收到针对该媒体流带有 a=remote-candidates 属性的 offer. 该属性出现在 offer 中, 用于处理 offer 到达与 Binding response 到达之间的 race condition, 后者会告诉 answerer 将由 ICE 选择的 candidate. 关于此 race condition 的说明见附录 B.6. 因此, 带有此属性的 offer 的处理取决于 race 的胜者.

agent 通过以下方式为媒体流的每个 component 形成 candidate pair:

  • 将 remote candidate 设置为 offerer 对该 component 的 default destination (例如, 对 RTP 而言为 m 和 c lines 的内容, 对 RTCP 而言为 a=rtcp 属性).

  • 将 local candidate 设置为 offer 中 a=remote-candidates 属性内同一 component 的 transport address.

然后 agent 查看这些 candidate pairs 是否各自出现在 valid list 中. 如果某个特定 pair 不在 valid list 中, 则该 check "输掉" 了 race. 称这样的 pair 为 "losing pair".

agent 查找 check list 中所有 remote candidates 等于 losing pair 中 remote candidate 的 pairs:

  • 如果没有任何 pair 处于 In-Progress, 且至少一个处于 Failed, 则很可能发生了网络故障, 例如网络分区或严重丢包. agent 应该像 remote-candidates 属性不存在一样为该媒体流生成 answer, 然后为此流 restart ICE.

  • 如果至少一个 pair 处于 In-Progress, agent 应该等待这些 checks 完成, 并在每个 check 完成时重新执行本节中的处理, 直到没有 losing pairs.

一旦没有 losing pairs, agent 就可以生成 answer. 它 必须将媒体的 default destination 设置为 offer 中 remote-candidates 属性内的 candidates (这些 candidates 现在都将是 valid list 中 candidate pair 的 local candidate). 它 必须在 answer 中为 offer 中 remote-candidates 属性内的每个 candidate 包含一个 candidate 属性.

9.2.3. lite 实现的过程

如果收到的 offer 为某个媒体流包含 remote-candidates 属性, agent 通过以下方式为该媒体流的每个 component 形成 candidate pair:

  • 将 remote candidate 设置为 offerer 对该 component 的 default destination (例如, 对 RTP 而言为 m 和 c lines 的内容, 对 RTCP 而言为 a=rtcp 属性).

  • 将 local candidate 设置为 offer 中 a=remote-candidates 属性内同一 component 的 transport address.

然后它将这些 candidates 放入该媒体流的 Valid list. 该媒体流的 ICE 处理状态设置为 Completed.

此外, 如果 agent 原本认为自己是 controlling, 但 offer 包含 remote-candidates 属性, 则两个 agents 都认为自己是 controlling. 在这种情况下, 二者会在大致相同时间发送更新的 offers. 但是, 承载 offer/answer 交换的 signaling protocol 会解决这种 glare condition, 使其中一个 agent 总是因其 offer 在 peer 发送 offer 前被接收而成为 "winner". winner 采用 controlled 角色, 因此 loser (本节考虑的 answerer) 必须将其角色改变为 controlled. 因此, 如果 agent 原本由于第 8.2.2 节中的规则认为自己是 controlling 而准备发送更新 offer, 现在就不再需要发送.

除潜在 role 变化, Valid list 变化以及状态变化之外, answer 的构造与第 9.1.3 节描述的 offer 构造完全相同.

9.3. 更新 Check 和 Valid Lists

9.3.1. full 实现的过程

9.3.1.1. ICE Restarts

在 restart 之前, agent 必须记住媒体流每个 component 在 Valid list 中最高优先级的 nominated pairs, 称为 previous selected pairs. agent 将继续使用这些 pairs 发送媒体, 如第 11.1 节所述. 记录这些 destinations 后, agent 必须清空 valid 和 check lists, 然后按第 5.7 节描述重新计算 check list 及其状态.

9.3.1.2. 新媒体流

如果 offer/answer 交换添加了新媒体流, agent 必须为其创建新的 check list (当然一开始还要有空的 Valid list), 如第 5.7 节所述.

9.3.1.3. 已移除媒体流

如果 offer/answer 交换移除了媒体流, 或 answer 拒绝了被 offer 的媒体流, agent 必须清空该媒体流的 Valid list. 它 必须终止该媒体流正在进行的任何 STUN transactions. agent 必须移除该媒体流的 check list, 并取消其任何 pending ordinary checks.

9.3.1.4. 现有媒体流继续 ICE

除非 ICE 正在 restart, 否则 valid list 不受更新的 offer/answer 交换影响.

如果 agent 对该媒体流处于 Running 状态, 则更新 check list (如果状态为 completed, check list 无关紧要). 为此, agent 使用第 5.7 节描述的过程重新计算 check list. 如果新 check list 上的某个 pair 也在先前 check list 上, 且其状态为 Waiting, In-Progress, Succeeded 或 Failed, 则复制其状态. 否则, 其状态设置为 Frozen.

如果没有任何 check lists 处于 active (即每个 check list 中的 pairs 都是 Frozen), full-mode agent 将第一个媒体流的 check list 中第一个 pair 设置为 Waiting, 然后也将该 check list 中具有相同 component ID 和相同 foundation 的所有其他 pairs 的状态设置为 Waiting.

接下来, agent 遍历每个 check list, 从最高优先级 pair 开始. 如果某个 pair 状态为 Succeeded 且 component ID 为 1, 则同一 check list 中具有相同 foundation, 且 component IDs 不是 1 的所有 Frozen pairs 都将状态设置为 Waiting. 如果对于某个特定 check list, 该媒体流每个 component 都有处于 Succeeded 状态的 pairs, 则 agent 将所有其他媒体流 (因此位于不同 check lists 中) 第一 component 上具有相同 foundation 的所有 Frozen pairs 的状态移为 Waiting.

9.3.2. lite 实现的过程

如果某个媒体流正在 restart ICE, agent 必须为该媒体流启动新的 Valid list. 它 必须记住该媒体流每个 component 在先前 Valid list 中的 pairs, 称为 previous selected pairs, 并继续向那里发送媒体, 如第 11.1 节所述. 每个媒体流的 ICE 处理状态 必须改为 Running, 且 ICE 处理状态 必须改为 Running.