添加rtcp bye相关代码

This commit is contained in:
xia-chu 2021-04-07 16:45:50 +08:00
parent 79267ae551
commit f374f72312
2 changed files with 182 additions and 4 deletions

View File

@ -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

View File

@ -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)