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 的处理基本类似,如下。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于TensorFlow Lite在移动端实现人声识别是一种利用机器学习和深度学习的技术,通过训练模型来识别和分析人的声音。TensorFlow Lite是一个针对移动和嵌入式设备的轻量级解决方案,可以在资源受限的环境下运行训练好的模型。 实现人声识别的过程可以分为以下步骤: 1. 数据收集和准备:收集需要识别的人声数据,并进行数据预处理,例如降噪、归一化和特征提取等。 2. 模型训练:使用TensorFlow框架进行模型的训练。可以通过卷积神经网络(CNN)和循环神经网络(RNN)等深度学习模型对特征进行学习和分类。 3. 模型转换:使用TensorFlow Lite将训练好的模型转换成适用于移动设备的.tflite格式。 4. 移动端集成:将转换后的模型集成到移动应用程序中,并利用TensorFlow Lite提供的API进行调用。可以使用Java或者Kotlin编写移动应用程序,并通过引入TensorFlow Lite库进行模型的加载和推断。 5. 人声识别:在移动设备上运行应用程序,通过录制人声并输入到模型中进行推断,从而实现人声的识别和分类。 基于TensorFlow Lite的人声识别在移动端具有较小的模型体积和快速的推断速度,适用于嵌入式设备和资源受限的环境。通过移动端的人声识别,可以实现一系列应用场景,例如语音助手、语音命令和声纹识别等,为用户提供更加智能和便捷的交互体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椛茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值