Appendix B. 设计动机 (Design Motivations)
ICE 包含许多规范性行为, 这些行为本身可能很简单, 但源自复杂或不明显的思考或用例, 值得进一步讨论. 由于理解这些设计动机对于实现目的并非必要, 因此在本规范的附录中讨论. 本节为非规范性内容.
B.1. STUN Transactions 的 Pacing
用于收集 candidates 和验证连接性的 STUN transactions 会以大约每 Ta 毫秒一个新 transaction 的速率进行 pacing. 每个 transaction 又有一个重传定时器 RTO, 该 RTO 同样是 Ta 的函数. 为什么要对这些 transactions 进行 pacing, 又为什么使用这些公式?
发送这些 STUN requests 通常会在客户端和 STUN servers 之间的 NAT devices 上创建 bindings. 经验表明, 许多 NAT devices 对其创建新 bindings 的速率有上限. 实验表明, 每 20 ms 一次得到了良好支持, 但再低很多则不行. 这就是 Ta 下限为 20 ms 的原因. 此外, 在网络上传输这些分组会使用带宽, 需要由 agent 限速. 基于本文档早期草案版本的部署往往会使受速率约束的 access links 过载并整体表现不佳, 同时对网络产生负面影响. 因此, pacing 确保 NAT device 不会过载, 并使流量保持在合理速率.
B.2. 具有多个 Bases 的 Candidates
第 4.1.3 节讨论了消除具有相同 transport address 和 base 的 candidates. 但是, 具有相同 transport addresses 但不同 bases 的 candidates 并非冗余. agent 什么时候会有两个 IP 地址和端口相同但 bases 不同的 candidates?
考虑 offerer 是 multihomed 的情况. 它在私有网络 C 上有一个 IP 地址, 在网络 A 上有另一个 IP 地址, 而网络 A 被 NAT 到网络 B. offerer 在 C 上获得一个 host candidate, 在 A 上获得一个 host candidate. 它从 A 执行 STUN query, 该 query 通过 NAT, 并被分配了一个恰好与 C 上 IP:port 匹配的 binding. 此时, offerer 获得了一个 transport address 与 host candidate 相同的 server reflexive candidate. 但是, 该 server reflexive candidate 与 host candidate 具有不同 base.
B.3. <rel-addr> 和 <rel-port> 属性的用途
candidate 属性包含两个 ICE 本身完全不使用的值: <rel-addr> 和 <rel-port>. 为什么它会存在?
包含它有两个动机. 第一个是诊断. 了解不同类型 candidates 之间的关系非常有用. 通过包含它, agent 可以知道哪个 relayed candidate 与哪个 reflexive candidate 关联, 而后者又与哪个特定 host candidate 关联. 当某个 candidate 的 checks 成功而其他 candidates 的 checks 不成功时, 这为诊断网络中发生了什么提供了有用信息.
第二个原因与 off-path Quality of Service (QoS) 机制有关. 当 ICE 用于 PacketCable 2.0 等环境时, proxies 会检查 SDP, 并提取媒体流量的 IP 地址和端口, 以建立保证 QoS. 当选择 relayed candidate 时, proxy 需要面向 TURN server 的 server reflexive candidate, 以便向 access router 请求 QoS. 通过在 SDP 中携带这种转换, proxy 可以使用该 transport address.
B.4. STUN Username 的重要性
ICE 要求使用 STUN short-term credential 功能进行 message integrity. 实际的 short-term credential 通过在 SDP offer/answer 交换中交换 username fragments 形成. 该机制的需要不只是出于安全; 它实际上首先就是 ICE 正确运行所必需的.
考虑处于重叠私有网络中的 agents L, R 和 Z. L 向 Z 发送 offer. Z 提供 host candidates. R 恰好使用与 Z 相同的 IP:port. L 发送的 STUN request 到达 R 而不是 Z. 如果 R 直接回复, L 会认为它具有到 Z 的连接性. 为修复这一点, 使用 STUN short-term credential 机制. username fragments 足够随机, 因而 R 使用与 Z 相同值的可能性极低. 因此, 由于 credentials 无效, R 会拒绝该 STUN request.
B.5. Candidate Pair Priority 公式
candidate pair 的 priority 形式有些特殊. 它是:
pair priority = 2^32*MIN(G, D) + 2*MAX(G, D) + (G>D?1:0)
为什么如此? 当 candidate pairs 按该值排序时, 得到的排序具有 MAX/MIN 属性. 这意味着 pairs 首先按两个 priorities 中较小值的递减顺序排序. 对于具有相同最小 priority 值的 pairs, 使用最大 priority 在它们之间排序. 如果最大和最小 priorities 相同, 则使用 controlling agent 的 priority 作为 tie-breaker. 这创建了 MAX/MIN 排序. MAX/MIN 确保对于特定 agent, 在尝试所有更高优先级 candidates 之前, 永远不会使用较低优先级 candidate.
B.6. remote-candidates 属性
a=remote-candidates 属性用于消除 updated offer 与 STUN Binding request 响应之间的 race condition, 该响应会将 candidate 移入 Valid list. 为消除这种情况, offerer 实际选择的 R 端 candidates (remote candidates) 被包含在 offer 本身中, answerer 会延迟其 answer, 直到这些 pairs 通过验证.
B.7. 为什么需要保活 (Keepalives)?
一旦媒体开始在 candidate pair 上流动, 仍然有必要在会话持续期间保持中间 NAT 上的 bindings 处于活动状态. 通常, 媒体流分组本身即可满足此目标. 但是, 如果媒体被置于 hold, 或者使用 silence suppression, 媒体传输可能会停止足够长时间, 导致 NAT bindings 超时. 由于这些原因, 不能依赖媒体分组本身. ICE 定义了一种使用 STUN Binding indications 的简单周期性 keepalive.
B.8. 为什么优先使用 Peer Reflexive Candidates?
第 4.1.2 节要求 peer reflexive candidates 的 type preference 始终高于 server reflexive. 为什么? 原因与安全考虑有关. 攻击者让 agent 使用错误的 server reflexive candidate, 比让 agent 使用错误的 peer reflexive candidate 容易得多. 因此, ICE 通过优先使用 peer reflexive candidates 来阻止针对使用 Binding requests 的地址收集的攻击.
B.9. 为什么发送 Updated Offer (更新 Offer)?
一旦 ICE checks 完成, 两个 agents 都可以发送媒体, 无需等待 updated offer. 实际上, updated offer 的唯一目的是 "correct" SDP, 使媒体的 default destination 与基于 ICE 过程发送媒体的位置匹配.
为什么还需要 updated offer/answer 交换? 实际上, 信令路径上的许多组件会查看 SDP 信息 (例如用于 QoS, NAT traversal, diagnostics). 为了让这些工具无需改变即可继续工作, 必须保留 SDP 的核心属性: 现有的, ICE 之前定义的媒体地址含义. 因此, 必须发送 updated offer.
B.10. 为什么使用 Binding Indications 作为保活 (Keepalives)?
主要原因与网络 QoS 机制有关. 如果 agent 正在发送媒体分组, 然后收到 Binding request, 它就需要在其媒体分组之外生成响应分组. 这会增加实际带宽需求并引入 jitter. 使用 Binding Indication 允许禁用 integrity, 从而获得更好的性能.
B.11. 为什么需要 Conflict Resolution 机制?
两个 agents 都认为自己是 controlled 的情况会出现在 third party call control 场景中. 例如, controller 向 agent A 发送 offerless INVITE, agent A 以 offer 响应. 然后 controller 向 agent B 发送 offerless INVITE, agent B 以 offer 响应. controller 使用这些 offers 生成 answers. 使用该 flow 时, ICE 会在 agents A 和 B 之间运行, 但二者都会认为自己处于 controlling role. 通过 role conflict resolution 过程, 该 flow 将正常工作.