mediasoup create/connect WebRtcTransport 流程分析

news2024/9/25 15:27:40

一. 前言

        在这篇博客中我们介绍了 mediasoup-demo 启动流程与信令交互,关键信令包括 getRouterRtpCapabilites,join, createWebRtcTransport, connectWebRtcTransport, produce,本文将介绍 createWebRtcTransport 和 connectRtcTransport 的流程。

二. createWebRtcTransport

        mediasoup-demo 信令层接收到 createWebRtcTransport 消息后处理请求参数并作为 webRtcTransportOptions 传递给 mediasoup C++ 层创建 transport 使用,请求参数包括 { forceTcp, producing, consuming, sctpCapabilities }。

         mediasoup Router 接收到 ROUTER_CREATE_WEBRTC_TRANSPORT 请求后创建 RTC::WebRtcTransport 对象。

         WebRtcTransport 构造函数处理流程如下,首先获取 enableUdp, enableTcp, preferUdp, preferTcp 参数配置,如果 enableUdp=true 则返回的候选者地址列表包含 UDP 类型的 (ip, port),如果 enableTcp=true 则返回的候选者地址列表包含 TCP 类型的 (ip, port),preferUdp=true 表示更倾向于使用 UDP,preferTcp=true 表示更倾向于使用 TCP,倾向性体现在候选地址的优先级。

        如果 enableUdp 和 enableTcp 同时为 true,说明需要返回两种协议类型的候选者列表,因此 iceCandidates 的大小设置为 listenIps 的 2 倍,每个 iceCandidates 对应一个 UdpSocket 或者 TcpSocket。UdpSocket 底层是 libuv 的 uv_udp_t 对象,它会在收到 UDP 报文数据后回调 WebRtcTransport 的 OnUdpSocketPacketReceived 处理,TcpSocket 底层则是 libuv 的 uv_tcp_t 对象。

候选者的优先级计算规则为:

icePriority = 2^24 * IceTypePreference + 2^8 * localPreference + 2^0 * (256 - IceComponent)。

IceTypePreference 为固定值 64,IceComponent 为固定值 1,说明 icePriority 与 localPreference 成正相关关系,

localPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement,

IceCandidateDefaultLocalPriority 为固定值 10000,而 iceLocalPreferenceDecrement 每次计算完一个地址列表后都会自增 100,也就是地址列表中靠后的地址优先级低于靠前的地址,并且如果设置了 preferUdp 或者 preferTcp 相应类型的候选者 localPreference 会加上 1000。

         WebRtcTransport 构造函数最后创建 ICE Server 和 DTLS Transport 对象。

        ICE 称为交互式连通建立方式(Interactive Connectivity Establishment)。ICE 有两种类型,一种是 full ICE,这种方式通信的双方都要进行连通性检查,另一种是 lite ICE,这种方式 lite ICE 方只要被动回应 reponse 消息即可,即 lite ICE 端不需要主动进行连通性检查,只要 full 端完成连通性检查即可,ICE Server 对应 lite ICE 实现。

        DTLS 是 UDP 层的安全传输协议(类似于 TLS),用来交换 SRTP 加解密的密钥。mediasoup 在启动时会读取配置的证书文件,然后为证书生成不同的散列值(指纹),在验证证书有效性时就可以比对指纹,如果指纹相等说明下发的证书没有被修改过。

        transport 创建完成后,信令层会监听 C++ 层发送的 sctpstatechange, dtlsstatechange, trace 事件并作出相应处理。

         

        createWebRtcTransport 最后返回 { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters }。

字段含义
id传输通道id
iceParametersICE类型,ICE用户名,密码
iceCandidatesICE候选者信息,包括ip, 端口, 协议类型, 优先级等信息
dtlsParameters用于DTLS握手的证书指纹信息
sctpParametersSCTP配置信息

        客户端在收到 createWebRtcTransport 的返回结果后会开启媒体连通性检查,即对 ICE candidates 列表地址发送 STUN 包 binding request ,mediasoup 收到后回应 binding response,如下是抓包内容。

        STUN 报文头部如下所示,Message Type 表示消息类型(包含 Message Method 和 Message Class),Message Length 表示 STUN 消息长度,不包含 20 字节头部,Magic Cookie 值固定为 0x2112A442,Transaction Id 为事务 ID,用于请求和响应的标记 ID 号。RFC3489 定义了 128 bit 的事务 ID,而 RFC5389 将 128bit 的事务 ID 分成 32bit 的 Magic Cookie 和 96bit 的 Transaction Id,因此根据 Magic Cookie 值可以区分是 RFC3489 还是 RFC5389 的 STUN 协议。

        STUN 报文头部后面跟着 0 个或多个属性(attribute),每个属性都采用 TLV 格式编码。

Type属性含义
0x0001MAPPED-ADDRESS获取客户端映射后地址
0x0006USERNAME通知用户名
0x0007PASSWORD密码,用于安全认证
0x0008MESSAGE-INTEGRITY消息完整性,包含一段SHA-1散列值
0x0009ERROR-CODE错误码类型
0x000AUNKNOWN-ATTRIBUTES未知属性
0x0020

XOR-MAPPED-ADDRESS

异或映射地址
0x0024

PRIORITY

候选者优先级
0x0025USE-CANDIDATE提名该候选者
0x8028FINGERPRINT对消息进行CRC值校验
0x8029ICE-CONTROLLED用于区分ICE角色,answer乙方为controlled角色
0x802AICE-CONTROLLING用于区分ICE角色,offer一方为controlling角色

三. connectWebRtcTransport

        connectWebRtcTransport 的请求参数为 transportId 和 dtlsParameters。

         mediasoup C++ 接收到 TRANSPORT_CONNECT 消息请求后会转到对应的 transport 处理,对于 WebRtcTransport 的处理则需要确定对端选择的 DTLS 角色,并开启 DTLS 交互。

         DTLS 交互流程如下所示,关于 DTLS 流程每一步含义说明请参考这篇文章。

         执行 DtlsTransport Run 函数后 DTLS 状态进入 CONNECTING,对于 Client 角色,调用 openssl SSL_set_connect_state,SSL_do_handshake,对于 Server 角色调用 openssl SSL_set_accept_state,SSL_do_handshake。

 

        DTLS 协商完成后计算出 SRTP 使用的密钥,通知 WebRtcTransport->OnDtlsTransportConnected,WebRtcTransport 收到后建立 srtpSendSession,最后通知 mediasoup-demo 信令层 dtlsstatechange (connected)。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为远程MySQL数据库配置固定的公网TCP地址【内网穿透】

在上篇文章中, 我们成功实现了在公网环境下远程连接内网MySQL数据库。但由于使用的免费的cpolar内网穿透,其所生成的公网地址为随机临时地址,24小时内会发生变化,对于需要长期远程访问的用户来讲非常不方便。因此,本篇…

华为云CDN加速服务,让企业用户上网“走高速”

如今CDN技术在互联网项目中越来越被广泛应用,虽然大多数人对于CDN并不熟悉,但其实我们的日常生活中的看新闻、看直播、网上购物等,都在无形之中跟CDN息息相关。 华为云CDN是通过部署广泛的节点服务器,将源站内容分发给靠近用户的智…

【修改】对“C语言实现轰炸代码”进行修改和完善

场景: 使用C语言实现“轰炸”效果,就是多条重复表情或信息的发送;使用场景是在QQ上面。 问题描述 1.不兼容,对于VS2022或者其他VS编译器无法实现效果。 2.代码能正常运行但无法弹出窗口进行发信息。 原因分析: 1.不…

力扣 2032. 至少在两个数组中出现的值

题目 给你三个整数数组 nums1、nums2 和 nums3 ,请你构造并返回一个 元素各不相同的 数组,且由 至少 在 两个 数组中出现的所有值组成。数组中的元素可以按 任意 顺序排列。 示例 输入:nums1 [1,1,3,2], nums2 [2,3], nums3 [3] 输出&a…

Day843.CompletableFuture -Java 并发编程实战

CompletableFuture Hi,我是阿昌,今天学习记录的是关于CompletableFuture的内容。 前面不止一次提到,用多线程优化性能,其实不过就是将串行操作变成并行操作。 如果仔细观察,还会发现在串行转换成并行的过程中&#…

堆树和堆排序

一、堆树 1、定义 堆树的定义如下: (1)堆树是一颗完全二叉树。 (2)堆树的每一个结点值都大于等于或者小于等于其左右子结点的值。 (3)堆树中每个结点的子树都是堆树。为什么是大于等于或者小于…

一口气讲透Redis分布式缓存、秒杀 + 思维导图

一、分布式缓存 1、单点Redis的问题 1、数据丢失问题 Redis数据持久化。 2、并发能力问题 大家主从集群,实现读写分离。 3、故障恢复问题 利用Redis哨兵,实现健康检测和自动恢复。 4、存储能力问题 搭建分片集群,利用插槽机制实现动…

【Linux 常用监控指标总结】

1. Linux运维基础采集项 做运维,不怕出问题,怕的是出了问题,抓不到现场,两眼摸黑。所以,依靠强大的监控系统,收集尽可能多的指标,意义重大。但哪些指标才是有意义的呢,本着从实践中…

【JavaScript】定时器详解

文章目录【JavaScript】定时器详解一. 定时器分类二. 定时器的使用三. 案例:实现抽奖效果样式一样式二【JavaScript】定时器详解 一. 定时器分类 延迟定时器 setTimeout(function(){}, 毫秒数)作用:隔一段时间之后执行 间隔定时器 setInterval(functio…

【UE4 第一人称射击游戏】18-添加角色换弹时的动作

上一篇: 【UE4 第一人称射击游戏】17-重写换弹逻辑 本篇效果: 步骤: 1.打开“SWAT_AnimBP”,在动画图表中,添加一个名为“Reloading”的状态 完善过渡规则的连线 双击打开“Reloading”,添加换弹动画 2…

Spring Security 401 问题解决

背景 : 微服务接口调用的时候报错,原来有一个rest服务用的不多,平时用的都是一些基础的服务,然后客户需要我们开放一个外部接口给他们,然后我寻思着就在这里面写接口。然后调用的时候就报如下的错。 后面跟踪源码发现 …

window上完全卸载oracle

Window上彻底卸载oracle 关闭oracle服务-----开始----->设置----->控制面板----->管理工具----->服务----->停止所有Oracle服务。 卸载软件------开始------所有程序------Oracle - OraDb11g_home1------Oracle 安装产品-----…

传统CV算法——边缘检测

文章目录传统CV算法-边缘检测第一章 概述1. **边缘检测概述**1.1 **认识边缘**1.2 **边缘检测的概念**1.3 **边缘检测的基本方法**1.4 **边缘检测算子的概念**1.5 **常见的边缘检测算子**2. **用梯度算子实现边缘检测的原理**2.1 **认识梯度算子**2.2 **梯度的衡量**2.3 **使用…

3D打印机的调平问题

快打完第五批料了,也算是有一些仅限于PLA以及PLA+耗材心得 3D打印机调平的简易方式有哪些? 在3D打印机中,打印平台作为模型的承载平台,如果有偏差,那么在后期的打印中,必然会导致细节的出现差…

[从零开始]用python制作识图翻译器·一

AlsoEasy-RecognitionTranslator前言需求分析应用场景需求提取需求补充竞品分析QQ识图百度翻译UU翻译器小结功能实现前言 这是我的毕设作品。当时玩了《人狼村之谜》觉得很惊艳,所以想玩一下该社的别的作品:《D.M.L.C.》。但是苦于没有熟肉,自…

vue2中使用VantUI

Vant 是一个轻量、可靠的移动端组件库 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 Vant 2 - Mobile UI Components built on Vue 第一步:安装该组件库 在现有项目中使用 Vant 时&a…

Azure 深入浅出[3]: 如何在MS Visio里面画专业的Azure技术架构图?

1.前言 笔者最近在研究Azure,需要画Azure的技术架构图;画Azure架构图的方法很多,有在线的工具,有基于Azure的PPT模板,同时也有笔者这样选择用最传统的微软的工具:MS Visio来绘图。那么在MS Visio里面如何绘…

设计模式六大原则

设计模式六大原则 1.单⼀职责( ⼀个类和⽅法只做⼀件事 ) 不遵守单一职责原则 模拟不同用户观看视频,先一把梭哈,所有用户观看视频的服务全部都写道一块 public class ApiTest {public static void main(String[] args) {VideoUserService service …

干货丨FPGA零基础学习,入门必看!

看到不少同学后台进行提问:FPGA如何入门?怎么学习?其实对于新人来说,FPGA的学习需要了解的东西还是非常多,下面IC修真院就带大家一起来了解一下吧。 FPGA简介 FPGA普遍用于实现数字电路模块,用户可对FPGA…

Codeforces Round #666 (Div. 1) A. Multiples of Length

Problem - A - Codeforces翻译: 您将得到一个由𝑛个整数组成的数组𝑎。 你想要让𝑎的所有元素都等于零,只需执行以下操作三次: 选择一个段,对于这个段中的每一个数字,我们可以给它加上&#…