P2PTransportChannel · ICE 总指挥
P2PTransportChannel 是 ICE 的总指挥,把候选采集、配对、连通性检查、选路串成一台状态机。这一章读 base/p2p_transport_channel.h:它如何实现 IceTransportInternal、MaybeStartGathering 与 AddRemoteCandidate 两个入口、以及 gathering 与 transport 两套状态怎么演进到 connected/completed。
P2PTransportChannel · ICE 总指挥
前面几章的零件——候选、Port、STUN、Connection——都要有个总指挥把它们协同起来。这个总指挥就是 P2PTransportChannel(p2p/base/p2p_transport_channel.h)。它实现 IceTransportInternal 接口,是上一部分 JsepTransport 里那个 ICE 传输的真身。这一章看它怎么把 ICE 跑成一台状态机。
两个入口
P2PTransportChannel 对外的核心动作,是通话流程驱动的两个入口(p2p/base/p2p_transport_channel.h):
// p2p/base/p2p_transport_channel.h(节选)
void MaybeStartGathering() override; // 开始采集候选
IceGatheringState gathering_state() const override;
void AddRemoteCandidate(const Candidate& candidate) override; // 加入远端候选
IceTransportStateInternal GetState() const override;MaybeStartGathering—— 由SetLocalDescription触发,委托PortAllocator开始采集本地候选。采到的候选经SignalCandidateGatheredtrickle 给应用。AddRemoteCandidate—— 收到对端候选时调用,把它和兼容的本地候选配成Connection,交给IceController。
一个管「采集与上报本地候选」,一个管「接纳远端候选并配对」——两股候选在 P2PTransportChannel 里汇合成一张连接网。
两套状态
P2PTransportChannel 维护两套状态,别混淆:
采集状态(gathering)和连接状态(transport)是两件事。
IceGatheringState—— 本地候选采集的进度:new(没开始)→gathering(采集中)→complete(采完了)。它只关心「我的候选找齐了没」。IceTransportState(对应 W3C 的RTCIceTransportState)—— 和对端连通的进度:new→checking(正在做连通性检查)→connected(至少一条路通了)→completed(检查全部完成、选定最优)→ 以及出问题时的disconnected/failed/closed。
你在 PeerConnectionObserver 里分别收到 OnIceGatheringChange 和 OnIceConnectionChange 两组回调,对应的正是这两套状态。「候选采集完了」不等于「连上了」——你可能候选早采完,却还在苦苦检查;也可能候选还没采齐,就已经用先到的候选连上了(trickle 的好处)。分开建模,才能精确反映真实进度。
状态怎么演进
把建连五步落到 P2PTransportChannel 的状态机上:
P2PTransportChannel 内部有个 SortConnectionsAndUpdateState——每当有 Connection 状态变化(变 writable、收到包、RTT 更新),它就重新给所有连接排序、更新自己的 transport 状态、并让 IceController 决定是否切换选中的连接。这个「排序 + 更新」是 ICE 动态适应网络的核心循环。
触发下游:连上了就握手
g3doc/ice.md 的建连第五步:一旦 P2PTransportChannel 首次选定一条连接、状态变化,它 SignalIceTransportStateChanged 向上通知——这会让上层的 DtlsTransport 意识到「路通了」,开始 DTLS 握手(第 3 部分)。至此 ICE 完成使命:它交出一条能通的、加密前的通路,媒体的加密与传输接力开始。
小结与下一章
P2PTransportChannel 是 ICE 总指挥(实现 IceTransportInternal),两个入口:MaybeStartGathering(采集本地候选)和 AddRemoteCandidate(接纳远端候选并配对成 Connection)。它维护两套状态——采集(new/gathering/complete)与连接(new/checking/connected/completed/failed/disconnected),分别对应 OnIceGatheringChange / OnIceConnectionChange。核心循环 SortConnectionsAndUpdateState 随连接变化重排、更新状态、驱动选路。连上后 SignalIceTransportStateChanged 触发 DTLS 握手。
它把「选哪条连接用、什么时候切」委托给了 IceController。下一章读这个选路大脑,以及 controlling / controlled 角色。👉 IceController:选路的大脑。
参考资料
- [1] libwebrtc 源码.
p2p/base/p2p_transport_channel.h/.cc(MaybeStartGathering、AddRemoteCandidate、GetState、SortConnectionsAndUpdateState)。 - [2] libwebrtc 源码.
p2p/base/ice_transport_internal.h(IceGatheringState/IceTransportState)、g3doc/ice.md。 - [3] IETF RFC 8445「ICE」;W3C
RTCIceTransportState。