从janus中学习webrtc的ice简单交换过程

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MeRcy_PM/article/details/55806415

1. 简介:

        本文通过web和janus进行实时音视频通信的Demo,结合rfc-5245来学习ice交换的过程。

2. 测试模型

        本文测试模型为一个NAT内的web的客户端,向一个NAT内的janus服务器发起请求。

        

3. rfc 5245

        本文只捡基础的一个流程进行分析,5245协议本身囊括的内容较多。(这里主要围绕2, 2.1, 2.2三段)。

        ICE的过程主要分为三个过程:

        1) 各个peer首先向各自的stun server请求,获取各自的对外IP。(非必须)

        2) 各个peer收集自己的ice candidate,这里包括了本机的local地址,及打洞后获取的对外IP,双方交换ice candidate。

        3) 各个peer收到对应的ice candidate后,排序后向各个candidate发起stun请求,用stun协议进行连通性测试,通过后择优。

4. 过程分析

        本次例子客户端发往打洞服务器被墙……,从抓包上来看,客户端打洞请求发出,但是没有收到对端服务器的响应,而服务端响应正常。

        下图为客户端打洞请求,但是并没有从相应的服务器得到相应的回复。

        下图为服务端的打洞请求,服务端收到了打洞服务器的响应,并得到了自己的对外IP和端口。

        接着我们继续查看客户端发给服务端的请求,这里还是查找POST请求,我们会发现,这里发送给服务端的ice candidate中都是NAT内部的IP。

        服务端日志上正是收到如上部分的candidate。

 

 
  1. [5261413890922073] Trickle candidate (sdparta_0): candidate:0 1 UDP 2122252543 192.168.0.102 55349 typ host

  2. [5261413890922073] Trickle candidate (sdparta_0): candidate:0 2 UDP 2122252542 192.168.0.102 59517 typ host

  3. [5261413890922073] Trickle candidate (sdparta_1): candidate:0 2 UDP 2122252542 192.168.0.102 50268 typ host

  4. [5261413890922073] Trickle candidate (sdparta_1): candidate:0 1 UDP 2122252543 192.168.0.102 50842 typ host

  5. [5261413890922073] Trickle candidate (sdparta_2): candidate:0 1 UDP 2122252543 192.168.0.102 55799 typ host

        服务端收到所有ice后,回复的sdp内容如下,服务端的candidate包含了本机打洞后的IP。

 
  1. "v=0\r\no=mozilla...THIS_IS_SDPARTA-50.1.0 1487429580697208 1 IN IP4 47.89.12.119\r\ns=-\r\nt=0 0\r\na=group:BUNDLE sdparta_0 sdparta_1 sdparta_2\r\na=msid-semantic: WMS janus\r\nm=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8\r\nc=IN IP4

  2. 47.89.12.119\r\na=sendrecv\r\na=mid:sdparta_0\r\na=rtcp-mux\r\na=ice-ufrag:Aa6k\r\na=ice-pwd:Iyz7Wyfm+iBlPYo+OTJiMV\r\na=ice-options:trickle\r\na=fingerprint:sha-256

  3. 9B:0E:EE:53:74:3F:C1:A3:0F:95:F5:15:84:38:8F:3D:8D:8C:00:DB:21:68:15:5E:6D:CA:F6:21:EE:D9:97:34\r\na=setup:active\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=fmtp:109

  4. maxplaybackrate=48000;stereo=1;useinbandfec=1\r\na=rtpmap:109 opus/48000/2\r\na=rtpmap:9 G722/8000/1\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=ssrc:2925740869 cname:janusaudio\r\na=ssrc:2925740869 msid:janus

  5. janusa0\r\na=ssrc:2925740869 mslabel:janus\r\na=ssrc:2925740869 label:janusa0\r\na=candidate:1 1 udp 2013266431 172.31.40.96 49432 typ host\r\na=candidate:2 1 udp 1677721855 47.89.12.119 49432 typ srflx raddr 172.31.40.96 rport

  6. 49432\r\nm=video 9 UDP/TLS/RTP/SAVPF 120 126 97\r\nc=IN IP4 47.89.12.119\r\na=sendrecv\r\na=mid:sdparta_1\r\na=rtcp-mux\r\na=ice-ufrag:Aa6k\r\na=ice-pwd:Iyz7Wyfm+iBlPYo+OTJiMV\r\na=ice-options:trickle\r\na=fingerprint:sha-256

  7. 9B:0E:EE:53:74:3F:C1:A3:0F:95:F5:15:84:38:8F:3D:8D:8C:00:DB:21:68:15:5E:6D:CA:F6:21:EE:D9:97:34\r\na=setup:active\r\na=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1\r\na=fmtp:97

  8. profile-level-id=42e01f;level-asymmetry-allowed=1\r\na=fmtp:120 max-fs=12288;max-fr=60\r\na=rtcp-fb:120 nack\r\na=rtcp-fb:120 nack pli\r\na=rtcp-fb:120 ccm fir\r\na=rtcp-fb:120 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126

  9. nack pli\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:97 nack\r\na=rtcp-fb:97 nack pli\r\na=rtcp-fb:97 ccm fir\r\na=rtcp-fb:97 goog-remb\r\na=rtpmap:120 VP8/90000\r\na=rtpmap:126 H264/90000\r\na=rtpmap:97

  10. H264/90000\r\na=ssrc:3393709355 cname:janusvideo\r\na=ssrc:3393709355 msid:janus janusv0\r\na=ssrc:3393709355 mslabel:janus\r\na=ssrc:3393709355 label:janusv0\r\na=candidate:1 1 udp 2013266431 172.31.40.96 49432 typ

  11. host\r\na=candidate:2 1 udp 1677721855 47.89.12.119 49432 typ srflx raddr 172.31.40.96 rport 49432\r\nm=application 9 DTLS/SCTP 5000\r\nc=IN IP4 47.89.12.119\r\na=sendrecv\r\na=sctpmap:5000 webrtc-datachannel

  12. 16\r\na=mid:sdparta_2\r\na=ice-ufrag:Aa6k\r\na=ice-pwd:Iyz7Wyfm+iBlPYo+OTJiMV\r\na=ice-options:trickle\r\na=fingerprint:sha-256

  13. 9B:0E:EE:53:74:3F:C1:A3:0F:95:F5:15:84:38:8F:3D:8D:8C:00:DB:21:68:15:5E:6D:CA:F6:21:EE:D9:97:34\r\na=setup:active\r\na=candidate:1 1 udp 2013266431 172.31.40.96 49432 typ host\r\na=candidate:2 1 udp 1677721855 47.89.12.119 49432

  14. typ srflx raddr 172.31.40.96 rport 49432\r\n"

        接着双方进行连通性测试,这里我们只看服务端的抓包信息对应的stun协议包。

 

        从下面抓包信息可以看出,服务端收到的candidate只有一个IP,192.168.0.102,服务端在对192.168.0.102:55349进行连通性测试时,并没有收到对应的消息回复,且持续发送(中间已经开始推流了),这是服务端的行为。

        除了服务端发起的连通性测试外,客户端也发起了连通性测试,但是此时的连通性测试发起的IP是一个客户端自己没有记录的IP,服务端收到这个请求后,会认为发现了一个新的candidate,这时候服务端正常回复stun消息后,也再次向该地址:端口发起连通性测试。

5. 部分参数

        在ice的连通性检查时,需要指明这次连通性测试的用户名和密码,如上图服务端的抓包信息,在Binding Request user中指明了【对端用户名:本地用户名】,这两个用户名是在sdp信息中的ice-ufrag字段指明,可以从上文中的sdp中找到相应的用户名Aa6k,同时在字段ice-pwd中指明连通性测试时的密码。此外,还有一个ice-options指明了一些ice使用的参数,这里主要指明了ice的类型是trickle

 

6. ICE确认连接

        这一部分需要解读rfc。

6.1 两种提名(regular nomination & aggressive nomination)

        分为常规的提名和激进的提名。

        常规的提名在协商中controlling一端在发送binding request时候不会携带确认标志,当所有协商完成后对所有的candidate进行评估,最后会再次发送一个带有标志位的请求来表示确认。

        而激进提名方式controlling在发送binding request的时候就会携带对应的标志位,当该次连通性测试完成时,就选定该连接,这种时候不会发送第二次的binding request。

 

With regular nomination, the controlling agent lets the checks
continue until at least one valid candidate pair for each media
stream is found.  Then, it picks amongst those that are valid, and
sends a second STUN request on its NOMINATED candidate pair, but this
time with a flag set to tell the peer that this pair has been
nominated for use.  This is shown in Figure 4.

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

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

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

                    Figure 4: Regular Nomination

Once the STUN transaction with the flag completes, both sides cancel
any future checks for that media stream.  ICE will now send media
using this pair.  The pair an ICE agent is using for media is called
the SELECTED PAIR.

In aggressive nomination, the controlling agent puts the flag in
every STUN request it sends.  This way, once the first check
succeeds, ICE processing is complete for that media stream and the
controlling agent doesn't have to send a second STUN request.  The
selected pair will be the highest-priority valid pair whose check
succeeded.  Aggressive nomination is faster than regular nomination,
but gives less flexibility.  Aggressive nomination is shown in
Figure 5.

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

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

                   Figure 5: Aggressive Nomination

Once all of the media streams are completed, the controlling endpoint
sends an updated offer if the candidates in the m and c lines for the
media stream (called the DEFAULT CANDIDATES) don't match ICE's
SELECTED CANDIDATES.

6.2 标志位

 

        ICE扩展了以下几个stun的attribute,其中6.1中的标志位是USE_CANDIDATE,controlling在选择candidate的时候会在binding request中携带该标志位,而controlled在binding response和binding request都不会携带该标志位。

 

This specification defines four new attributes, PRIORITY, USE-
CANDIDATE, ICE-CONTROLLED, and ICE-CONTROLLING.

The PRIORITY attribute indicates the priority that is to be
associated with a peer reflexive candidate, should one be discovered
by this check.  It is a 32-bit unsigned integer, and has an attribute
value of 0x0024.

The USE-CANDIDATE attribute indicates that the candidate pair
resulting from this check should be used for transmission of media.
The attribute has no content (the Length field of the attribute is
zero); it serves as a flag.  It has an attribute value of 0x0025.

The ICE-CONTROLLED attribute is present in a Binding request and
indicates that the client believes it is currently in the controlled
role.  The content of the attribute is a 64-bit unsigned integer in
network byte order, which contains a random number used for tie-
breaking of role conflicts.

The ICE-CONTROLLING attribute is present in a Binding request and
indicates that the client believes it is currently in the controlling
role.  The content of the attribute is a 64-bit unsigned integer in
network byte order, which contains a random number used for tie-
breaking of role conflicts.

6.3 Janus服务器中的controlling判断

 

        从日志中可以看出Janus的服务器属于controlled,因此连接的最终选择权在客户端。在日志中我们可以看到如下log信息,并搜索对应代码,最终在janus_ice_set_local函数中。

 

[3814770425474886] Setting ICE locally: got OFFER (1 audios, 1 videos)
[3814770425474886] Creating ICE agent (ICE Full mode, controlled)

        我们可以看出此时服务端收到的是客户端的offer,并找到对应分支,controlling的判断首先基于ice的设置,看看服务器是处于lite模式或者是full模式,lite模式时服务端总是controlled,而在full模式时,则根据收到offer或者是发起offer来判断,先发起offer的是controlling。

 
  1. handle->controlling = janus_ice_lite_enabled ? FALSE : !offer;

  2. JANUS_LOG(LOG_INFO, "[%"SCNu64"] Creating ICE agent (ICE %s mode, %s)\n", handle->handle_id,

  3. janus_ice_lite_enabled ? "Lite" : "Full", handle->controlling ? "controlling" : "controlled");

        结合rfc的2.7节:总是处于公网IP下的服务端可以使用lite实现,这种工作模式下的服务端不用收集ice candidate信息,也不用主动发起连通性测试,只需要进行被动响应即可。

 

In order for ICE to be used in a call, both agents need to support
it.  However, certain agents will always be connected to the public
Internet and have a public IP address at which it can receive packets
from any correspondent.  To make it easier for these devices to
support ICE, ICE defines a special type of implementation called LITE
(in contrast to the normal FULL implementation).  A lite
implementation doesn't gather candidates; it includes only host
candidates for any media stream.  Lite agents do not generate
connectivity checks or run the state machines, though they need to be
able to respond to connectivity checks.  When a lite implementation
connects with a full implementation, the full agent takes the role of
the controlling agent, and the lite agent takes on the controlled
role.  When two lite implementations connect, no checks are sent.

For guidance on when a lite implementation is appropriate, see the
discussion in Appendix A.

It is important to note that the lite implementation was added to
this specification to provide a stepping stone to full
implementation.  Even for devices that are always connected to the
public Internet, a full implementation is preferable if achievable.
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值