流媒体服务器

article/2025/10/19 14:44:42

WebRTC ICE概述

一、概述

ICE全称Interactive Connectivity Establishment:交互式连通建立方式。
ICE参照RFC5245建议实现,是一组基于offer/answer模式解决NAT穿越的协议集合。
它综合利用现有的STUN,TURN等协议,以更有效的方式来建立会话。
ICE是通过综合运用STUN,TURN,RSIP等NAT穿透方式,使之能在最适合的情况下工作,以弥补单独使用其中任何一种所带来的固有缺陷。对于SIP来说,ICE只需要定义一些SDP(Sessionescription Protoc01)附加属性即可,对于别的多媒体信令协议也需要制定一些相应的机制来实现。

ICE的算法可以分为以下几个流程:(1)收集本地传输地址会话者从服务器上获得主机上一个物理(或虚拟)接口绑定一个端口的本地传输地址。(2)启动STUN与传统的STUN不同,ICE用户名和密码可以通过信令协议进行交换。(3)确定传输地址的优先级优先级反映了UA在该地址上接收媒体流的优先级别,取值范围0到1之间,按照被传输媒体流量来确定。(4)构建初始化信息(Initiate Message)初始化消息由一系列媒体流组成,每个媒体流的任意Peer之间实现最人连通可能性的传输地址是由公网L转发服务器(如TURN)提供的地址。(5)响应处理连通性检查和执行ICE算法中描述的地址收集过程。(6)生成接受信息(Accept Message)若接受则发送Accept消息,其构造过程与InitiateMessage类似。(7)接受信息处理接受过程需要发起者使用Send命令,由服务器转发至响应者。(8)附加ICE过程Initiate或Accept消息交换过程结束后,双方可能仍将继续收集传输地址。简单的说,就是SIP终端在注册时,访问STUN服务器;当发起呼叫信息(INVITE)或接收到呼叫信息回应(200 OK)之前根据NAT/防火墙类型通过访问STUN服务器进行对RTP进行地址收集;然后在RTP的地址端口启动接收线程RSTUN服务程序;最后发送SIP消息,收集的地址放列SDP消息中的alt属性中。STUN(简单的用UDP穿透NAT),后面最大的区别是支持TCP穿透(即使用中继穿透NAT)。STUN的扩展。简单的说,TURN与STURN的共同点都是通过修改应用层中的私网地址达到NAT穿透的效果,异同点是TURN是通过两方通讯的“中间人”方式实现穿透。一般来说,实现P2P通信无法实现时,TURN就会派上用场

二、STUN的报文结构为:

消息头
所有的STUN消息都包含20个字节的消息头,包括16位的消息类型,16位的消息长度和128位的事务ID。

 0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|0 0|     STUN Message Type     |         Message Length        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         Magic Cookie                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                                                               ||                     Transaction ID (96 bits)                  ||                                                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                                                              ||              2 byte attrtype  2 byte attrlength  body        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

头两位必须是0,当网络中收到stun和其他数据包时,可以基于该两位的值是否为0判断是stun包。(当然这种判断方式不太严谨
在这里插入图片描述

  • Message Type 总共占14位,其中方法Method 占12位,类型Class占两位。展开后具体格式如下
0                 1
2  3  4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|

M11 到M0 表示12位的Method,C1和C0两位表示Class。
在这里插入图片描述
用12位表示Method,理论上可以表示2^12个Method,实际应用中主要用到一个Binding方法。
Class 占2位,可以表示2^2=4 种类型

在这里插入图片描述
四种类型分别为:request、sucess response、failure response、indication
具体如下:(注意协议文档中的0b00,代表二进制00)
在这里插入图片描述
对于每种Method都会对应请求、成功响应、错误响应、指示四种类型。Method和Class 拼接在一起组成Message Type

enum MessageType
{// see @ https://tools.ietf.org/html/rfc3489#section-11.1 BindingRequest            = 0x0001,BindingResponse           = 0x0101,BindingErrorResponse      = 0x0111,SharedSecretRequest       = 0x0002,SharedSecretResponse      = 0x0102,SharedSecretErrorResponse = 0x0112,
};

Message Length
Message Length 表示除了20字节头以外的所有数据长度。由于STUN属性都是以4字节的倍数填充,因此这个字段最后两位总是等于零,这也是辨别STUN包的一个方法之一。

Magic Cookie
固定的4个字节,具体值为:0x2112A442
Magic Cookie用来和客户端映射的外网IP地址做异或,形成XOR-MAPPED-ADDRESS属性。见下文分析。
Transaction ID
12字节的事务ID。对于一个客户端,客户端和服务端的事务id相等,它被用来作为客户端的唯一标识。
stun协议20字节的消息头后,就是0到N个的属性消息。

三、属性消息

属性格式

 0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|         Type                  |            Length             |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         Value (variable)                ....+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

获取AttrType 和 AtrrLenght方法:
在这里插入图片描述

四、介绍几个常用属性

USERNAME
USERNAME 是有sdp中的ice-ufrag拼接而成,具体的拼接格式为 answer sdp 中的ice-ufrag: offer sdp中的ice-ufrag
在服务器单端口改造时,由于所有客户端的stun包都发到服务器的同一端口,且客户端发送sdp信令(tcp或者websocket协议)的端口和发送stun包(udp协议)的端口不是同一个,所以可用USERNAME区分不同的客户端。
USE_CANDIDATE
USE_CANDIDATE 客户端的icecandidate。
ICE-CONTROLLING
用来表示通信双方的ice角色,ICE-CONTROLLING 表示控制端,用来选择最终进行连接性检测的候选地址对;ICE-CONTROLLED表示被控端,被告知最终用哪个地址对进行通信。

    在实际通信过程中,双方都可能是ICE-CONTROLLING或者ICE-CONTROLLED,当双方值相同时就会产生冲突。为了解决这个冲突,引入一个 tie-breake字段,tie-breake值大的一端是控制端。

Attribute::FINGERPRINT
如果turn包属性中带了FINGERPRINT,需要信息校验。具体mediasoup中实现。
在这里插入图片描述
在这里插入图片描述
MESSAGE-INTEGRITY
消息完整性。

先解释HMAC-SHA1 算法。
HMAC 是一种基于密钥的报文完整性验证方法,其安全性是建立在Hash加密算法基础上的。HMAC利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
SHA1 是一种哈希算法,可以生成一个被称为消息摘要的160位(20字节)散列值
stun包中被加密的具体数据为:
从stun头到该字段(包含该字段)的所有数据,加密中所用的密码是ice-pwd中表示的密码。
加密完成的值,作为MESSAGE-INTEGRITY的属性值保存到stun包中。
mediasoup中具体实现见:StunPacket.cpp 的Serialize()函数
在这里插入图片描述
stun包信息会大概会带以下信息:USERNAME, ICE_CONTROLLING, USE_CANDIDATE, PRIORITY, MESSAGE_INTEGRITY和FINGERPRINT。

五、stun包的合法性判断

mediasoup基于MESSAGE-INTEGRITY 和USERNAME来验证stun包的合法性。

StunPacket::Authentication StunPacket::CheckAuthentication(const std::string& localUsername, const std::string& localPassword){MS_TRACE();switch (this->klass){case Class::REQUEST:case Class::INDICATION:{// Both USERNAME and MESSAGE-INTEGRITY must be present.if (!this->messageIntegrity || this->username.empty())return Authentication::BAD_REQUEST;// Check that USERNAME attribute begins with our local username plus ":".size_t localUsernameLen = localUsername.length();if (this->username.length() <= localUsernameLen || this->username.at(localUsernameLen) != ':' ||(this->username.compare(0, localUsernameLen, localUsername) != 0)){return Authentication::UNAUTHORIZED;}break;}// This method cannot check authentication in received responses (as we// are ICE-Lite and don't generate requests).case Class::SUCCESS_RESPONSE:case Class::ERROR_RESPONSE:{MS_ERROR("cannot check authentication for a STUN response");return Authentication::BAD_REQUEST;}}// If there is FINGERPRINT it must be discarded for MESSAGE-INTEGRITY calculation,// so the header length field must be modified (and later restored).if (this->hasFingerprint)// Set the header length field: full size - header length (20) - FINGERPRINT length (8).Utils::Byte::Set2Bytes(this->data, 2, static_cast<uint16_t>(this->size - 20 - 8));// Calculate the HMAC-SHA1 of the message according to MESSAGE-INTEGRITY rules.const uint8_t* computedMessageIntegrity = Utils::Crypto::GetHmacShA1(localPassword, this->data, (this->messageIntegrity - 4) - this->data);Authentication result;// Compare the computed HMAC-SHA1 with the MESSAGE-INTEGRITY in the packet.if (std::memcmp(this->messageIntegrity, computedMessageIntegrity, 20) == 0)result = Authentication::OK;elseresult = Authentication::UNAUTHORIZED;// Restore the header length field.if (this->hasFingerprint)Utils::Byte::Set2Bytes(this->data, 2, static_cast<uint16_t>(this->size - 20));return result;}

FINGERPRINT
指纹属性,用来检测数据传输过程中是否发生了错误。前面数据完整性是验证数据是否完整,这里是验证消息内部具体的数据是否出错了。

计算规则:
对FINGERPRINT以外的所有数据进行crc-32循环冗余校验(FINGERPRINT是stun包最后一个属性),并把得到的值与0x5354554e异或得到最终的值。

服务端收到stun包以后,再按同样的规则生成一遍,判断自己生成的值和FINGERPRINT属性中所带的值是否相等,相等说明数据正确,否则数据传输中发生了错误。

mediasoup中生成FINGERPRINT和判断FINGERPRINT是否相等的代码如下:

// Add MESSAGE-INTEGRITY.if (addMessageIntegrity){// Ignore FINGERPRINT.if (addFingerprint)Utils::Byte::Set2Bytes(buffer, 2, static_cast<uint16_t>(this->size - 20 - 8));// Calculate the HMAC-SHA1 of the packet according to MESSAGE-INTEGRITY rules.const uint8_t* computedMessageIntegrity =Utils::Crypto::GetHmacShA1(this->password, buffer, pos);Utils::Byte::Set2Bytes(buffer, pos, static_cast<uint16_t>(Attribute::MESSAGE_INTEGRITY));Utils::Byte::Set2Bytes(buffer, pos + 2, 20);std::memcpy(buffer + pos + 4, computedMessageIntegrity, 20);// Update the pointer.this->messageIntegrity = buffer + pos + 4;pos += 4 + 20;// Restore length field.if (addFingerprint)Utils::Byte::Set2Bytes(buffer, 2, static_cast<uint16_t>(this->size - 20));}else{// Unset the pointer (if it was set).this->messageIntegrity = nullptr;}// Add FINGERPRINT.if (addFingerprint){// Compute the CRC32 of the packet up to (but excluding) the FINGERPRINT// attribute and XOR it with 0x5354554e.uint32_t computedFingerprint = Utils::Crypto::GetCRC32(buffer, pos) ^ 0x5354554e;Utils::Byte::Set2Bytes(buffer, pos, static_cast<uint16_t>(Attribute::FINGERPRINT));Utils::Byte::Set2Bytes(buffer, pos + 2, 4);Utils::Byte::Set4Bytes(buffer, pos + 4, computedFingerprint);pos += 4 + 4;// Set flag.this->hasFingerprint = true;}else{this->hasFingerprint = false;}

交流QQ群:512923876 联系邮箱:wsx958191@126.com


http://chatgpt.dhexx.cn/article/TJBTKx9f.shtml

相关文章

常见的流媒体协议

一&#xff0c;基本概念 流媒体&#xff08;streaming media&#xff09;是指将一连串的媒体数据压缩后&#xff0c;经过网上分段发送数据&#xff0c;在网上即时传输影音以供观赏的一种技术与过程&#xff0c;此技术使得数据包得以像流水一样发送&#xff1b;如果不使用此技术…

流媒体技术基础-流媒体编码与协议

一、流媒体传输协议 1.实时传输协议RTP 针对多媒体数据流的一种传输协议&#xff0c;建立在UDP协议上&#xff0c;属于传输层协议。 定义互联网上传递音频和视频的标准数据包格式。RTP协议常用于流媒体系统&#xff08;配合RTCP协议&#xff09;、视频会议和视频电话系统&…

最新海康摄像机、NVR、流媒体服务器、回放取流RTSP地址规则说明

本文档主要介绍海康威视设备直播预览RTSP、录像回放RTSP、流媒体取流的RTSP URL和IE直接预览、回放的HTTP URL。 RTSP为取流协议&#xff0c;取到码流后需要解码显示&#xff0c;可以通过VLC播放器或者EasyPlayer播放器进行测试&#xff0c;IE等浏览器网页不支持RTSP协议直接取…

流媒体服务器ZLMediaKit

ZLMediaKit 获取代码 git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit cd ZLMediaKit git submodule update --init安装GCC4.8 sudo yum -y install gcc sudo yum -y install gcc-c安装cmake3.9 卸载旧版本的cmake(慎用&#xff01;它会删除所有包含cmake的目录…

LiveQing流媒体RTMP推流服务-如何获直播流地址 HLS/HTTP-FLV/WS-FLV/WebRTC/RTMP视频流地址

LiveQing流媒体RTMP推流服务-如何获直播流地址 HLS/HTTP-FLV/WS-FLV/WebRTC/RTMP视频流地址 1、服务说明2、如何一步一步搭建视频直播3、配置鉴权直播间3.1 直播间创建3.2 获取RTMP推流地址3.3 播放流地址 4、视频集成方式5、分享页面集成6、视频流地址集成6.1、直播流地址&…

什么是流媒体???

流媒体又叫做流式媒体&#xff0c;它是指商家用一个视频传送服务器把节目当成数据包发出&#xff0c;传送到网络上。用户通过解压设备对这些数据进行解压后&#xff0c;节目就会像发送前那先显示出来。 这个过程的一系列相关的包称为“流”。流媒体实际指的是一种新的媒体传送方…

Windows基于Nginx搭建RTMP流媒体服务器(附带所有组件下载地址及验证方法)

RTMP服务时常用于直播时提供拉流推流传输数据的一种服务。前段时间由于朋友想搭建一套直播时提供稳定数据传输的服务器&#xff0c;所以就研究了一下如何搭建及使用。 1、下载nginx 首先我们要知道一般nginx不能直接配置rtmp服务&#xff0c;在Windows系统上需要特殊nginx版本…

流媒体服务器(17)—— 流媒体开源服务 MediaSoup 初识

目录 前言 正文 一、简单介绍 二、关键特色 1. 超强 SFU 功能 2. Node.js 模块 3. 客户端 SDK 三、架构组成 1. 关键实例 2. 重要模块 四、发展现状 https://liuzhen.blog.csdn.net/article/details/115603863https://liuzhen.blog.csdn.net/article/details/1156038…

最新有效的rtsp流媒体测试地址

以下发布的地址经测试有效地址 发布时间 2022年8月15日10:26:24 提示&#xff1a;地址如果失效请大家提醒会及时更新 rtsp地址&#xff1a;rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4 2023-6-30 测试已失效 rtmp地址&#xff1a;rtmp://ns8.indexforce…

流媒体服务器EasyNVR怎样获取视频流的播放地址?

很多用户要求在视频直播的过程中&#xff0c;直播画面或者链接是可以进行分享的&#xff0c;以便更多的人能够看到&#xff0c;这一项要求被运用在很多监管平台当中。 在我们的流媒体服务器EasyNVR中可以通过多种方式获得播放地址&#xff0c;本文就为大家介绍三种获取播放地址…

VS2010安装

使用的电脑为Win10 64位&#xff0c;这是使用的VS2010&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1JV3zpoahAPTezE06dB2gEw 提取码&#xff1a;gty8 1、下载后点击【setup.exe】&#xff0c;安装VS2010&#xff1b; 2、点击【安装VS2010】 &#xff1b; 3、这里…

Visual Studio 2010 下载及安装方法(图文解说)

Visual Studio 2010 下载及安装方法&#xff08;图文解说&#xff09; 2012-02-22 11:16:38| 分类&#xff1a; VC程序设计 | 标签&#xff1a; |字号大中小 订阅 http://blog.sina.com.cn/s/blog_5feacbdf0100iiu4.html 在2010年的4月21日&#xff0c;微软官方发布了一…

Win10环境下VS2003安装教程

1、将下图红色框里的两个文件里的内容拷贝到一个新的文件夹中&#xff0c;遇到相同文件直接替换即可&#xff1b; 双击下图红色框中文件后关闭&#xff08;为后面步骤使用&#xff09; 2、打开拷贝后的文件夹&#xff0c;找到setup.exe双击打开&#xff1b; 3、VS.NET第一部…

Visual Studio2015专业版安装教程

Win7系统下安装&#xff1a; 参考链接&#xff1a;https://blog.csdn.net/j879159541/article/details/93461358 不需要VS2015的全部组件&#xff0c;只需要与C/C相关的组件&#xff0c;这里只选择了“Visual C”。 等待安装完成即可。

VS2010详细安装步骤

VS2010安装步骤 为了满足不同需求的用户&#xff0c;VS2010 又被细分成了五个版本&#xff0c;分别是专业版(Professional)、高级版(Premium)、旗舰版(Ultimate)、学习版(Express)和测试版(Test) 其中&#xff1a; 学习版是免费的&#xff0c;功能也相对简单&#xff0c;主要供…

VS 2017安装教程

1、首先下载安装包&#xff0c;地址是&#xff1a;https://www.microsoft.com/zh-cn/download/&#xff0c;进入首页后选择开发人员工具&#xff0c;进入开发人员工具后即可下载VS&#xff0c;VS有三个版本&#xff0c;分别是社区版、专业版、企业版。我选择的是社区版。点击下…

VS2015安装

计算机配置&#xff1a; i7 win7 sp1 vs2010&#xff1b; VS2015安装过程中&#xff0c;首先在安装.net的时候很慢&#xff0c;全部安装完成2小时左右&#xff1b; 如果安装过程顺利就安装完成了&#xff0c;但是我安装后提示一些组件安装错误&#xff0c;重新安装依然错误…

Visual studio 2015(VS2015)的下载和安装,以及安装VS2015中的C++

主要内容如下&#xff1a; 1. VS2015下载 2. VS2015安装 3. VS2015安装C的内容 作者&#xff1a;大曲曲 邮箱&#xff1a;xiaoxia.qufoxmail.com 本文最终目标&#xff1a;要实现VS2015QT5OpenCV3开发环境搭建 1. VS2015下载 Visual studio官方网站&#xff1a;https://www.vi…

Visual Studio系列 Visual Studio2010安装教程

目前微软官网上面好像是只有最新版的Visual Studio 2019了&#xff0c;一般现在新买的电脑上面可能会附带着该年最新版的Visual Studio&#xff0c;如果没有的话&#xff0c;你也可以要求他帮你安装激活好。毕竟如果你要是想买正版软件的话&#xff0c;其实也挺贵的&#xff0c…

VS2010的详细安装

Microsoft Visual Studio2010旗舰版的详细安装。 安装包&#xff1a;链接: https://pan.baidu.com/s/1-JNyGhwIvasAYQL0GsmzQw 密码: fdds step 1、拷贝或下载的安装包&#xff08;Microsoft Visual Studio2010.rar&#xff09;放在E盘&#xff08;最好不要放在C盘&#xff0…