mediasoup源码分析(四)channel返回信令及notify通知

channel返回信令及notify通知

    • 前言
    • 正常成功返回Accept
    • 异常失败返回Reject
    • mediasoup主动推送,Emit
    • mediasoup推送数据到信令服务的具体实现:
    • tips

前言

在mediasoup源码分析(三)channel创建及信令交互一文中介绍了mediasoup中channel的创建,接下来在本文中,会说明mediasoup c++层如何将处理后的数据返回到信令服务中。

在 Mediasoup 中,C++ 编写的媒体层(mediasoup-worker)与信令服务之间的通信通常是通过 JSON 格式的数据进行的。这种数据格式易于解析和生成,并且被广泛用于 Web 服务和客户端之间的通信。
一个有三个返回的接口

正常成功返回Accept

void Request::Accept(Json::Value& data){MS_TRACE();static Json::Value emptyData(Json::objectValue);static const Json::StaticString JsonStringId{ "id" };static const Json::StaticString JsonStringAccepted{ "accepted" };static const Json::StaticString JsonStringData{ "data" };MS_ASSERT(!this->replied, "Request already replied");this->replied = true;Json::Value json(Json::objectValue);json[JsonStringId]       = Json::UInt{ this->id };json[JsonStringAccepted] = true;if (data.isObject() || data.isArray())json[JsonStringData] = data;elsejson[JsonStringData] = emptyData;this->channel->Send(json);}

数据格式eg:

  1. 无数据
createRouter返回
{"accepted":true,"data":{},"id":12610940}
  1. 有数据
createWebRtcTransport返回
{"accepted": true,"data": {"dtlsLocalParameters": {"fingerprints": [{"algorithm": "sha-1","value": "4F:6A:93:00:BF:8D:BD:C6:B5:18:64:65:35:83:7A:6F:2F:BF:FE:45"}, {"algorithm": "sha-224","value": "04:9D:E6:35:24:62:C6:1D:B3:34:63:DB:B0:28:8E:77:4D:DD:AD:6B:F7:7A:F9:3D:7D:44:F1:CC"}, {"algorithm": "sha-256","value": "15:8C:71:05:B6:F9:B8:CD:09:7A:BB:1A:D2:CC:64:53:D4:4B:8C:E3:1F:56:C3:2F:F5:C1:73:F8:06:86:5C:C2"}, {"algorithm": "sha-384","value": "FB:61:03:17:88:DE:A8:F7:B3:52:1F:7E:0B:4A:9D:0A:4F:E2:83:B2:F1:60:3E:B4:0F:42:48:AA:48:01:26:A5:82:57:82:33:33:77:9C:3F:4B:C0:C7:30:4F:D0:1C:E4"}, {"algorithm": "sha-512","value": "78:30:EA:FD:D9:2B:FB:9E:45:43:BE:FE:05:D2:33:DC:38:70:63:D7:0F:8E:DC:4F:C9:88:44:75:0C:31:38:70:64:E2:56:3E:78:71:0E:E8:CE:DA:28:97:05:0F:99:90:0A:E6:CE:B1:D0:33:F3:E6:B9:00:67:EC:19:BD:77:48"}],"role": "auto"},"dtlsState": "new","headerExtensionIds": {},"iceLocalCandidates": [{"family": "ipv4","foundation": "udpcandidate","ip": "0.0.0.0","port": 52000,"priority": 1078862079,"protocol": "udp","type": "host"}],"iceLocalParameters": {"iceLite": true,"password": "t6f2mqxz6d3cy46xe7cfr3ywruk9ftji","usernameFragment": "21256833097-1899696"},"iceRole": "controlled","iceState": "new","rtpListener": {"muxIdTable": {},"ridTable": {},"ssrcTable": {}},"transportId": 1899696},"id": 62863332
}

异常失败返回Reject

	void Request::Reject(const char* reason){MS_TRACE();static const Json::StaticString JsonStringId{ "id" };static const Json::StaticString JsonStringRejected{ "rejected" };static const Json::StaticString JsonStringReason{ "reason" };MS_ASSERT(!this->replied, "Request already replied");this->replied = true;Json::Value json(Json::objectValue);json[JsonStringId]       = Json::UInt{ this->id };json[JsonStringRejected] = true;if (reason != nullptr)json[JsonStringReason] = reason;this->channel->Send(json);}

数据格式eg

{"rejected":true,"reason":{},"id":12610945}

mediasoup主动推送,Emit

	void Notifier::Emit(uint32_t targetId, const std::string& event, Json::Value& data){MS_TRACE();static const Json::StaticString JsonStringTargetId{ "targetId" };static const Json::StaticString JsonStringEvent{ "event" };static const Json::StaticString JsonStringData{ "data" };Json::Value json(Json::objectValue);json[JsonStringTargetId] = Json::UInt{ targetId };json[JsonStringEvent]    = event;json[JsonStringData]     = data;this->channel->Send(json);}

数据格式eg

{"data":{"entries":[[87344059,-89],[42826186,-24]]},"event":"audiolevels","targetId":37286065}

mediasoup推送数据到信令服务的具体实现:

由上面三段代码可以看到,无论是Accept,还是Reject,亦或者是Emit,最终实际都调用的是UnixStreamSocket模块的send接口channel->Send接口

void UnixStreamSocket::Send(Json::Value& msg)
{if (IsClosed())return;// MS_TRACE_STD();std::ostringstream stream;std::string nsPayload;size_t nsPayloadLen;size_t nsNumLen;size_t nsLen;this->jsonWriter->write(msg, &stream);nsPayload    = stream.str();nsPayloadLen = nsPayload.length();if (nsPayloadLen > MessageMaxSize){MS_ERROR_STD("mesage too big");return;}if (nsPayloadLen == 0){nsNumLen       = 1;WriteBuffer[0] = '0';WriteBuffer[1] = ':';WriteBuffer[2] = ',';}else{nsNumLen = static_cast<size_t>(std::ceil(std::log10(static_cast<double>(nsPayloadLen) + 1)));std::sprintf(reinterpret_cast<char*>(WriteBuffer), "%zu:", nsPayloadLen);std::memcpy(WriteBuffer + nsNumLen + 1, nsPayload.c_str(), nsPayloadLen);WriteBuffer[nsNumLen + nsPayloadLen + 1] = ',';}nsLen = nsNumLen + nsPayloadLen + 2;Write(WriteBuffer, nsLen);
}
  • this->jsonWriter:指的是当前 UnixStreamSocket 类实例的 jsonWriter 成员,这个成员是一个指向 JSON 写入器的指针。这个写入器负责将 Json::Value 对象转换成 JSON 格式的字符串。
  • write(msg, &stream):是 jsonWriter 指针所指向对象的一个成员函数,它接受两个参数:
    • msg:要序列化的 Json::Value 对象。
    • &stream:一个引用,指向 std::ostringstream 类型的 stream 对象。这个对象是一个输出流,用于接收序列化后的 JSON 字符串。

当这个函数调用执行时,jsonWriter 会将 msg 对象中的数据转换成 JSON 格式,并将结果输出到 stream 中。这样,stream 就会包含序列化后的 JSON 字符串,这个字符串可以用于后续的网络传输或其他用途。

void UnixStreamSocket::Write(const uint8_t* data, size_t len)
{if (this->closed)return;if (len == 0)return;uv_buf_t buffer;int written;int err;// First try uv_try_write(). In case it can not directly send all the given data// then build a uv_req_t and use uv_write().buffer  = uv_buf_init(reinterpret_cast<char*>(const_cast<uint8_t*>(data)), len);written = uv_try_write(reinterpret_cast<uv_stream_t*>(this->uvHandle), &buffer, 1);// All the data was written. Done.if (written == static_cast<int>(len)){return;}// Cannot write any data at first time. Use uv_write().else if (written == UV_EAGAIN || written == UV_ENOSYS){// Set written to 0 so pendingLen can be properly calculated.written = 0;}// Error. Should not happen.else if (written < 0){MS_ERROR_STD("uv_try_write() failed, closing the socket: %s", uv_strerror(written));Close();// Notify the subclass.UserOnUnixStreamSocketClosed(this->isClosedByPeer);return;}size_t pendingLen = len - written;// Allocate a special UvWriteData struct pointer.auto* writeData = static_cast<UvWriteData*>(std::malloc(sizeof(UvWriteData) + pendingLen));std::memcpy(writeData->store, data + written, pendingLen);writeData->req.data = (void*)writeData;buffer = uv_buf_init(reinterpret_cast<char*>(writeData->store), pendingLen);err = uv_write(&writeData->req,reinterpret_cast<uv_stream_t*>(this->uvHandle),&buffer,1,static_cast<uv_write_cb>(onWrite));if (err != 0)MS_ABORT("uv_write() failed: %s", uv_strerror(err));
}

这段代码使用了libuv库,这是一个跨平台的异步I/O库,用于网络编程。先uv_buf_init初始化,随后使用了uv_try_write和uv_write函数来尝试写入数据,如果一次性写入不成功,则使用异步写入的方式继续写入剩余的数据。此外,代码中还包含了错误处理和内存分配的逻辑。

tips:
关于libuv的介绍,可以看我写的网络编程-libuv介绍一文。

tips

更多关于mediasoup的文章可以进入我的专栏查看
http://t.csdnimg.cn/3UQeL

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

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

相关文章

拼多多面试总结

文章目录 一面自我介绍提问算法反问结果 二面提问算法反问结果 主管面主管面试准备算法题其他个人提问准备 提问数据库普通索引和覆盖索引的区别索引是什么&#xff1f;索引怎么加快数据库查询的&#xff1f;索引具体怎么实现的&#xff1f;以B树为例&#xff0c;节点放了什么&…

自动预约申购 i茅台工具完善

自动预约申购茅台工具 概述新的改变界面预览 概述 今天刷到一个windows自动刷茅台的工具&#xff0c;是用wpf实现的&#xff0c;看到作者最后是2023年更新的&#xff0c;评论中有好多人提出一些需求&#xff0c;刚才在学习wpf&#xff0c;就试着完善了一下。 工具下载&#x…

【C++】文件处理(IO流)

文章目录 C IO流1. C语言IO2. CIO2.1 C标准IO流2.2 C文件IO流2.3 C IO 文件常用函数总结表2.4 C stringstream C IO流 回顾一下&#xff0c;C语言中IO输入输出的 1. C语言IO C语言中常用的输入输出函数有如下几种&#xff1a;前者是格式化标准输入输出&#xff0c;后者是格式化…

C语言——结构体指针

观察下述代码&#xff1a; typedef struct student {char* name; //可以存char *a “hellow world”; 可以当一个字符串 他的地址是第一个字母hint age; int (*init)(void);//一个指向无参数、返回类型为int的函数的指针。后面需要用到就成员名点方法struct student* classma…

windows和linux下清空Redis

前言 在本文中&#xff0c;我们将详尽阐述在Windows与Linux操作系统中有效清除Redis缓存的实践方法&#xff0c;旨在为您提供清晰、高效的指导流程&#xff0c;确保数据管理的灵活性与效率。 windows下推荐两款可视化工具 Another Redis Desktop Manager 这是我用的最多也是最…

数据库原理与安全复习笔记(未完待续)

1 概念 产生与发展&#xff1a;人工管理阶段 → \to → 文件系统阶段 → \to → 数据库系统阶段。 数据库系统特点&#xff1a;数据的管理者&#xff08;DBMS&#xff09;&#xff1b;数据结构化&#xff1b;数据共享性高&#xff0c;冗余度低&#xff0c;易于扩充&#xff…

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中&#xff0c;数据载体是一个较为重要组成部分&#xff0c;ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是&#xff0c;这些…

从移动切换到电信IP:详细介绍两种方法

在当前的互联网环境中&#xff0c;用户可能会因为各种原因需要切换网络服务提供商&#xff0c;比如从移动切换到电信。这种切换不仅涉及到网络服务的变更&#xff0c;还可能意味着IP地址的改变。那么&#xff0c;移动的怎么切换成电信的IP&#xff1f;下面一起来了解一下吧。 方…

测试内容初步认知

测试流程 了解需求--需求评审--编写测试用例--测试用例评审(产品、开发、测试)--提测测试--bug管理(devops)--集成--集成回归--发布灰度包测试(灰度周期一周)----编写测试报告--发布上线 测试岗位划分 功能测试 负责编写测试用例&#xff0c;执行手动测试&#xff0c;记录并…

麦肯锡:量子传感究竟在何处可以发光发热

量子传感技术已经提供价值&#xff0c;潜在的应用案例可以塑造多个行业。有四种核心技术具有应用前景&#xff1a;固态自旋、中性原子、超导电路和离子阱&#xff0c;它们具有在广泛的物理属性上的传感能力&#xff0c;包括磁场、电场、旋转、温度、重力、时间和压力。选择哪种…

一网通办怎么办?一网统管怎么管?

一网通办怎么办?一网统管怎么管? 下面资源来源于网络,如有侵权请联络删除! **一网通办与一网统管的建设背景、建设情况及建设意义** 一、建设背景随着信息技术的飞速发展,传统的政务服务方式已难以满足人民群众日益增长的需求。各部门信息系统独立运行,导致信息孤岛现象…

Android Service功能使用

在Android开发中&#xff0c;Service是一个在后台长时间运行的组件&#xff0c;不会提供用户界面。它可以用来处理一些需要在后台进行的操作&#xff0c;比如播放音乐、下载文件或进行网络请求。本文将介绍如何在Kotlin中使用Service&#xff0c;并包含具体的代码示例。 什么是…

Python自动化(6)——图像模块

本文所述的方法都是基于前几章的后台点击&#xff0c;因此同样需要绑定窗口句柄。 Python自动化(6)——图像模块 识色 定点比色 def cv2CompareColorOneMatch(self, x, y, hexColor, _similar0, borderNone):startX 0startY 0similar _similar self.colorOffsetif bord…

Spring AOP架构设计解析

一、AOP&#xff08;Aspect Oriented Programming&#xff09;Aspect&#xff1a;方面/层面&#xff1b;Oriented&#xff1a;朝向 1、面向方面&#xff08;切面&#xff09;编程 2、Spring基于代理实现AOP 3、业务作用类似于过滤器&#xff0c;比过滤器强大 二、AOP实现方…

基于Java协同过滤算法的电影推荐系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

Kotlin 中的解构

解构声明是 Kotlin 语言的一个特性&#xff0c;它允许我们从一个数据结构中提取多个变量&#xff0c;这样可以让我们的代码更加简洁易读&#xff0c;同时也提高了代码的可维护性。 在 Kotlin 中&#xff0c;解构可以用于多种数据类型&#xff0c;例如&#xff0c;列表&#xf…

vue3文件目录解析

Vue3 的文件目录结构在构建单页面应用时起到了至关重要的作用&#xff0c;其结构清晰、模块化设计有助于提高代码的可读性、可维护性和可重用性。以下是 Vue3 文件目录的详细解析&#xff1a; 根目录&#xff1a; 包含 Vue3 项目的所有主要文件和文件夹。node_modules&#xf…

几何内核开发-实现自己的NURBS曲线生成API

我去年有一篇帖子&#xff0c;介绍了NURBS曲线生成与显示的实现代码。 https://blog.csdn.net/stonewu/article/details/133387469?spm1001.2014.3001.5501文章浏览阅读323次&#xff0c;点赞4次&#xff0c;收藏2次。搞3D几何内核算法研究&#xff0c;必须学习NURBS样条曲线…

前端的拖拽和缩放(缩放以鼠标为中心)

效果&#xff1a; 拖拽和缩放&#xff08;缩放以鼠标为中心&#xff09; 代码具体实现如下&#xff1a; 但是有几个注意点 &#xff08;1&#xff09;为什么需要设置 transform-origin: 0 0; 缩放时以鼠标为中心进行缩放。这意味着需要手动计算缩放过程中元素的位移&#…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-25使用块的网络VGG

25使用块的网络VGG import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as plt# 定义VGG块 # num_convs: 卷积层的数量 # in_channels: 输入通道的数量 # out_channels: 输出通道的数量 def vgg_block(num_convs, in_channels, out_channel…