乐趣区

关于webrtc:WebRTC-ICE-状态与提名处理

大家都晓得奥斯卡有提名,其实在 WebRTC 的 ICE 中也有提名,有惯例的提名,也有激进的提名,而且提名的候选人不肯定是最优良的候选人喔,本文就带你一探其中玄妙。文章内容次要形容 RFC 5245 中 ICE 相干的状态和 ICE 提名机制,并联合 libnice(0.14) 版本进行剖析。

作者:阵图,阿里云开发工程师
审校:泰一,阿里云高级开发工程师

Scene

剖析一个问题时候遇到这样的场景:服务端一个 Candidate,客户端三个不同优先级的 Candidate,然而最初竟然抉择了一个优先级最低的 Pair。

服务端有一个 Relay Candidate,端口 50217。

a=candidate:3 1 udp 503316991 11.135.171.187 50217 typ relay raddr 10.101.107.25 rport 40821

客户端有三个 Candidate,端口 50218(两头优先级),50219(最低优先级),50220(最高优先级)。

Candidate 1:
candidate:592388294 1 udp 47563391 11.135.171.187 50219 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag fO75 network-cost 50

Candidate 2:
candidate:592388294 1 udp 48562623 11.135.171.187 50218 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag fO75 network-cost 50

Candidate 3:
candidate:592388294 1 udp 49562879 11.135.171.187 50220 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag fO75 network-cost 50

然而最初抉择的却是最低优先级的 Pair,50219。

Remote selected pair: 1:1 592388294 UDP 11.135.171.187:50219 RELAYED

Candidate’s Foundation

Candidate 的 Foundation: 这里先提一下 Foundation,会波及到 Frozen 状态。

对于一条雷同的信道,可能有不同的 Candidate,比方 Relay Candidate 被发现的时候,就能够生成一个新的 Server Reflexive 类型的 Candidate,然而他们都是基于雷同的本地地址(IP,端口)和协定,则能够认为这些网络是类似的,则他们就会有雷同的 Foundation。其中 Foundation 在 SDP 中为第一个字段,即上面例子中的 ‘7’。

a=candidate:7 1 udp 503316991 11.178.68.36 51571 typ relay raddr 30.40.198.7 rport 55896

ICE States

ICE 次要有以下五种状态,其中前四种是失常的状态,第五种状态 Frozen 波及到 ICE Frozen Algorithm。

ICE 的五种状态:

  • Waiting: 当连通性查看还没有开始执行的时候(Binding Request 还没发送)。
  • In Progress: 当连通性查看发送了,然而相应查看的事务仍在执行中(Binding Request 已发送)。
  • Successed: 连通性查看执行实现且返回后果胜利(Binding Request 已实现)。
  • Failed: 连通性查看执行实现且后果失败(Binding Request 已实现)。
  • Frozen:,所有 Candidate Pair 初始化实现当前就在这个状态,对于雷同的 Foundation(类似的 Candidate),会依照优先级顺次选取一个 Pair,Unfreeze,并设置为 Waiting 状态,其余则放弃 Frozen。直到选取的 Pair 实现,才会持续 Unfreeze 另一个 Pair。

ICE Nomination

ICE 有两种提名形式:

1.Regular Nomination

对于惯例提名,次要工作流程如下:

L                        R
-                        -
STUN request ->             \  L's
<- STUN response  /  check

<- STUN request  \  R's
STUN response ->            /  check

STUN request + flag ->      \  L's
<- STUN response  /  check

Regular Nomination  

Controlling 模式下的 Agent 发动 Binding Request,并且收到对端的 Response,同时对端发动的 Connective Check 实现,Controling 一端会再次收回一个携带 USE_CANDIDATE 标记位的 Binding Request,当 Controlled 一端收到了,就承受这次提名。

2.Aggressive nomination

除了惯例提名,还有一种比拟激进的提名,惯例提名中会新增一次握手。

L                        R
-                        -
STUN request + flag ->      \  L's

<- STUN response  /  check
<- STUN request  \  R's
STUN response ->            /  check

Figure 5: Aggressive Nomination

Controlling 模式下的 Agent 发动 Binding Request,然而在这个 Binding Request 中会间接携带 USE_CANDIDATE 的标记位,Controlled 模式下的 Agent 收到了当前就承受这次提名。在激进提名模式下,能节约一次握手过程,然而当多个 Pair 同时承受提名时,会依据这些 Pair 各自的优先级进行抉择,抉择出优先级最高的 Pair 作为理论的信道。

实在案例:

Updating States When Nomination

原文参考

当一个新的提名产生时,会对 ICE 外部状态进行对应的变动。

当一端的 Binding Request 携带了 Use Candidate 的标记位时,则会产生一次提名(Nomination)。

不论 Controlling 或者 Controlled 模式下的 Agent,解决提名的状态更新规定倡议如下:

  • 如果没有提名的 Pair,则持续进行连通性查看的过程。
  • 如果至多有一个无效的提名:

    • Agent 必须删除该 Component 下的所有 Waiting 状态和 Frozen 状态的 Pair。
    • 对于 In Progress 状态下的 Pair,优先级低于以后提名 Pair 优先级的,进行重传(勾销)。
  • 当某一个 Stream 的所有 Compont 都至多领有一个提名时,且查看依然在进行时:

    • Agent 必须将该 Stream 标记为已实现。
    • Agent 能够开始传输媒体流。
    • Agent 必须继续响应收到的音讯。
    • Agent 必须重传以后依然在 In Progress 的 Pair(优先级高于以后提名的,不然曾经被删除或者勾销)。
  • 当查看列表中的所有 Pair 都实现时:

    • ICE 实现。
    • Controlling Agent 依据优先级更新 Offer(貌似 WebRTC 没有这一步)。
  • 当查看列表查看有失败时:

    • 所有 Pair 都失败时,敞开 ICE。
    • 当有某个流的查看胜利时,Controlling Agent 移出失败的 Pair,并更新 Offer。
    • 如果有些查看没有实现,则 ICE 持续。

Scheduling Checks

在形容提名时,还会波及 ICE 对 Pair 的调度(当无效 Candidate 还在 In Progress 的时候然而其余 Candidate 的 Pair 曾经收到 Binding Request)。

这里只探讨 Full,先不形容 Lite 模式。

ICE 的 Checks 分成两种,Ordinary Checks And Triggered Checks。

  • Ordinary Checks 是惯例的 Pair 的查看,示意这些 Pair 的查看是从失常流程中切换过去的状态的查看。
  • Triggered Check 是被动触发的查看,当这些 Pair 尽管还处在不能够开始查看的状态,然而这时候收到了对端的连通性查看,这时候会对这个 Pair 进行提速,将其间接放入调度列表。

当 ICE 建设一个 Check List(每个 Stream 一个)后,会对每个 Check List 增加一个定时器,当定时器到来时,会进行如下调度:

注:这里有点不能了解,整个流程看起来是串行的,激活速度有点慢。

  • 首先调度 Triggered Check 并执行。
  • 若无,调度优先级最高的 Waiting 状态的 Pair,发送 Request,同时将状态置为 In Progress。
  • 若无,则从 Check List 中找出优先级最高的 Frozen 状态的 Pair,Unfreeze 之,并发送 Request,状态设置为 In Progress。
  • 若无,终止调度。

Case Analyzed

简略理解了 ICE 的流程后,咱们回归最开始的 Case。

首先看 Add Candidate,三个 Remote Candidate 增加程序不同,顺次为 50219,50218,50220,留神,此时 50219 收到了对端的 Binding Request,激进提名,携带 USE_CANDIDATE,因而很快执行 Create Permission 并实现,这时候能够开始发送 Binding Request 了,属于 Triggered Checks 优先调度,发送 Binding Request,并进入 In Progress 状态。

注:这里除了本地 Relay 的 Pair,还有和 Turn 通信的本地 Host 类型的 Candidate。

接着在 50219 在其余两个 Create Permission 还没实现时候以迅雷不及掩耳之势实现了 Check,依据 rfc 8.1.2 中的形容,对于不是在 In Progress 状态的 Pair,都删除,并不参考其优先级,故最初抉择了 50219 这个优先级最低的 Pair。

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。

退出移动版