webrtc中ICE介绍

原因:根据源码进行分析,在此记录一下webrtc中ice连接流程。

概述:Agent首先获取需要的地址,然后地址进行交换,随后进行连通性测试,最终选择一个最合理的连接用于数据传输。

ICE:interactive connectivity establishment交互式连接建立。是一组基于offer/answer模式解决NAT穿越的协议集合。在此简单介绍一下NAT,NAT(Network Address Translation网络地址转换)。目前NAT类型主要分为完全锥型,地址限制锥型,端口限制锥型,对称型,每种类型数据交互模式也不同,需要记住对称型NAT会存在打洞失败的问题。其中ICE主要包含STUN+TURN等协议,TURN协议的主要作用就是用于NAT打洞失败后,利用Relay进行转发。

接下来进行源码分析:

1:首先agent获取地址,其中地址包括host address,srvflx address,relay address 三种。host地址就是我们本地的地址,可以用于局域网内angent之间通信。srvflx address为经过NAT进行反射后的对应的公网地址,通过该地址进行agent之间进行通信。relay address则是经过TURN服务器分配的代理地址,用于进行转发使用。其中使用的优先级为host > srvflx > relay。

通过创建UDPPort,在创建过程中就会进行本地host信息的采集,并按照candidate进行组合。并通过sigslot进行数据回调。

PeerConnection::SetLocalDescription
WebRtcSession::MayStartGathering
P2PTransportChannel::MaybeStartGathering
BasicPortAllocatorSession::DoAllocate
AllocationSequence::OnMessage
AllocationSequence::CreateUDPPorts
UDPPort::OnLocalAddressReady

UDPPort创建成功后我们就要向STUN服务器发送bindingrequest消息,用于获取自身的NAT地址。此时通过发送消息成功接收发回数据,我们将返回数据进行candidate组合并回调。

UDPPort::SendStunBindingRequests
StunBindingRequest::OnResponse
UDPPort::OnStunBindingRequestSuccessded

接下来进行relay地址的获取,此时获取relay地址进行组合candidate并回调。

AllocationSequence::CreateRelayPorts
TurnAllocateRequest::OnResponse
TurnPort::OnAllocateSuccess

关于candidate的格式在此介绍一下:主要参数为foundation,priority,protocol,type,address等。foundation是用于判断candiadate是否相同。priority是用于判断优先级,protocol是用于传输的协议。type是地址类型。address就是地址。在此会有一个baseAddress的概念,该值会决定foundation的值。决定foundation是否相同的参数主要是:候选地址类型type,基准地址ip,传输协议,候选地址。关于基准地址如下:host地址的基准地址就是本身。srvflx地址的基准地址是host地址。relay地址的基准地址是relay地址。

a=candidate:1 1 UDP 9654321 212.223.223.223 12345 typ srflx raddr 10.216.33.9 rport 54321
static std::string ComputeFoundation(const std::string& type,
                                     const std::string& protocol,
                                     const std::string& relay_protocol,
                                     const rtc::SocketAddress& base_address)

此时candidate信息收集完成,则通过上层协议进行交互,接下来我们收到了对端的candidate数据进行设置,首先我们会根据远端的candidate地址创建连接,然后在针对连接进行排序,最终选择一个最优的作为传输连接。

PeerConnection::AddIceCandidate
P2PTransportChannel::AddRemoteCandidate

创建连接:我们将本地所有保存的端口都与远端地址进行创建链接,本地端口的保存是通过每次获取candidate的时候的数据回调。每个连接内部对应一个Connection对象,每个Connection对象内部维护一个队列存放SentPing。根据SentPIng的状态来维护连接的状态。根据状态从而实现排序。

P2PTransportChannel::CreateConnections

排序:主要根据连接状态进行排序,原理就是writeable,receving排在non-writeable,non-receving前面。且内部也会根据网络类型进行比较。

P2PTransportChannel::AddRemoteCandidate
P2PTransportChannel::SortConnectionsAndUpdateState
{
    UpdateConnectionStates();
    CompareConnections();
}

排序完成后我们就会选择一个最优,其中会涉及到连接状态的判断,以及和现有最优的比较等

P2PTransportChannel::MaybeSwitchSelectedConnection

此时选择完成后我们就会进行发送ping进行状态保活。内部原理就是每次都会进行状态更新,查看是否会选择其他connection进行连通。

P2PTransportChannel::MaybeStartPinging
P2PTransportChannel::OnCheckAndPing
P2PTransportChannel::FindNextPingableConnection

以上就是连通性连接流程。

你可能感兴趣的:(WebRTC)