sdp完整性检查,与忽略大小写拼写

This commit is contained in:
ziyue 2021-03-30 09:53:58 +08:00
parent a1b2aa9abb
commit daef7051ad
3 changed files with 90 additions and 74 deletions

View File

@ -12,19 +12,20 @@
#define ZLMEDIAKIT_ASSERT_H #define ZLMEDIAKIT_ASSERT_H
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void Assert_Throw(int failed, const char *exp, const char *func, const char *file, int line);
#ifdef __cplusplus
}
#endif
#ifndef NDEBUG #ifndef NDEBUG
#ifdef assert #ifdef assert
#undef assert #undef assert
#endif//assert #endif//assert
#ifdef __cplusplus
extern "C" {
#endif
extern void Assert_Throw(int failed, const char *exp, const char *func, const char *file, int line);
#ifdef __cplusplus
}
#endif
#define assert(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__); #define assert(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__);
#else #else
#define assert(e) ((void)0) #define assert(e) ((void)0)

View File

@ -3,10 +3,14 @@
// //
#include "Sdp.h" #include "Sdp.h"
#include "assert.h"
#include "Common/Parser.h"
#include <inttypes.h> #include <inttypes.h>
#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__);
using onCreateSdpItem = function<SdpItem::Ptr(const string &key, const string &value)>; using onCreateSdpItem = function<SdpItem::Ptr(const string &key, const string &value)>;
static unordered_map<string, onCreateSdpItem> sdpItemCreator; static map<string, onCreateSdpItem, StrCaseCompare> sdpItemCreator;
template <typename Item> template <typename Item>
void registerSdpItem(){ void registerSdpItem(){
@ -89,17 +93,15 @@ static bool registerAllItem(){
return true; return true;
} }
TrackType getTrackType(const string &str){ static map<string, TrackType, StrCaseCompare> track_str_map = {
if (str == "video") { {"video", TrackVideo},
return TrackVideo; {"audio", TrackAudio},
} {"application", TrackApplication}
if (str == "audio") { };
return TrackAudio;
} TrackType getTrackType(const string &str) {
if (str == "application") { auto it = track_str_map.find(str);
return TrackApplication; return it == track_str_map.end() ? TrackInvalid : it->second;
}
return TrackInvalid;
} }
const char* getTrackString(TrackType type){ const char* getTrackString(TrackType type){
@ -111,17 +113,15 @@ const char* getTrackString(TrackType type){
} }
} }
DtlsRole getDtlsRole(const string &str){ static map<string, DtlsRole, StrCaseCompare> dtls_role_map = {
if (str == "active") { {"active", DtlsRole::active},
return DtlsRole::active; {"passive", DtlsRole::passive},
} {"actpass", DtlsRole::actpass}
if (str == "passive") { };
return DtlsRole::passive;
} DtlsRole getDtlsRole(const string &str) {
if (str == "actpass") { auto it = dtls_role_map.find(str);
return DtlsRole::actpass; return it == dtls_role_map.end() ? DtlsRole::invalid : it->second;
}
return DtlsRole::invalid;
} }
const char* getDtlsRoleString(DtlsRole role){ const char* getDtlsRoleString(DtlsRole role){
@ -133,20 +133,16 @@ const char* getDtlsRoleString(DtlsRole role){
} }
} }
RtpDirection getRtpDirection(const string &str){ static map<string, RtpDirection, StrCaseCompare> direction_map = {
if (str == "sendonly") { {"sendonly", RtpDirection::sendonly},
return RtpDirection::sendonly; {"recvonly", RtpDirection::recvonly},
} {"sendrecv", RtpDirection::sendrecv},
if (str == "recvonly") { {"inactive", RtpDirection::inactive}
return RtpDirection::recvonly; };
}
if (str == "sendrecv") { RtpDirection getRtpDirection(const string &str) {
return RtpDirection::sendrecv; auto it = direction_map.find(str);
} return it == direction_map.end() ? RtpDirection::invalid : it->second;
if (str == "inactive") {
return RtpDirection::inactive;
}
return RtpDirection::invalid;
} }
const char* getRtpDirectionString(RtpDirection val){ const char* getRtpDirectionString(RtpDirection val){
@ -182,14 +178,15 @@ RtpDirection RtcSdpBase::getDirection() const{
return RtpDirection::invalid; return RtpDirection::invalid;
} }
SdpItem::Ptr RtcSdpBase::getItem(char key, const char *attr_key) const { SdpItem::Ptr RtcSdpBase::getItem(char key_c, const char *attr_key) const {
for (auto item : items) { for (auto item : items) {
if (item->getKey()[0] == key) { string key(1, key_c);
if (strcasecmp(item->getKey(), key.data()) == 0) {
if (!attr_key) { if (!attr_key) {
return item; return item;
} }
auto attr = dynamic_pointer_cast<SdpAttr>(item); auto attr = dynamic_pointer_cast<SdpAttr>(item);
if (attr && !strcmp(attr->detail->getKey() , attr_key)) { if (attr && !strcasecmp(attr->detail->getKey() , attr_key)) {
return attr->detail; return attr->detail;
} }
} }
@ -884,6 +881,7 @@ void RtcSession::loadFrom(const string &str) {
session_info = sdp.getSessionInfo(); session_info = sdp.getSessionInfo();
connection = sdp.getConnection(); connection = sdp.getConnection();
bandwidth = sdp.getBandwidth(); bandwidth = sdp.getBandwidth();
time = sdp.getSessionTime();
msid_semantic = sdp.getItemClass<SdpAttrMsidSemantic>('a', "msid-semantic"); msid_semantic = sdp.getItemClass<SdpAttrMsidSemantic>('a', "msid-semantic");
for (auto &media : sdp.medias) { for (auto &media : sdp.medias) {
auto mline = media.getItemClass<SdpMedia>('m'); auto mline = media.getItemClass<SdpMedia>('m');
@ -1036,7 +1034,7 @@ void RtcSession::loadFrom(const string &str) {
string RtcCodecPlan::getFmtp(const char *key) const{ string RtcCodecPlan::getFmtp(const char *key) const{
for (auto &item : fmtp) { for (auto &item : fmtp) {
if (item.first == key) { if (strcasecmp(item.first.data(), key) == 0) {
return item.second; return item.second;
} }
} }
@ -1052,34 +1050,41 @@ const RtcCodecPlan *RtcMedia::getPlan(uint8_t pt) const{
return nullptr; return nullptr;
} }
void RtcMedia::checkValid() const{ const RtcCodecPlan *RtcMedia::getPlan(const char *codec) const{
switch (direction) {
case RtpDirection::sendonly:
case RtpDirection::sendrecv: {
if (rtp_ssrc.empty()) {
throw std::invalid_argument("发送rtp但是未指定rtp ssrc");
}
break;
}
default: break;
}
for (auto &item : plan) { for (auto &item : plan) {
if (item.codec == "rtx") { if (strcasecmp(item.codec.data(), codec) == 0) {
if (rtx_ssrc.empty()) { return &item;
throw std::invalid_argument("指定开启rtx但是未指定rtx ssrc");
}
auto apt = atoi(item.getFmtp("apt").data());
if (!getPlan(apt)) {
throw std::invalid_argument("找不到rtx关联的plan信息");
}
} }
} }
//todo 校验更多信息 return nullptr;
}
void RtcMedia::checkValid() const{
CHECK(type != TrackInvalid);
CHECK(!mid.empty());
CHECK(!proto.empty());
CHECK(direction != RtpDirection::invalid || type == TrackApplication);
CHECK(!plan.empty() || type == TrackApplication );
bool send_rtp = (direction == RtpDirection::sendonly || direction == RtpDirection::sendrecv);
CHECK(!rtp_ssrc.empty() || !send_rtp);
auto rtx_plan = getPlan("rtx");
if (rtx_plan) {
//开启rtx后必须指定rtx_ssrc
CHECK(!rtx_ssrc.empty() || !send_rtp);
auto apt = atoi(rtx_plan->getFmtp("apt").data());
//开启rtx后必须指定其关联的其他的plan
CHECK(getPlan(apt));
}
} }
void RtcSession::checkValid() const{ void RtcSession::checkValid() const{
CHECK(version == 0);
CHECK(!origin.empty());
CHECK(!session_name.empty());
CHECK(!msid_semantic.empty());
CHECK(!media.empty());
CHECK(group.mids.size() <= media.size());
for (auto &item : media) { for (auto &item : media) {
item.checkValid(); item.checkValid();
} }
//todo 校验更多信息
} }

View File

@ -134,6 +134,10 @@ public:
void parse(const string &str) override; void parse(const string &str) override;
string toString() const override; string toString() const override;
const char* getKey() const override { return "o";} const char* getKey() const override { return "o";}
bool empty() const {
return username.empty() || session_id.empty() || session_version.empty()
|| nettype.empty() || addrtype.empty() || address.empty();
}
}; };
class SdpConnection : public SdpItem { class SdpConnection : public SdpItem {
@ -233,6 +237,9 @@ public:
void parse(const string &str) override; void parse(const string &str) override;
string toString() const override; string toString() const override;
const char* getKey() const override { return "msid-semantic";} const char* getKey() const override { return "msid-semantic";}
bool empty() const {
return msid.empty();
}
}; };
class SdpAttrRtcp : public SdpItem { class SdpAttrRtcp : public SdpItem {
@ -467,10 +474,11 @@ public:
SdpItem::Ptr getItem(char key, const char *attr_key = nullptr) const; SdpItem::Ptr getItem(char key, const char *attr_key = nullptr) const;
template<typename cls> template<typename cls>
vector<cls> getAllItem(char key, const char *attr_key = nullptr) const { vector<cls> getAllItem(char key_c, const char *attr_key = nullptr) const {
vector<cls> ret; vector<cls> ret;
for (auto item : items) { for (auto item : items) {
if (item->getKey()[0] == key) { string key(1, key_c);
if (strcasecmp(item->getKey(), key.data()) == 0) {
if (!attr_key) { if (!attr_key) {
auto c = dynamic_pointer_cast<cls>(item); auto c = dynamic_pointer_cast<cls>(item);
if (c) { if (c) {
@ -478,7 +486,7 @@ public:
} }
} else { } else {
auto attr = dynamic_pointer_cast<SdpAttr>(item); auto attr = dynamic_pointer_cast<SdpAttr>(item);
if (attr && !strcmp(attr->detail->getKey(), attr_key)) { if (attr && !strcasecmp(attr->detail->getKey(), attr_key)) {
auto c = dynamic_pointer_cast<cls>(attr->detail); auto c = dynamic_pointer_cast<cls>(attr->detail);
if (c) { if (c) {
ret.emplace_back(*c); ret.emplace_back(*c);
@ -518,7 +526,7 @@ public:
string mslabel; string mslabel;
string label; string label;
bool empty() const {return ssrc == 0;} bool empty() const {return ssrc == 0 && cname.empty();}
}; };
//rtc传输编码方案 //rtc传输编码方案
@ -582,6 +590,7 @@ public:
void checkValid() const; void checkValid() const;
const RtcCodecPlan *getPlan(uint8_t pt) const; const RtcCodecPlan *getPlan(uint8_t pt) const;
const RtcCodecPlan *getPlan(const char *codec) const;
}; };
class RtcSession{ class RtcSession{
@ -590,6 +599,7 @@ public:
SdpOrigin origin; SdpOrigin origin;
string session_name; string session_name;
string session_info; string session_info;
SdpTime time;
SdpConnection connection; SdpConnection connection;
SdpBandwidth bandwidth; SdpBandwidth bandwidth;
SdpAttrMsidSemantic msid_semantic; SdpAttrMsidSemantic msid_semantic;