mediasoup源码分析(三)channel创建及信令交互

mediasoup源码分析--channel创建及信令交互

    • 概述
    • 跨职能图
    • 业务流程图
    • 代码剖析

概述

在golang实现mediasoup的tcp服务及channel通道一文中,已经介绍过信令服务中tcp和channel的创建,本文主要讲解c++中mediasoup的channel创建,以及信令服务和mediasoup服务如何交互

跨职能图

c92bb199ca71184775fa8bea149e201.png

业务流程图

image.png

数据发送有两种方式:
应用层发送的request最后被封装在Requst对象中,其中包含着"id",因为Request对象中包含着Channel::UnixStreamSocket对象,所以可以直接调用Request::Accept()将处理后的结果告诉应用层进程。
Worker进程也可以主动给应用层进程发送消息,通过Notifier::Emit()即可以给应用进程发送消息,Notifier类中有Channel::UnixStreamSocket,所以直接调用Channel::UnixStreamSocket::Send()就可以发送消息。Notifier类内部的数据成员和函数成员都是静态的,所以在任意位置可以直接通过Channel::Notifier::Emit()函数发送消息。

代码剖析

1.channel创建

int main(int argc, char* argv[])
{// Ensure we are called by our Node library.if (argc == 1){std::cerr << "ERROR: you don't seem to be my real father" << std::endl;std::_Exit(EXIT_FAILURE);}std::string id = std::string(argv[1]);std::string ip = std::string(argv[2]);int port = atoi(argv[3]);int iperfPort = atoi(argv[4]);// Initialize libuv stuff (we need it for the Channel).DepLibUV::ClassInit();//..........省略部分代码..............// Set the Channel socket (this will be handled and deleted by the Worker).printf("new Channel to %s:%d\n",ip.c_str(),port);auto* channel = new Channel::UnixStreamSocket(ip,port);//..........省略部分代码..............try{// Run the Worker.Worker worker(id,channel);// Worker ended.destroy();exitSuccess();}catch (const MediaSoupError& error){MS_ERROR_STD("failure exit: %s", error.what());destroy();exitWithError();}
}

UnixStreamSocket构造函数

UnixStreamSocket::UnixStreamSocket(const std::string& ip,int port) : ::UnixStreamSocket::UnixStreamSocket(ip,port, MaxSize)
{MS_TRACE_STD();// Create the JSON reader.{Json::CharReaderBuilder builder;Json::Value settings = Json::nullValue;Json::Value invalidSettings;builder.strictMode(&settings);MS_ASSERT(builder.validate(&invalidSettings), "invalid Json::CharReaderBuilder");this->jsonReader = builder.newCharReader();}// Create the JSON writer.{Json::StreamWriterBuilder builder;Json::Value invalidSettings;builder["commentStyle"]            = "None";builder["indentation"]             = "";builder["enableYAMLCompatibility"] = false;builder["dropNullPlaceholders"]    = false;MS_ASSERT(builder.validate(&invalidSettings), "invalid Json::StreamWriterBuilder");this->jsonWriter = builder.newStreamWriter();}
}

跳转到handles\UnixStreamSocket.cpp下

UnixStreamSocket::UnixStreamSocket( const std::string& ip,int port,size_t bufferSize) : bufferSize(bufferSize)
{printf("::UnixStreamSocket::UnixStreamSocket\n");MS_TRACE_STD();int err;this->uvHandle       = new uv_tcp_t;this->uvHandle->data = (void*)this;err = uv_tcp_init(DepLibUV::GetLoop(), this->uvHandle);if (err != 0){delete this->uvHandle;this->uvHandle = nullptr;printf("uv_tcp_init() failed: %s\n", uv_strerror(err));MS_THROW_ERROR_STD("uv_tcp_init() failed: %s", uv_strerror(err));}struct sockaddr_in dest;uv_ip4_addr(ip.c_str(), port, &dest);this->connect = new uv_connect_t;printf("will connect to %s:%d\n",ip.c_str(),port);err = uv_tcp_connect(this->connect, this->uvHandle, (const struct sockaddr*)&dest, onConnect);if (err != 0){delete this->uvHandle;this->uvHandle = nullptr;printf("uv_tcp_connect() failed: %s\n", uv_strerror(err));MS_THROW_ERROR_STD("uv_tcp_connect() failed: %s", uv_strerror(err));}// Start reading.err = uv_read_start(reinterpret_cast<uv_stream_t*>(this->uvHandle),static_cast<uv_alloc_cb>(onAlloc),static_cast<uv_read_cb>(onRead));if (err != 0){uv_close(reinterpret_cast<uv_handle_t*>(this->uvHandle), static_cast<uv_close_cb>(onClose));MS_THROW_ERROR_STD("uv_read_start() failed: %s", uv_strerror(err));}// NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb().
}

代码中的uv_read_start接口中onRead回调

    err = uv_read_start(reinterpret_cast<uv_stream_t*>(this->uvHandle),static_cast<uv_alloc_cb>(onAlloc),static_cast<uv_read_cb>(onRead));

跳转到onRead中

inline static void onRead(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
{auto* socket = static_cast<UnixStreamSocket*>(handle->data);if (socket == nullptr)return;socket->OnUvRead(nread, buf);
}

OnUvRead中调用UserOnUnixStreamRead

	void UnixStreamSocket::UserOnUnixStreamRead(){MS_TRACE_STD();// Be ready to parse more than a single message in a single TCP chunk.while (true){if (IsClosed())return;size_t readLen  = this->bufferDataLen - this->msgStart;char* jsonStart = nullptr;size_t jsonLen;int nsRet = netstring_read(reinterpret_cast<char*>(this->buffer + this->msgStart), readLen, &jsonStart, &jsonLen);//.............省略部分代码..............// If here it means that jsonStart points to the beginning of a JSON string// with jsonLen bytes length, so recalculate readLen.readLen =reinterpret_cast<const uint8_t*>(jsonStart) - (this->buffer + this->msgStart) + jsonLen + 1;Json::Value json;std::string jsonParseError;if (this->jsonReader->parse((const char*)jsonStart, (const char*)jsonStart + jsonLen, &json, &jsonParseError)){Channel::Request* request = nullptr;try{request = new Channel::Request(this, json);}catch (const MediaSoupError& error){MS_ERROR_STD("discarding wrong Channel request");}if (request != nullptr){// Notify the listener.this->listener->OnChannelRequest(this, request);// Delete the Request.delete request;}//.............省略部分代码.................}}

channel创建完成,至此,跳转到worker.cpp中的OnChannelRequest接口。mediasoup监听channel信令并根据request->methodId分类处理
根据request->methodId,分别执行不同的业务
request->methodId有如下分类

	std::unordered_map<std::string, Request::MethodId> Request::string2MethodId ={{ "worker.dump",                       Request::MethodId::WORKER_DUMP                          },{ "worker.updateSettings",             Request::MethodId::WORKER_UPDATE_SETTINGS               },{ "worker.createRouter",               Request::MethodId::WORKER_CREATE_ROUTER                 },{ "router.close",                      Request::MethodId::ROUTER_CLOSE                         },{ "router.dump",                       Request::MethodId::ROUTER_DUMP                          },{ "router.createWebRtcTransport",      Request::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT       },{ "router.createPlainRtpTransport",    Request::MethodId::ROUTER_CREATE_PLAIN_RTP_TRANSPORT    },{ "router.createProducer",             Request::MethodId::ROUTER_CREATE_PRODUCER               },{ "router.createConsumer",             Request::MethodId::ROUTER_CREATE_CONSUMER               },{ "router.setAudioLevelsEvent",        Request::MethodId::ROUTER_SET_AUDIO_LEVELS_EVENT        },{ "transport.close",                   Request::MethodId::TRANSPORT_CLOSE                      },{ "transport.dump",                    Request::MethodId::TRANSPORT_DUMP                       },{ "transport.getStats",                Request::MethodId::TRANSPORT_GET_STATS                  },{ "transport.setRemoteDtlsParameters", Request::MethodId::TRANSPORT_SET_REMOTE_DTLS_PARAMETERS },{ "transport.setRemoteParameters",     Request::MethodId::TRANSPORT_SET_REMOTE_PARAMETERS      },{ "transport.setMaxBitrate",           Request::MethodId::TRANSPORT_SET_MAX_BITRATE            },{ "transport.changeUfragPwd",          Request::MethodId::TRANSPORT_CHANGE_UFRAG_PWD           },{ "transport.startMirroring",          Request::MethodId::TRANSPORT_START_MIRRORING            },{ "transport.stopMirroring",           Request::MethodId::TRANSPORT_STOP_MIRRORING             },{ "producer.close",                    Request::MethodId::PRODUCER_CLOSE                       },{ "producer.dump",                     Request::MethodId::PRODUCER_DUMP                        },{ "producer.getStats",                 Request::MethodId::PRODUCER_GET_STATS                   },{ "producer.pause",                    Request::MethodId::PRODUCER_PAUSE                       },{ "producer.resume" ,                  Request::MethodId::PRODUCER_RESUME                      },{ "producer.setPreferredProfile",      Request::MethodId::PRODUCER_SET_PREFERRED_PROFILE       },{ "consumer.close",                    Request::MethodId::CONSUMER_CLOSE                       },{ "consumer.dump",                     Request::MethodId::CONSUMER_DUMP                        },{ "consumer.getStats",                 Request::MethodId::CONSUMER_GET_STATS                   },{ "consumer.enable",                   Request::MethodId::CONSUMER_ENABLE                      },{ "consumer.pause",                    Request::MethodId::CONSUMER_PAUSE                       },{ "consumer.resume",                   Request::MethodId::CONSUMER_RESUME                      },{ "consumer.setPreferredProfile",      Request::MethodId::CONSUMER_SET_PREFERRED_PROFILE       },{ "consumer.setEncodingPreferences",   Request::MethodId::CONSUMER_SET_ENCODING_PREFERENCES    },{ "consumer.requestKeyFrame",          Request::MethodId::CONSUMER_REQUEST_KEY_FRAME           }};

下一章节介绍mediasoup如何将信令返回值及其他通知信息推送到信令服务,敬请期待!

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

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

相关文章

HTML|02HTML标签

HTML标签的语义化 语义化就是&#xff1a;标签的含义HTML标签 排版标签标题标签h<h1></h1> 标签有h1-h6&#xff0c;没有h7段落标签p<p></p>水平线标签hr<hr /> 单标记换行标签br<br />div span标签用来布局的 文本格式化标签<b>&…

编程用什么电脑不卡的:深度解析与推荐

编程用什么电脑不卡的&#xff1a;深度解析与推荐 在编程的世界里&#xff0c;一台流畅不卡的电脑无疑是每个开发者的得力助手。然而&#xff0c;面对市场上琳琅满目的电脑品牌和型号&#xff0c;如何选择一台适合编程的电脑却成为了一个令人困惑的问题。本文将从四个方面、五…

如何避免接口重复请求(axios推荐使用AbortController)

前言&#xff1a; 我们日常开发中&#xff0c;经常会遇到点击一个按钮或者进行搜索时&#xff0c;请求接口的需求。 如果我们不做优化&#xff0c;连续点击按钮或者进行搜索&#xff0c;接口会重复请求。 以axios为例&#xff0c;我们一般以以下几种方法为主&#xff1a; 1…

「C系列」C 头文件及引发方法/操作

文章目录 一、C 头文件二、引用头文件的方法1. 使用尖括号 < > 引用标准库头文件2. 使用双引号 " " 引用用户自定义头文件 三、引用头文件的操作四、相关链接 一、C 头文件 在C语言中&#xff0c;头文件&#xff08;Header Files&#xff09;通常用于包含函数…

bashrc和profile区别

作用与目的&#xff1a; .bashrc&#xff1a;这个文件主要用于配置和自定义用户的终端环境和行为。每次启动新的终端时&#xff0c;.bashrc文件都会被执行&#xff0c;加载用户设置的环境变量、别名、函数等。这使得用户能够根据自己的喜好和需求来定制终端的行为和外观。profi…

如何通过编程获取桌面分辨率、操作像素点颜色、保存位图和JPG格式图片,以及图片数据的处理和存储方式

本节课在线学习视频&#xff08;网盘地址&#xff0c;保存后即可免费观看&#xff09;&#xff1a; ​​https://pan.quark.cn/s/c474d087e76f​​ 在图形编程中&#xff0c;获取桌面分辨率、操作像素点颜色、保存和处理图片数据是常见任务。本文将介绍如何通过编程实现这些操…

沃尔玛验厂报告的颜色分级

Walmart沃尔玛每年评估约 14000 份第三方社会责任验厂报告。沃尔玛验厂总的原则是&#xff0c;工厂从RBA、BSCI、SA8000等11个第三方社会责任验厂标准中&#xff0c;自由选择其中一个来进行验厂&#xff0c;验厂结束以后&#xff0c;把验厂报告提交给沃尔玛&#xff1b;然后沃尔…

【Pmac】PMAC QT联合开发中各种可能遇到的坑

目录 1. 错误 C2027 使用了未定义类型“PCOMMSERVERLib::DEVUPLOAD”2. 输入了正确的pmac的ip地址&#xff0c;没有显示可选的pmac设备3. Pmac DTC-28B无读数 使用QT编写PMAC上位机程序时&#xff0c;利用QT中的dump工具可以将pcommserver.exe转化为pcommserverlib.h和pcommser…

Java并发编程之线程基础

线程通知与等待 Java中的Object类是所有类的父类&#xff0c;鉴于继承机制&#xff0c;Java把所有类都需要的方法放到了Object类里面&#xff0c;其中就包括了线程的通知和等待。 wait以及notify 当一个线程调用一个共享变量的wait()方法时&#xff0c;该调用线程会被阻塞挂…

mysql数据库迁移步骤

备份数据库&#xff1a; mysqldump -u [username] -p[password] [database_name] > [database_name].sql 注意&#xff1a;“-u”与用户名之间有一个空格&#xff0c;而“-p”与密码之间没有空格 恢复数据库&#xff1a; mysql -u [username] -p[password] [database_name]…

调度算法-内存页面置换算法

缺⻚异常&#xff08;缺⻚中断&#xff09; 与⼀般中断的主要区别在于&#xff1a; 缺⻚中断在指令执⾏「期间」产⽣和处理中断信号&#xff0c;⽽⼀般中断在⼀条指令执⾏「完成」后检查和处理中断信号。缺⻚中断返回到该指令的开始重新执⾏「该指令」&#xff0c;⽽⼀般中断返…

【HarmonyOS】鸿蒙应用模块化实现

【HarmonyOS】鸿蒙应用模块化实现 一、Module的概念 Module是HarmonyOS应用的基本功能单元&#xff0c;包含了源代码、资源文件、第三方库及应用清单文件&#xff0c;每一个Module都可以独立进行编译和运行。一个HarmonyOS应用通常会包含一个或多个Module&#xff0c;因此&am…

简单处理字符串——6.14山大软院项目实训1

对于直接输出服务器返回的json到Debug&#xff0c;发现他还包含json的结构&#xff0c;但是不想调试json的返回结构&#xff0c;可以使用简单地处理字符串的方法&#xff0c;而不引入额外的库或复杂的JSON解析&#xff0c;但是这个解决方式是暂时的是投机取巧的&#xff0c;正确…

我主编的电子技术实验手册(08)——串联电阻分压

本专栏是笔者主编教材&#xff08;图0所示&#xff09;的电子版&#xff0c;依托简易的元器件和仪表安排了30多个实验&#xff0c;主要面向经费不太充足的中高职院校。每个实验都安排了必不可少的【预习知识】&#xff0c;精心设计的【实验步骤】&#xff0c;全面丰富的【思考习…

单例及工厂模式适合的场景

工厂模式适合以下场景&#xff1a; 1. **对象的创建与使用分离**&#xff1a;工厂模式可以将对象的创建和使用分离&#xff0c;客户端只需要通过工厂来创建对象&#xff0c;而无需关心对象的具体实现细节。 2. **对象的类型不容易预先确定**&#xff1a;当需要根据条件动态创…

Golang——gRPC认证和拦截器

一. OpenSSL 1.1 介绍 OpenSSL是一个开放源代码的软件库包&#xff0c;用于支持网络通讯过程中的加密。这个库提供的功能包含了SSL和TLS协议的实现&#xff0c;并可用于生成密钥、证书、进行密码运算等。 其组成主要包括一下三个组件&#xff1a; openssl&#xff1a;多用途的命…

有效招聘营销策略的六个组成部分

任何想吸引更多人购买其产品的公司都必须投资于市场营销。然而&#xff0c;当涉及到让更多的人了解公司的工作时&#xff0c;许多有效的营销活动可能不是招聘团队的首要考虑因素。为了超越招聘委员会上的“发布祈祷”策略&#xff0c;有必要包括有效招聘营销策略的所有组成部分…

车联网车载设备

智能网联主要通过OBU&#xff08;On Board Unit,车载单元&#xff09;实现。OBU是一种安装在车辆上用于实现V2X通信的硬件设备&#xff0c;可实现和其他车辆OBU&#xff08;PC5&#xff09;、路侧RSU&#xff08;PC5&#xff09;、行人&#xff08;PC5&#xff09;和V2X平台&am…

基于Redis实现共享session登录

搭配食用&#xff1a;Redis&#xff08;基础篇&#xff09;-CSDN博客 项目实现前的 Mysql中的表&#xff1a; 表说明tb_user用户表tb_user_info用户详情表tb_shop商户信息表tb_shop_type商户类型表tb_blog用户日记表&#xff08;达人探店日记)tb_follow用户关注表tb_voucher优…

vlcplayer for android 源码编译log打印

vlcplayer for android 源码编译log打印 这篇文章记录了vlcplayer for android 开源库中libvlc.so中添加log打印的方法。 主要针对libvlc源码中msg_Info/msg_Err/msg_Warn/msg_Dbg 函数打印输出到Android log中。修改如下&#xff1a; vlc-android/libvlcjni/vlc/include/vlc…