mediasoup Lite ICE实现说明

目录

一. 前言

二. Lite ICE流程

三. STUN协议说明

STUN Header

STUN Body

四. mediasoup Lite ICE实现源码剖析


一. 前言

        ICE 是一种交互式建立连接的流程协议。ICE 有两种模式(Full ICE 和 Lite ICE),Full ICE 要求建立连接的双方都要执行连通性检测,而 Lite ICE 则只要求响应 STUN binding request 信息即可,它不需要添加候选者并对候选者进行连通性检测。

        媒体服务器一般都使用的是 Lite ICE 实现,因为媒体服务器通常部署在公网,它的网络没有限制,因此一般只需要客户端检测与媒体服务器提供的候选者地址是连通的即可。

二. Lite ICE流程

        mediasoup 客户端要进行推流首先要创建通道,创建通道是通过 createWebRtcTransport 信令完成的,该信令返回的信息包含 {id, iceParameters, iceCandidates, dtlsParameters, sctpParameters},如下是一个示例值,包含了 ICE 的用户名,密码,使用的是 Lite ICE,以及候选者地址,优先级,协议等。

示例:{ id: ‘c0fe3f31-a764-40ff-88ff-69c14b83afda’,

iceParameters: { iceLite: true, password: ‘0pcc8bpoj1ug2s30p6ldh4qlgan1n5wd’, usernameFragment: '6jeiq5rqh7ke06dqzgnvzmg3iwtjxbqr' },

iceCandidates: [{"foundation":"udpcandidate","ip":"10.211.55.5","port":44445,"priority":1076302079,"protocol":"udp","type":"host"}],

dtlsParameters: { fingerprints: [ {"algorithm":"sha-224","value":"21:81:82:05:AD:52:C3:64:C1:F8:FF:44:65:79:97:51:85:D1:7A:20:13:6F:B0:B6:25:EA:B4:46"}, ... ], role: 'auto' },

sctpParameters: { MIS: 1024, OS: 1024, isDataChannel: true, maxMessageSize: 262144, port: 5000, sctpBufferedAmount: 0, sendBufferSize: 262144 } }

        mediasoup 的 WebRtcTransport 对应 webrtc 的 RTCPeerConnection,mediasoup 客户端收到 createWebRtcTransport 的返回结果后会创建 WebRtcTransport(即对应一个 RTCPeerConnection),然后将 createWebRtcTransport 信令返回的 ICE 等参数信息设置到 remoteSdp 中,在媒体协商的时候将 remoteSdp 设置为 RTCPeerConnection 的remoteDescription,之后就开始发送 binding request 进行连通性检测。

        设置的 remoteSdp 部分内容如下所示,可以看到 usernameFragment 的内容在 a=ice-ufrag,password 的内容在 a=ice-pwd 中,a=candidate 的内容为 iceCandidates 的内容。

        抓包分析 Lite ICE 流程如下所示,mediasoup 客户端发送 STUN binding request 消息,携带 USERNAME, GOOG-NETWORK-INFO, ICE-CONTROLLING, PRIORITY, MESSAGE-INTEGRITY 以及 FINGERPRINT 属性。

        mediasoup 服务端收到 STUN binding request 消息后,回复 STUN binding response 消息,携带 XOR-MAPPED-ADDRESS, MESSAGE-INTEGRITY, FINGERPRINT 属性。

        之后 mediasoup 客户端发送 DTLS Client Hello 消息,说明客户端收到服务器回复的 STUN binding response 消息后 ICE 状态已经是成功连接的状态了。

三. STUN协议说明

        STUN工作原理 这篇博客描述了 STUN 报文的格式,ICE 实现要求遵循 RFC5389 而不是 RFC3489,RFC5389 的 STUN 报文格式如下所示。

STUN Header

STUN Message Type 的 14bit 含义如下,M11-M0 表示 Method,目前只有 Binding 一种 Method,C1C0 表示 Class,C1C0=0b00 表示请求,C1C0=0b01 表示指示,C1C0=0b10 表示请求成功的响应,C1C0=0b11 表示请求失败的响应。

Message Length 表示 STUN 报文 Body 的长度

Magic Cookie 固定为 0x2112a442

Transaction ID 表示事务 ID,用于关联请求和响应,响应携带事务 ID 以表明这是对哪个请求的响应

STUN Body

        STUN 消息体的内容是一系列属性,每个属性都是 Type, Length, Value 结构,我们主要讲解 Lite ICE 流程涉及到的属性含义,注意下面的属性值不完全属于 RFC5389 规范的定义,例如 PRIORITY,USE-CANDIDATE,ICE-CONTROLLING 是由 RFC5245 ICE 规范对 RFC STUN 协议的扩展,而 GOOG-NETWORK-INFO 是 webrtc 对 STUN 协议的扩展。

属性名称Type说明
USERNAME0x0006ICE用户名
GOOG-NETWORK-INFO0xC057网络信息,包含network-id以及network cost信息
ICE-CONTROLLING0x802AICE控制角色,携带该属性表示是控制方,与之对应的为受控方(ICE-CONTROLLED),对于 mediasoup,客户端需要进行连通性检测,是控制方角色,而服务器是受控方角色
PRIORITY0x0024优先级
MESSAGE-INTEGRITY0x0008用于消息完整性验证,该值的计算是基于SHA-1的HMAC算法,密钥使用 ICE 的 password,消息体则使用 STUN 消息内容(不包含该属性本身以及 FINGERPRINT 属性的内容)
FINGERPRINT0x8028消息指纹
XOR-MAPPED-ADDRESS0x0020异或地址
USE-CANDIDATE0x0025该属性只会出现在ICE控制方,表示ICE控制方已经选择好候选地址并准备通信,ICE受控方收到该消息后将该消息发送的对端地址设置为通信的对端地址即可

四. mediasoup Lite ICE实现源码剖析

        WebRtcTransport 收到数据包后调用 WebRtcTransport::OnPacketReceived,该函数会判断接收到的消息是什么类型的消息,如果是 STUN 协议的消息,就调用 OnStunDataReceived 进行处理,STUN 协议消息的判断即根据上述描述的 STUN 报文格式进行判断即可。

       WebRtcTransport::OnStunDataReceived 会调用 RTC::StunPacket::Parse 解析消息,得到 StunPacket,之后调用 IceServer::ProcessStunPacket 进行处理。

        IceServer 是 WebRtcTransport 的一个成员变量, 它负责维护 WebRtcTransport 的 ICE 当前状态信息,例如保存 ICE 用户名密码,连接状态,所有的对端候选地址以及当前选中使用的对端候选地址,如下是 IceServer 的成员变量。

class IceServer
{
public:enum class IceState{NEW = 1,CONNECTED,COMPLETED,DISCONNECTED};// ......private:// Passed by argument.Listener* listener{ nullptr };// Others.std::string usernameFragment;std::string password;std::string oldUsernameFragment;std::string oldPassword;uint32_t remoteNomination{ 0u };IceState state{ IceState::NEW };std::list<RTC::TransportTuple> tuples;RTC::TransportTuple* selectedTuple{ nullptr };
};

        IceServer::ProcessStunPacket 处理流程如下所示,首先判断 STUN 消息是否是一个正常的消息,如果 Method 不是 binding,说明不是一个正常的 STUN Message,或者如果 STUN binding request 消息没有携带 FINGERPRINT 属性,也不是一个正常的消息,返回错误响应即可。

        接下来判断 STUN Message 是否携带了 MESSAGE-INTEGRITY, PRIORITY, USERNAME 等属性,如果当中任意一个属性不包含,则返回错误响应。

        之后再调用 packet->CheckAuthentication 校验消息,CheckAuthentication 主要是校验 STUN Message 的用户名是否正确,以及 MESSAGE-INTEGRITY 是否正确。

         StunPacket::CheckAuthentication 处理逻辑如下所示,首先是判断 USERNAME 属性分号前的用户名与服务器本地用户名是否相等,如果不相等则认证失败,如果相等,再判断 MESSAGE-INTEGRITY 属性是否正确,避免使用在传输过程中被篡改的消息。

        接下来再判断如果 STUN Message 携带了 ICE-CONTROLLED 属性,则返回角色错误的失败响应,因为 mediasoup 客户端是控制方角色,mediasoup 服务端是受控方角色,所以 mediasoup 客户端发送的 STUN Message 不应该携带 ICE-CONTROLLED,而应当是 ICE-CONTROLLING。

        如果前面的合法性都校验通过,接下来就是执行对 STUN binding request 的响应,即生成 STUN binding reponse 消息,并设置 XOR-MAPPED-ADDRESS 属性值,然后添加 MESSAGE-INTEGRITY 以及 FINGERPRINT 属性值。

        至此 mediasoup 接收 STUN binding request 并回复 STUN binding response 的流程就讲解完成,收到 STUN binding request 最后一步处理函数是 HandleTuple(tuple, packet->HasUseCandidate(), packet->HasNomination(), nomination);

        HandleTuple 的处理逻辑如下所示,客户端第一次发送的 STUN binding request 消息没有携带 USE-CANDIDATE 和 NOMINATION,并且此时是 New 状态,因此执行下面的逻辑,此时将当前的对端地址信息添加到 IceServer 的 tuples 成员变量,并设置当前 tuple 为 selectedTuple,设置为 selectedTuple 即表示这个对端地址信息是 WebRtcTransport 认为的客户端的通信地址,之后需要往客户端发送的媒体数据就会往这个地址发送,这些操作完成之后 ICE 状态变成 CONNECTED。

        连通性检测成功后,mediasoup 客户端会再发送 STUN binding request 消息进行保活,此时发送的 STUN bindind request 会增加 USE-CANDIDATE 属性,表示 mediasoup 客户端已经确定使用该连接进行后续的通信。

        当 ICE 处于 CONNECTED 状态,再收到 STUN binding request 消息后执行的逻辑如下,如果 STUN binding request 里包含 USE-CANDIDATE 则会将 tuple 设置为 selectedTuple,如果包含 NOMINATION 则必须属性里携带的提名值大于当前使用的提名值,处理完成后将 ICE 状态设置为 COMPLETED。

        当 ICE 处于 COMPLETED 状态收到 STUN binding request 后的处理与 ICE 处于 CONNECTED 时收到 STUN binding request 的处理基本类似,如下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/54125.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS——锁与死锁问题

iOS中的锁 什么是锁锁的分类互斥锁1. synchronized2. NSLock3. pthread 递归锁1. NSRecursiveLock2. pthread 信号量Semaphore1. dispatch_semaphore_t2. pthread 条件锁1. NSCodition2. NSCoditionLock3. POSIX Conditions 分布式锁NSDistributedLock 读写锁1. dispatch_barri…

AOF日志:宕机了,Redis如何避免数据丢失

当服务器宕机后&#xff0c;数据全部丢失&#xff1a;我们很容易想到的一个解决方案是从后端数据库恢复这些数据&#xff0c;但这种方式存在两个问题&#xff1a;一是&#xff0c;需要频繁访问数据库&#xff0c;会给数据库带来巨大的压力&#xff1b;二是&#xff0c;这些数据…

Rust 编程小技巧摘选(6)

目录 Rust 编程小技巧(6) 1. 打印字符串 2. 重复打印字串 3. 自定义函数 4. 遍历动态数组 5. 遍历二维数组 6. 同时遍历索引和值 7. 迭代器方法的区别 8. for_each() 用法 9. 分离奇数和偶数 10. 判断素数&#xff08;质数&#xff09; Rust 编程小技巧(6) 1. 打印…

剑指offer60.n个骰子的点数

这道题很简单&#xff0c;看完题目就会。看完题就会想到用动态规划的方法&#xff0c;如果我要用i个骰子拿到j个点数&#xff0c;那么我只能在i-1个骰子拿到j-1个点的情况下再用第i个骰子投出一个1&#xff0c;或者i-1个骰子拿到j-2个点的情况下再用第i个骰子投出一个2&#xf…

Unity学习参考文档和开发工具

☺ unity的官网文档&#xff1a;脚本 - Unity 手册 ■ 学习方式&#xff1a; 首先了解unity相关概述&#xff0c;快速认识unity编辑器&#xff0c;然后抓住重点的学&#xff1a;游戏对象、组件|C#脚本、预制体、UI ☺ 学习过程你会发现&#xff0c;其实Unity中主要是用c#进行开…

[Docker实现测试部署CI/CD----自由风格和流水线的CD操作(6)]

目录 12、自由风格的CD操作发布 V1.0.0 版本修改代码并推送GitLab 中项目打 Tag 发布 V2.0.0 版本Jenkins 配置 tag 参数添加 Git 参数添加 checkout 命令修改构建命令配置修改 SSH 配置 部署 v1.0.0重新构建工程构建结果 部署 v2.0.0重新构建工程访问 部署v3.0.0 13、流水线任…

微信小程序animation动画,微信小程序animation动画无限循环播放

需求是酱紫的&#xff1a; 页面顶部的喇叭通知&#xff0c;内容不固定&#xff0c;宽度不固定&#xff0c;就是做走马灯&#xff08;轮播&#xff09;效果&#xff0c;从左到右的走马灯&#xff08;轮播&#xff09;&#xff0c;每播放一遍暂停 1500ms &#xff5e; 2000ms 刚…

npm -v无法显示版本号

情况&#xff1a; 删除C盘下.npmrc文件后解决。路径 C:\Users\Dell 记录一下这个解法。

【eNSP】Telnet远程登录

Telnet远程登录 eNSP软件TelnetTelnet远程登录-路由连接关闭防火墙eNSP根据图1画图路线配置路由端口IP配置路由R1改名配置接口IP 配置路由R2 配置R2的远程登录设置登录用户授权级别退出登录超时时间 Telnet测试 eNSP软件 eNSP(Enterprise Network Simulation Platform)是一款由…

像素画教程:立体感与“84渐变法“

像素画本身没有什么困难&#xff0c;是矢量图简笔画之外最简单、而又最容易产生美术效果的画风。 然而&#xff0c;细节难以描绘、立体感难表现、画面易单调成了像素画绘制过程中的常见困难。 这篇文章或许不能保证每个人都能熟练掌握、运用像素画&#xff0c;但至少可以抛砖引…

【雕爷学编程】MicroPython动手做(31)——物联网之Easy IoT 3

1、物联网的诞生 美国计算机巨头微软(Microsoft)创办人、世界首富比尔盖茨&#xff0c;在1995年出版的《未来之路》一书中&#xff0c;提及“物物互联”。1998年麻省理工学院提出&#xff0c;当时被称作EPC系统的物联网构想。2005年11月&#xff0c;国际电信联盟发布《ITU互联网…

考研408 | 【计算机网络】物理层

导图&#xff1a; 一、通信基础 基本概念&#xff1a; 物理层接口特性&#xff1a;物理层解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。 物理层主要任务&#xff1a;确定与传输媒体接口有关的一些特性 典型的数据通信模型 数据通…