mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 20:47:08 +08:00
添加rtcp bye相关代码
This commit is contained in:
parent
79267ae551
commit
f374f72312
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "Rtcp.h"
|
#include "Rtcp.h"
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
|
|
||||||
@ -87,10 +88,20 @@ string RtcpHeader::dumpString() const {
|
|||||||
RtcpPli *rtcp = (RtcpPli *)this;
|
RtcpPli *rtcp = (RtcpPli *)this;
|
||||||
return rtcp->dumpString();
|
return rtcp->dumpString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case RtcpType::RTCP_BYE: {
|
||||||
|
RtcpBye *rtcp = (RtcpBye *)this;
|
||||||
|
return rtcp->dumpString();
|
||||||
|
}
|
||||||
|
|
||||||
default: return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), length << 2);
|
default: return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), length << 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t RtcpHeader::getSize() const {
|
||||||
|
return (1 + length) << 2;
|
||||||
|
}
|
||||||
|
|
||||||
void RtcpHeader::net2Host(size_t len){
|
void RtcpHeader::net2Host(size_t len){
|
||||||
switch ((RtcpType)pt) {
|
switch ((RtcpType)pt) {
|
||||||
case RtcpType::RTCP_SR: {
|
case RtcpType::RTCP_SR: {
|
||||||
@ -116,6 +127,12 @@ void RtcpHeader::net2Host(size_t len){
|
|||||||
pli->net2Host(len);
|
pli->net2Host(len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case RtcpType::RTCP_BYE: {
|
||||||
|
RtcpBye *bye = (RtcpBye *)this;
|
||||||
|
bye->net2Host(len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt));
|
default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,6 +144,10 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len){
|
|||||||
while (remain > (ssize_t) sizeof(RtcpHeader)) {
|
while (remain > (ssize_t) sizeof(RtcpHeader)) {
|
||||||
RtcpHeader *rtcp = (RtcpHeader *) ptr;
|
RtcpHeader *rtcp = (RtcpHeader *) ptr;
|
||||||
auto rtcp_len = (1 + ntohs(rtcp->length)) << 2;
|
auto rtcp_len = (1 + ntohs(rtcp->length)) << 2;
|
||||||
|
if (remain < rtcp_len) {
|
||||||
|
WarnL << "非法的rtcp包,声明的长度超过实际数据长度";
|
||||||
|
break;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
rtcp->net2Host(rtcp_len);
|
rtcp->net2Host(rtcp_len);
|
||||||
ret.emplace_back(rtcp);
|
ret.emplace_back(rtcp);
|
||||||
@ -144,7 +165,7 @@ class BufferRtcp : public Buffer {
|
|||||||
public:
|
public:
|
||||||
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) {
|
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) {
|
||||||
_rtcp = std::move(rtcp);
|
_rtcp = std::move(rtcp);
|
||||||
_size = (htons(_rtcp->length) + 1) << 2;
|
_size = (ntohs(_rtcp->length) + 1) << 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BufferRtcp() override {}
|
~BufferRtcp() override {}
|
||||||
@ -440,4 +461,97 @@ void RtcpPli::net2Host(size_t size) {
|
|||||||
ssrc_media = ntohl(ssrc_media);
|
ssrc_media = ntohl(ssrc_media);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::shared_ptr<RtcpBye> RtcpBye::create(const std::initializer_list<uint32_t> &ssrcs, const string &reason) {
|
||||||
|
assert(reason.size() <= 0xFF);
|
||||||
|
auto bytes = alignSize(sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size() + 1 + reason.size());
|
||||||
|
auto ptr = (RtcpBye *) new char[bytes];
|
||||||
|
setupHeader(ptr, RtcpType::RTCP_BYE, ssrcs.size(), bytes);
|
||||||
|
|
||||||
|
auto *ssrc_ptr = &(((RtcpBye *) ptr)->ssrc);
|
||||||
|
for (auto ssrc : ssrcs) {
|
||||||
|
*ssrc_ptr = htonl(ssrc);
|
||||||
|
++ssrc_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reason.empty()) {
|
||||||
|
uint8_t *reason_len_ptr = (uint8_t *) ptr + sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size();
|
||||||
|
*reason_len_ptr = reason.size() & 0xFF;
|
||||||
|
memcpy(reason_len_ptr + 1, reason.data(), *reason_len_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::shared_ptr<RtcpBye>(ptr, [](RtcpBye *ptr) {
|
||||||
|
delete[] (char *) ptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<uint32_t *> RtcpBye::getSSRC() {
|
||||||
|
vector<uint32_t *> ret;
|
||||||
|
uint32_t *ssrc_ptr = &ssrc;
|
||||||
|
for (size_t i = 0; i < report_count; ++i) {
|
||||||
|
ret.emplace_back(ssrc_ptr);
|
||||||
|
ssrc_ptr += 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
string RtcpBye::getReason() const {
|
||||||
|
auto *reason_len_ptr = &reason_len + sizeof(ssrc) * (report_count - 1);
|
||||||
|
if (reason_len_ptr + 1 >= (uint8_t *) this + getSize()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return string((char *) reason_len_ptr + 1, *reason_len_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
string RtcpBye::dumpString() const {
|
||||||
|
_StrPrinter printer;
|
||||||
|
printer << RtcpHeader::dumpHeader();
|
||||||
|
for(auto ssrc : ((RtcpBye *)this)->getSSRC()) {
|
||||||
|
printer << "ssrc:" << *ssrc << "\r\n";
|
||||||
|
}
|
||||||
|
printer << "reason:" << getReason();
|
||||||
|
return std::move(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtcpBye::net2Host(size_t size) {
|
||||||
|
static const size_t kMinSize = sizeof(RtcpHeader);
|
||||||
|
CHECK_MIN_SIZE(size, kMinSize);
|
||||||
|
RtcpHeader::net2Host();
|
||||||
|
|
||||||
|
uint32_t *ssrc_ptr = &ssrc;
|
||||||
|
size_t offset = kMinSize;
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < report_count && offset + sizeof(ssrc) <= size; ++i) {
|
||||||
|
*ssrc_ptr = ntohl(*ssrc_ptr);
|
||||||
|
ssrc_ptr += 1;
|
||||||
|
offset += sizeof(ssrc);
|
||||||
|
}
|
||||||
|
//修正ssrc个数
|
||||||
|
CHECK_LENGTH(size, i);
|
||||||
|
|
||||||
|
if (offset < size) {
|
||||||
|
uint8_t *reason_len_ptr = &reason_len + sizeof(ssrc) * (report_count - 1);
|
||||||
|
if (reason_len_ptr + 1 + *reason_len_ptr > (uint8_t *) this + size) {
|
||||||
|
WarnL << "invalid rtcp bye reason length";
|
||||||
|
//修正reason_len长度
|
||||||
|
*reason_len_ptr = ((uint8_t *) this + size - reason_len_ptr - 1) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
|
||||||
|
static toolkit::onceToken token([](){
|
||||||
|
auto bye = RtcpBye::create({1,2,3,4,5,6}, "this is a bye reason");
|
||||||
|
auto buffer = RtcpHeader::toBuffer(bye);
|
||||||
|
|
||||||
|
auto rtcps = RtcpHeader::loadFromBytes(buffer->data(), buffer->size());
|
||||||
|
for(auto rtcp : rtcps){
|
||||||
|
std::cout << rtcp->dumpString() << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
@ -124,6 +124,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
string dumpString() const;
|
string dumpString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据length字段获取rtcp总长度
|
||||||
|
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||||
|
*/
|
||||||
|
size_t getSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* 网络字节序转换为主机字节序
|
* 网络字节序转换为主机字节序
|
||||||
@ -465,9 +471,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* 创建SDES包,只赋值了RtcpHeader以及SdesItem对象的length和text部分
|
* 创建pli包
|
||||||
* @param item_text SdesItem列表,只赋值length和text部分
|
|
||||||
* @return SDES包
|
|
||||||
*/
|
*/
|
||||||
static std::shared_ptr<RtcpPli> create();
|
static std::shared_ptr<RtcpPli> create();
|
||||||
|
|
||||||
@ -485,6 +489,66 @@ private:
|
|||||||
void net2Host(size_t size);
|
void net2Host(size_t size);
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
//BYE
|
||||||
|
/*
|
||||||
|
0 1 2 3
|
||||||
|
0 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
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|V=2|P| SC | PT=BYE=203 | length |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| SSRC/CSRC |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
: ... :
|
||||||
|
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||||
|
(opt) | length | reason for leaving ...
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RtcpBye : public RtcpHeader {
|
||||||
|
public:
|
||||||
|
friend class RtcpHeader;
|
||||||
|
/* 变长,根据count决定有多少个ssrc */
|
||||||
|
uint32_t ssrc;
|
||||||
|
|
||||||
|
/** 中间可能有若干个 ssrc **/
|
||||||
|
|
||||||
|
/* 可选 */
|
||||||
|
uint8_t reason_len;
|
||||||
|
char reason;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 创建bye包
|
||||||
|
* @param ssrc ssrc列表
|
||||||
|
* @param reason 原因
|
||||||
|
* @return rtcp bye包
|
||||||
|
*/
|
||||||
|
static std::shared_ptr<RtcpBye> create(const std::initializer_list<uint32_t> &ssrc, const string &reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ssrc列表
|
||||||
|
*/
|
||||||
|
vector<uint32_t *> getSSRC();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取原因
|
||||||
|
*/
|
||||||
|
string getReason() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 打印字段详情
|
||||||
|
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||||
|
*/
|
||||||
|
string dumpString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络字节序转换为主机字节序
|
||||||
|
* @param size 字节长度,防止内存越界
|
||||||
|
*/
|
||||||
|
void net2Host(size_t size);
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
|
Loading…
Reference in New Issue
Block a user