#define MS_CLASS "RTC::RTCP::Packet"
#include "RTC/RTCP/Packet.hpp"
#include "Logger.hpp"
#include "RTC/RTCP/Bye.hpp"
#include "RTC/RTCP/Feedback.hpp"
#include "RTC/RTCP/ReceiverReport.hpp"
#include "RTC/RTCP/Sdes.hpp"
#include "RTC/RTCP/SenderReport.hpp"
#include "RTC/RTCP/XR.hpp"
namespace RTC
{
namespace RTCP
{
alignas(4) uint8_t SerializationBuffer[SerializationBufferSize];
const absl::flat_hash_map<Type, std::string> Packet::Type2String =
{
{ Type::SR, "SR" },
{ Type::RR, "RR" },
{ Type::SDES, "SDES" },
{ Type::BYE, "BYE" },
{ Type::APP, "APP" },
{ Type::RTPFB, "RTPFB" },
{ Type::PSFB, "PSFB" },
{ Type::XR, "XR" }
};
Packet* Packet::Parse(const uint8_t* data, size_t len)
{
MS_TRACE();
Packet* first{ nullptr }; Packet* current{ nullptr };
Packet* last{ nullptr };
while (len > 0u)
{
if (!Packet::IsRtcp(data, len))
{
MS_WARN_TAG(rtcp, "data is not a RTCP packet");
return first;
}
auto* header = const_cast<CommonHeader*>(reinterpret_cast<const CommonHeader*>(data));
const size_t packetLen = static_cast<size_t>(ntohs(header->length) + 1) * 4;
if (len < packetLen)
{
MS_WARN_TAG(
rtcp,
"packet length exceeds remaining data [len:%zu, "
"packet len:%zu]",
len,
packetLen);
return first;
}
switch (Type(header->packetType))
{
case Type::SR:
{
current = SenderReportPacket::Parse(data, packetLen);
if (!current)
{
break;
}
if (header->count > 0)
{
Packet* rr = ReceiverReportPacket::Parse(data, packetLen, current->GetSize());
if (!rr)
{
break;
}
current->SetNext(rr);
}
break;
}
case Type::RR:
{
current = ReceiverReportPacket::Parse(data, packetLen);
break;
}
case Type::SDES:
{
current = SdesPacket::Parse(data, packetLen);
break;
}
case Type::BYE:
{
current = ByePacket::Parse(data, packetLen);
break;
}
case Type::APP:
{
current = nullptr;
break;
}
case Type::RTPFB:
{
current = FeedbackRtpPacket::Parse(data, packetLen);
break;
}
case Type::PSFB:
{
current = FeedbackPsPacket::Parse(data, packetLen);
break;
}
case Type::XR:
{
current = ExtendedReportPacket::Parse(data, packetLen);
break;
}
default:
{
MS_WARN_TAG(rtcp, "unknown RTCP packet type [packetType:%" PRIu8 "]", header->packetType);
current = nullptr;
}
}
if (!current)
{
std::string packetType = TypeToString(Type(header->packetType));
if (Type(header->packetType) == Type::PSFB)
{
packetType +=
" " + FeedbackPsPacket::MessageTypeToString(FeedbackPs::MessageType(header->count));
}
else if (Type(header->packetType) == Type::RTPFB)
{
packetType +=
" " + FeedbackRtpPacket::MessageTypeToString(FeedbackRtp::MessageType(header->count));
}
MS_WARN_TAG(rtcp, "error parsing %s Packet", packetType.c_str());
return first;
}
data += packetLen;
len -= packetLen;
if (!first)
{
first = current;
}
else
{
last->SetNext(current);
}
last = current->GetNext() != nullptr ? current->GetNext() : current;
}
return first;
}
const std::string& Packet::TypeToString(Type type)
{
MS_TRACE();
static const std::string Unknown("UNKNOWN");
auto it = Packet::Type2String.find(type);
if (it == Packet::Type2String.end())
{
return Unknown;
}
return it->second;
}
size_t Packet::Serialize(uint8_t* buffer)
{
MS_TRACE();
this->header = reinterpret_cast<CommonHeader*>(buffer);
const size_t length = (GetSize() / 4) - 1;
this->header->version = 2;
this->header->padding = 0;
this->header->count = static_cast<uint8_t>(GetCount());
this->header->packetType = static_cast<uint8_t>(GetType());
this->header->length = htons(length);
return CommonHeaderSize;
}
} }