mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-12-18 06:09:11 +00:00
Cleanup and reformatting
This commit is contained in:
@@ -32,6 +32,15 @@
|
|||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
|
const string DEFAULT_AUDIO_PROFILE =
|
||||||
|
"minptime=10;maxaveragebitrate=96000;stereo=1;sprop-stereo=1;useinbandfec=1";
|
||||||
|
|
||||||
|
// Use Constrained Baseline profile Level 4.2 (necessary for Firefox)
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#Supported_video_codecs
|
||||||
|
// TODO: Should be 42E0 but 42C0 appears to be more compatible. Investigate this.
|
||||||
|
const string DEFAULT_VIDEO_PROFILE =
|
||||||
|
"profile-level-id=42e01f;packetization-mode=1;level-asymmetry-allowed=1";
|
||||||
|
|
||||||
class RTC_CPP_EXPORT Description {
|
class RTC_CPP_EXPORT Description {
|
||||||
public:
|
public:
|
||||||
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
|
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
|
||||||
@@ -131,8 +140,10 @@ public:
|
|||||||
|
|
||||||
void removeFormat(const string &fmt);
|
void removeFormat(const string &fmt);
|
||||||
|
|
||||||
void addSSRC(uint32_t ssrc, std::optional<std::string> name, std::optional<std::string> msid=std::nullopt);
|
void addSSRC(uint32_t ssrc, std::optional<string> name,
|
||||||
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<std::string> name, std::optional<std::string> msid=std::nullopt);
|
std::optional<string> msid = nullopt);
|
||||||
|
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
||||||
|
std::optional<string> msid = nullopt);
|
||||||
bool hasSSRC(uint32_t ssrc);
|
bool hasSSRC(uint32_t ssrc);
|
||||||
std::vector<uint32_t> getSSRCs();
|
std::vector<uint32_t> getSSRCs();
|
||||||
|
|
||||||
@@ -141,7 +152,8 @@ public:
|
|||||||
|
|
||||||
bool hasPayloadType(int payloadType) const;
|
bool hasPayloadType(int payloadType) const;
|
||||||
|
|
||||||
void addRTXCodec(unsigned int payloadType, unsigned int originalPayloadType, unsigned int clockRate);
|
void addRTXCodec(unsigned int payloadType, unsigned int originalPayloadType,
|
||||||
|
unsigned int clockRate);
|
||||||
|
|
||||||
virtual void parseSdpLine(string_view line) override;
|
virtual void parseSdpLine(string_view line) override;
|
||||||
|
|
||||||
@@ -151,7 +163,7 @@ public:
|
|||||||
|
|
||||||
void removeFB(const string &string);
|
void removeFB(const string &string);
|
||||||
void addFB(const string &string);
|
void addFB(const string &string);
|
||||||
void addAttribute(std::string attr) { fmtps.emplace_back(attr); }
|
void addAttribute(string attr) { fmtps.emplace_back(std::move(attr)); }
|
||||||
|
|
||||||
int pt;
|
int pt;
|
||||||
string format;
|
string format;
|
||||||
@@ -190,8 +202,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
|
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
|
||||||
|
|
||||||
void addAudioCodec(int payloadType, const string &codec, const std::optional<std::string>& profile=
|
void addAudioCodec(int payloadType, string codec,
|
||||||
"minptime=10; maxaveragebitrate=96000; stereo=1; sprop-stereo=1; useinbandfec=1");
|
std::optional<string> profile = DEFAULT_AUDIO_PROFILE);
|
||||||
|
|
||||||
void addOpusCodec(int payloadType);
|
void addOpusCodec(int payloadType);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -199,11 +212,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
Video(string mid = "video", Direction dir = Direction::SendOnly);
|
Video(string mid = "video", Direction dir = Direction::SendOnly);
|
||||||
|
|
||||||
// Use Constrained Baseline profile Level 4.2 (necessary for Firefox)
|
void addVideoCodec(int payloadType, string codec,
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#Supported_video_codecs
|
std::optional<string> profile = DEFAULT_VIDEO_PROFILE);
|
||||||
// TODO: Should be 42E0 but 42C0 appears to be more compatible. Investigate this.
|
|
||||||
void addVideoCodec(int payloadType, const string &codec, const std::optional<std::string>&
|
|
||||||
profile="profile-level-id=42e01f;packetization-mode=1;level-asymmetry-allowed=1");
|
|
||||||
|
|
||||||
void addH264Codec(int payloadType);
|
void addH264Codec(int payloadType);
|
||||||
void addVP8Codec(int payloadType);
|
void addVP8Codec(int payloadType);
|
||||||
|
|||||||
@@ -66,10 +66,17 @@ public:
|
|||||||
inline uint32_t ssrc() const { return ntohl(_ssrc); }
|
inline uint32_t ssrc() const { return ntohl(_ssrc); }
|
||||||
|
|
||||||
inline size_t getSize() const {
|
inline size_t getSize() const {
|
||||||
return ((char *)&csrc) - ((char *)this) + sizeof(SSRC) * csrcCount();
|
return reinterpret_cast<const char *>(&csrc) - reinterpret_cast<const char *>(this) +
|
||||||
|
sizeof(SSRC) * csrcCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *getBody() const { return ((char *)&csrc) + sizeof(SSRC) * csrcCount(); }
|
[[nodiscard]] char *getBody() {
|
||||||
|
return reinterpret_cast<char *>(&csrc) + sizeof(SSRC) * csrcCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char *getBody() const {
|
||||||
|
return reinterpret_cast<const char *>(&csrc) + sizeof(SSRC) * csrcCount();
|
||||||
|
}
|
||||||
|
|
||||||
inline void setSeqNumber(uint16_t newSeqNo) { _seqNumber = htons(newSeqNo); }
|
inline void setSeqNumber(uint16_t newSeqNo) { _seqNumber = htons(newSeqNo); }
|
||||||
inline void setPayloadType(uint8_t newPayloadType) {
|
inline void setPayloadType(uint8_t newPayloadType) {
|
||||||
@@ -113,22 +120,23 @@ public:
|
|||||||
setDelaySinceSR(uint32_t(lastSR_DELAY));
|
setDelaySinceSR(uint32_t(lastSR_DELAY));
|
||||||
|
|
||||||
// The delay, expressed in units of 1/65536 seconds
|
// The delay, expressed in units of 1/65536 seconds
|
||||||
// this->delaySinceLastReport = lastSR_DELAY;
|
// this->delaySinceLastReport = lastSR_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setSSRC(SSRC in_ssrc) { this->ssrc = htonl(in_ssrc); }
|
inline void setSSRC(SSRC in_ssrc) { this->ssrc = htonl(in_ssrc); }
|
||||||
inline SSRC getSSRC() const { return ntohl(ssrc); }
|
[[nodiscard]] inline SSRC getSSRC() const { return ntohl(ssrc); }
|
||||||
|
|
||||||
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
|
inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost,
|
||||||
[[maybe_unused]] unsigned int totalPackets) {
|
[[maybe_unused]] unsigned int totalPackets) {
|
||||||
// TODO Implement loss percentages.
|
// TODO Implement loss percentages.
|
||||||
_fractionLostAndPacketsLost = 0;
|
_fractionLostAndPacketsLost = 0;
|
||||||
}
|
}
|
||||||
inline unsigned int getLossPercentage() const {
|
|
||||||
|
[[nodiscard]] inline unsigned int getLossPercentage() const {
|
||||||
// TODO Implement loss percentages.
|
// TODO Implement loss percentages.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inline unsigned int getPacketLostCount() const {
|
[[nodiscard]] inline unsigned int getPacketLostCount() const {
|
||||||
// TODO Implement total packets lost.
|
// TODO Implement total packets lost.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -145,13 +153,13 @@ public:
|
|||||||
inline void setJitter(uint32_t jitter) { _jitter = htonl(jitter); }
|
inline void setJitter(uint32_t jitter) { _jitter = htonl(jitter); }
|
||||||
|
|
||||||
inline void setNTPOfSR(uint64_t ntp) { _lastReport = htonll(ntp >> 16u); }
|
inline void setNTPOfSR(uint64_t ntp) { _lastReport = htonll(ntp >> 16u); }
|
||||||
inline uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; }
|
[[nodiscard]] inline uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; }
|
||||||
|
|
||||||
inline void setDelaySinceSR(uint32_t sr) {
|
inline void setDelaySinceSR(uint32_t sr) {
|
||||||
// The delay, expressed in units of 1/65536 seconds
|
// The delay, expressed in units of 1/65536 seconds
|
||||||
_delaySinceLastReport = htonl(sr);
|
_delaySinceLastReport = htonl(sr);
|
||||||
}
|
}
|
||||||
inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); }
|
[[nodiscard]] inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); }
|
||||||
|
|
||||||
inline void log() const {
|
inline void log() const {
|
||||||
PLOG_VERBOSE << "RTCP report block: "
|
PLOG_VERBOSE << "RTCP report block: "
|
||||||
@@ -242,8 +250,10 @@ public:
|
|||||||
this->_senderSSRC = htonl(senderSSRC);
|
this->_senderSSRC = htonl(senderSSRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
|
[[nodiscard]] inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
|
||||||
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
|
[[nodiscard]] inline const RTCP_ReportBlock *getReportBlock(int num) const {
|
||||||
|
return &_reportBlocks + num;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline size_t getSize() const {
|
[[nodiscard]] inline size_t getSize() const {
|
||||||
// "length" in packet is one less than the number of 32 bit words in the packet.
|
// "length" in packet is one less than the number of 32 bit words in the packet.
|
||||||
@@ -280,8 +290,10 @@ private:
|
|||||||
RTCP_ReportBlock _reportBlocks;
|
RTCP_ReportBlock _reportBlocks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
|
[[nodiscard]] inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
|
||||||
inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
|
[[nodiscard]] inline const RTCP_ReportBlock *getReportBlock(int num) const {
|
||||||
|
return &_reportBlocks + num;
|
||||||
|
}
|
||||||
|
|
||||||
inline SSRC senderSSRC() const { return ntohl(_senderSSRC); }
|
inline SSRC senderSSRC() const { return ntohl(_senderSSRC); }
|
||||||
inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); }
|
inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); }
|
||||||
@@ -477,11 +489,15 @@ public:
|
|||||||
return ntohs(*(uint16_t *)(header.getBody()));
|
return ntohs(*(uint16_t *)(header.getBody()));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *getBody() { return header.getBody() + sizeof(uint16_t); }
|
[[nodiscard]] char *getBody() { return header.getBody() + sizeof(uint16_t); }
|
||||||
|
|
||||||
size_t getBodySize(size_t totalSize) { return totalSize - ((char *)getBody() - (char *)this); }
|
[[nodiscard]] const char *getBody() const { return header.getBody() + sizeof(uint16_t); }
|
||||||
|
|
||||||
RTP &getHeader() { return header; }
|
[[nodiscard]] size_t getBodySize(size_t totalSize) {
|
||||||
|
return totalSize - (getBody() - reinterpret_cast<char *>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] RTP &getHeader() { return header; }
|
||||||
|
|
||||||
size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) {
|
size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) {
|
||||||
header.setSeqNumber(getOriginalSeqNo());
|
header.setSeqNumber(getOriginalSeqNo());
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
struct Configuration {
|
struct Configuration {
|
||||||
bool disableTlsVerification = false; // if true, don't verify the TLS certificate
|
bool disableTlsVerification = false; // if true, don't verify the TLS certificate
|
||||||
std::optional<std::vector<string>> protocols = std::nullopt;
|
std::vector<string> protocols;
|
||||||
};
|
};
|
||||||
|
|
||||||
WebSocket(std::optional<Configuration> config = nullopt);
|
WebSocket(std::optional<Configuration> config = nullopt);
|
||||||
|
|||||||
@@ -29,13 +29,13 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using std::size_t;
|
|
||||||
using std::string;
|
|
||||||
using std::string_view;
|
|
||||||
using std::chrono::system_clock;
|
using std::chrono::system_clock;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::string_view;
|
||||||
|
|
||||||
inline bool match_prefix(string_view str, string_view prefix) {
|
inline bool match_prefix(string_view str, string_view prefix) {
|
||||||
return str.size() >= prefix.size() &&
|
return str.size() >= prefix.size() &&
|
||||||
std::mismatch(prefix.begin(), prefix.end(), str.begin()).first == prefix.end();
|
std::mismatch(prefix.begin(), prefix.end(), str.begin()).first == prefix.end();
|
||||||
@@ -483,8 +483,7 @@ string Description::Entry::generateSdpLines(string_view eol) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &attr : mAttributes) {
|
for (const auto &attr : mAttributes) {
|
||||||
if (attr.find("extmap") == std::string::npos &&
|
if (attr.find("extmap") == string::npos && attr.find("rtcp-rsize") == string::npos)
|
||||||
attr.find("rtcp-rsize") == std::string::npos)
|
|
||||||
sdp << "a=" << attr << eol;
|
sdp << "a=" << attr << eol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +518,8 @@ Description::Entry::removeAttribute(std::vector<string>::iterator it) {
|
|||||||
return mAttributes.erase(it);
|
return mAttributes.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::addSSRC(uint32_t ssrc, std::optional<std::string> name, std::optional<std::string> msid) {
|
void Description::Media::addSSRC(uint32_t ssrc, std::optional<string> name,
|
||||||
|
std::optional<string> msid) {
|
||||||
if (name)
|
if (name)
|
||||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
|
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
|
||||||
else
|
else
|
||||||
@@ -531,7 +531,8 @@ void Description::Media::addSSRC(uint32_t ssrc, std::optional<std::string> name,
|
|||||||
mSsrcs.emplace_back(ssrc);
|
mSsrcs.emplace_back(ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<std::string> name, std::optional<std::string> msid) {
|
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
||||||
|
std::optional<string> msid) {
|
||||||
auto it = mAttributes.begin();
|
auto it = mAttributes.begin();
|
||||||
while (it != mAttributes.end()) {
|
while (it != mAttributes.end()) {
|
||||||
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
||||||
@@ -543,13 +544,13 @@ void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::removeSSRC(uint32_t oldSSRC) {
|
void Description::Media::removeSSRC(uint32_t oldSSRC) {
|
||||||
auto it = mAttributes.begin();
|
auto it = mAttributes.begin();
|
||||||
while (it != mAttributes.end()) {
|
while (it != mAttributes.end()) {
|
||||||
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
||||||
it = mAttributes.erase(it);
|
it = mAttributes.erase(it);
|
||||||
} else
|
} else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Description::Media::hasSSRC(uint32_t ssrc) {
|
bool Description::Media::hasSSRC(uint32_t ssrc) {
|
||||||
@@ -702,17 +703,17 @@ void Description::Media::removeFormat(const string &fmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Video::addVideoCodec(int payloadType, const string &codec, const std::optional<std::string>& profile) {
|
void Description::Video::addVideoCodec(int payloadType, string codec,
|
||||||
|
std::optional<string> profile) {
|
||||||
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/90000");
|
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/90000");
|
||||||
map.addFB("nack");
|
map.addFB("nack");
|
||||||
map.addFB("nack pli");
|
map.addFB("nack pli");
|
||||||
// map.addFB("ccm fir");
|
// map.addFB("ccm fir");
|
||||||
map.addFB("goog-remb");
|
map.addFB("goog-remb");
|
||||||
if (profile)
|
if (profile)
|
||||||
map.fmtps.emplace_back(*profile);
|
map.fmtps.emplace_back(*profile);
|
||||||
addRTPMap(map);
|
addRTPMap(map);
|
||||||
|
|
||||||
// // RTX Packets
|
|
||||||
/* TODO
|
/* TODO
|
||||||
* TIL that Firefox does not properly support the negotiation of RTX! It works, but doesn't
|
* TIL that Firefox does not properly support the negotiation of RTX! It works, but doesn't
|
||||||
* negotiate the SSRC so we have no idea what SSRC is RTX going to be. Three solutions: One) we
|
* negotiate the SSRC so we have no idea what SSRC is RTX going to be. Three solutions: One) we
|
||||||
@@ -720,31 +721,34 @@ void Description::Video::addVideoCodec(int payloadType, const string &codec, con
|
|||||||
* rebuild the original packet before we send it distribute it to each track. Three) we complain
|
* rebuild the original packet before we send it distribute it to each track. Three) we complain
|
||||||
* to mozilla. This one probably won't do much.
|
* to mozilla. This one probably won't do much.
|
||||||
*/
|
*/
|
||||||
// RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000");
|
// RTX Packets
|
||||||
// // TODO rtx-time is how long can a request be stashed for before needing to resend it.
|
// RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000");
|
||||||
// Needs to be parameterized rtx.addAttribute("apt=" + std::to_string(payloadType) +
|
// // TODO rtx-time is how long can a request be stashed for before needing to resend it.
|
||||||
// ";rtx-time=3000"); addRTPMap(rtx);
|
// Needs to be parameterized rtx.addAttribute("apt=" + std::to_string(payloadType) +
|
||||||
|
// ";rtx-time=3000"); addRTPMap(rtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Audio::addAudioCodec(int payloadType, const string &codec, const std::optional<std::string>& profile) {
|
void Description::Audio::addAudioCodec(int payloadType, string codec,
|
||||||
|
std::optional<string> profile) {
|
||||||
// TODO This 48000/2 should be parameterized
|
// TODO This 48000/2 should be parameterized
|
||||||
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2");
|
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2");
|
||||||
if (profile)
|
if (profile)
|
||||||
map.fmtps.emplace_back(*profile);
|
map.fmtps.emplace_back(*profile);
|
||||||
addRTPMap(map);
|
addRTPMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::addRTXCodec(unsigned int payloadType, unsigned int originalPayloadType, unsigned int clockRate) {
|
void Description::Media::addRTXCodec(unsigned int payloadType, unsigned int originalPayloadType,
|
||||||
RTPMap map(std::to_string(payloadType) + " RTX/" + std::to_string(clockRate));
|
unsigned int clockRate) {
|
||||||
map.fmtps.emplace_back("apt=" + std::to_string(originalPayloadType));
|
RTPMap map(std::to_string(payloadType) + " RTX/" + std::to_string(clockRate));
|
||||||
addRTPMap(map);
|
map.fmtps.emplace_back("apt=" + std::to_string(originalPayloadType));
|
||||||
|
addRTPMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Video::addH264Codec(int pt) { addVideoCodec(pt, "H264"); }
|
void Description::Video::addH264Codec(int pt) { addVideoCodec(pt, "H264"); }
|
||||||
|
|
||||||
void Description::Video::addVP8Codec(int payloadType) { addVideoCodec(payloadType, "VP8"); }
|
void Description::Video::addVP8Codec(int payloadType) { addVideoCodec(payloadType, "VP8", nullopt); }
|
||||||
|
|
||||||
void Description::Video::addVP9Codec(int payloadType) { addVideoCodec(payloadType, "VP9"); }
|
void Description::Video::addVP9Codec(int payloadType) { addVideoCodec(payloadType, "VP9", nullopt); }
|
||||||
|
|
||||||
void Description::Media::setBitrate(int bitrate) { mBas = bitrate; }
|
void Description::Media::setBitrate(int bitrate) { mBas = bitrate; }
|
||||||
|
|
||||||
@@ -813,7 +817,7 @@ void Description::Media::parseSdpLine(string_view line) {
|
|||||||
} else if (key == "rtcp-mux") {
|
} else if (key == "rtcp-mux") {
|
||||||
// always added
|
// always added
|
||||||
} else if (key == "ssrc") {
|
} else if (key == "ssrc") {
|
||||||
mSsrcs.emplace_back(std::stoul((std::string)value));
|
mSsrcs.emplace_back(std::stoul(string(value)));
|
||||||
} else {
|
} else {
|
||||||
Entry::parseSdpLine(line);
|
Entry::parseSdpLine(line);
|
||||||
}
|
}
|
||||||
@@ -833,7 +837,7 @@ std::vector<uint32_t> Description::Media::getSSRCs() {
|
|||||||
for (auto &val : mAttributes) {
|
for (auto &val : mAttributes) {
|
||||||
PLOG_DEBUG << val;
|
PLOG_DEBUG << val;
|
||||||
if (val.find("ssrc:") == 0) {
|
if (val.find("ssrc:") == 0) {
|
||||||
vec.emplace_back(std::stoul((std::string)val.substr(5, val.find(" "))));
|
vec.emplace_back(std::stoul(string(val.substr(5, val.find(" ")))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
@@ -857,7 +861,7 @@ Description::Media::RTPMap::RTPMap(string_view mline) { setMLine(mline); }
|
|||||||
void Description::Media::RTPMap::removeFB(const string &str) {
|
void Description::Media::RTPMap::removeFB(const string &str) {
|
||||||
auto it = rtcpFbs.begin();
|
auto it = rtcpFbs.begin();
|
||||||
while (it != rtcpFbs.end()) {
|
while (it != rtcpFbs.end()) {
|
||||||
if (it->find(str) != std::string::npos) {
|
if (it->find(str) != string::npos) {
|
||||||
it = rtcpFbs.erase(it);
|
it = rtcpFbs.erase(it);
|
||||||
} else
|
} else
|
||||||
it++;
|
it++;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
|
|||||||
if (err == srtp_err_status_replay_fail)
|
if (err == srtp_err_status_replay_fail)
|
||||||
throw std::runtime_error("SRTCP packet is a replay");
|
throw std::runtime_error("SRTCP packet is a replay");
|
||||||
else if (err == srtp_err_status_no_ctx) {
|
else if (err == srtp_err_status_no_ctx) {
|
||||||
auto ssrc = ((RTCP_SR *)message->data())->senderSSRC();
|
auto ssrc = reinterpret_cast<RTCP_SR *>(message->data())->senderSSRC();
|
||||||
PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc;
|
PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc;
|
||||||
addSSRC(ssrc);
|
addSSRC(ssrc);
|
||||||
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
|
if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)))
|
||||||
@@ -127,7 +127,7 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
|
|||||||
if (err == srtp_err_status_replay_fail)
|
if (err == srtp_err_status_replay_fail)
|
||||||
throw std::runtime_error("Outgoing SRTP packet is a replay");
|
throw std::runtime_error("Outgoing SRTP packet is a replay");
|
||||||
else if (err == srtp_err_status_no_ctx) {
|
else if (err == srtp_err_status_no_ctx) {
|
||||||
auto ssrc = ((RTP *)message->data())->ssrc();
|
auto ssrc = reinterpret_cast<RTP *>(message->data())->ssrc();
|
||||||
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
|
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
|
||||||
addSSRC(ssrc);
|
addSSRC(ssrc);
|
||||||
if ((err = srtp_protect(mSrtpOut, message->data(), &size)))
|
if ((err = srtp_protect(mSrtpOut, message->data(), &size)))
|
||||||
@@ -196,7 +196,7 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
|
|||||||
else if (err == srtp_err_status_auth_fail)
|
else if (err == srtp_err_status_auth_fail)
|
||||||
PLOG_WARNING << "Incoming SRTCP packet failed authentication check";
|
PLOG_WARNING << "Incoming SRTCP packet failed authentication check";
|
||||||
else if (err == srtp_err_status_no_ctx) {
|
else if (err == srtp_err_status_no_ctx) {
|
||||||
auto ssrc = ((RTCP_SR *)message->data())->senderSSRC();
|
auto ssrc = reinterpret_cast<RTCP_SR *>(message->data())->senderSSRC();
|
||||||
PLOG_INFO << "Adding SSRC to RTCP: " << ssrc;
|
PLOG_INFO << "Adding SSRC to RTCP: " << ssrc;
|
||||||
addSSRC(ssrc);
|
addSSRC(ssrc);
|
||||||
if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size)))
|
if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size)))
|
||||||
@@ -210,8 +210,7 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
|
|||||||
}
|
}
|
||||||
PLOG_VERBOSE << "Unprotected SRTCP packet, size=" << size;
|
PLOG_VERBOSE << "Unprotected SRTCP packet, size=" << size;
|
||||||
message->type = Message::Type::Control;
|
message->type = Message::Type::Control;
|
||||||
auto rtp = (RTCP_SR *)message->data();
|
message->stream = reinterpret_cast<RTCP_SR *>(message->data())->senderSSRC();
|
||||||
message->stream = rtp->senderSSRC();
|
|
||||||
} else {
|
} else {
|
||||||
PLOG_VERBOSE << "Incoming SRTP packet, size=" << size;
|
PLOG_VERBOSE << "Incoming SRTP packet, size=" << size;
|
||||||
if (srtp_err_status_t err = srtp_unprotect(mSrtpIn, message->data(), &size)) {
|
if (srtp_err_status_t err = srtp_unprotect(mSrtpIn, message->data(), &size)) {
|
||||||
@@ -220,7 +219,7 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
|
|||||||
else if (err == srtp_err_status_auth_fail)
|
else if (err == srtp_err_status_auth_fail)
|
||||||
PLOG_WARNING << "Incoming SRTP packet failed authentication check";
|
PLOG_WARNING << "Incoming SRTP packet failed authentication check";
|
||||||
else if (err == srtp_err_status_no_ctx) {
|
else if (err == srtp_err_status_no_ctx) {
|
||||||
auto ssrc = ((RTP *)message->data())->ssrc();
|
auto ssrc = reinterpret_cast<RTP *>(message->data())->ssrc();
|
||||||
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
|
PLOG_INFO << "Adding SSRC to RTP: " << ssrc;
|
||||||
addSSRC(ssrc);
|
addSSRC(ssrc);
|
||||||
if ((err = srtp_unprotect(mSrtpIn, message->data(), &size)))
|
if ((err = srtp_unprotect(mSrtpIn, message->data(), &size)))
|
||||||
@@ -228,13 +227,12 @@ void DtlsSrtpTransport::incoming(message_ptr message) {
|
|||||||
to_string(static_cast<int>(err)));
|
to_string(static_cast<int>(err)));
|
||||||
} else
|
} else
|
||||||
PLOG_WARNING << "SRTP unprotect error, status=" << err
|
PLOG_WARNING << "SRTP unprotect error, status=" << err
|
||||||
<< " SSRC=" << ((RTP *)message->data())->ssrc();
|
<< " SSRC=" << reinterpret_cast<RTP *>(message->data())->ssrc();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PLOG_VERBOSE << "Unprotected SRTP packet, size=" << size;
|
PLOG_VERBOSE << "Unprotected SRTP packet, size=" << size;
|
||||||
message->type = Message::Type::Binary;
|
message->type = Message::Type::Binary;
|
||||||
auto rtp = (RTP *)message->data();
|
message->stream = reinterpret_cast<RTP *>(message->data())->ssrc();
|
||||||
message->stream = rtp->ssrc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message->resize(size);
|
message->resize(size);
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ bool RtcpReceivingSession::requestKeyframe() {
|
|||||||
|
|
||||||
void RtcpReceivingSession::pushPLI() {
|
void RtcpReceivingSession::pushPLI() {
|
||||||
auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control);
|
auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control);
|
||||||
auto *pli = (rtc::RTCP_PLI *)msg->data();
|
auto *pli = reinterpret_cast<rtc::RTCP_PLI *>(msg->data());
|
||||||
pli->preparePacket(mSsrc);
|
pli->preparePacket(mSsrc);
|
||||||
send(msg);
|
send(msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,14 +292,13 @@ shared_ptr<WsTransport> WebSocket::initWsTransport() {
|
|||||||
if (!lower)
|
if (!lower)
|
||||||
lower = std::atomic_load(&mTcpTransport);
|
lower = std::atomic_load(&mTcpTransport);
|
||||||
|
|
||||||
auto wsConfig = WsTransport::Configuration();
|
WsTransport::Configuration wsConfig = {};
|
||||||
if(mConfig.protocols) {
|
wsConfig.host = mHost;
|
||||||
wsConfig.protocols = *mConfig.protocols;
|
wsConfig.path = mPath;
|
||||||
}
|
wsConfig.protocols = mConfig.protocols;
|
||||||
|
|
||||||
auto transport = std::make_shared<WsTransport>(
|
auto transport = std::make_shared<WsTransport>(
|
||||||
wsConfig,
|
lower, wsConfig, weak_bind(&WebSocket::incoming, this, _1),
|
||||||
lower, mHost, mPath, weak_bind(&WebSocket::incoming, this, _1),
|
|
||||||
[this, weak_this = weak_from_this()](State state) {
|
[this, weak_this = weak_from_this()](State state) {
|
||||||
auto shared_this = weak_this.lock();
|
auto shared_this = weak_this.lock();
|
||||||
if (!shared_this)
|
if (!shared_this)
|
||||||
|
|||||||
@@ -27,9 +27,9 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <numeric>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <numeric>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -54,17 +54,17 @@ using std::to_string;
|
|||||||
using random_bytes_engine =
|
using random_bytes_engine =
|
||||||
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned short>;
|
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned short>;
|
||||||
|
|
||||||
WsTransport::WsTransport(std::optional<Configuration> config, std::shared_ptr<Transport> lower, string host, string path,
|
WsTransport::WsTransport(std::shared_ptr<Transport> lower, Configuration config,
|
||||||
message_callback recvCallback, state_callback stateCallback)
|
message_callback recvCallback, state_callback stateCallback)
|
||||||
: Transport(lower, std::move(stateCallback)), mHost(std::move(host)), mPath(std::move(path)), mConfig(config ? std::move(*config) : Configuration()) {
|
: Transport(lower, std::move(stateCallback)), mConfig(std::move(config)) {
|
||||||
onRecv(recvCallback);
|
onRecv(recvCallback);
|
||||||
|
|
||||||
PLOG_DEBUG << "Initializing WebSocket transport";
|
PLOG_DEBUG << "Initializing WebSocket transport";
|
||||||
|
|
||||||
if (mHost.empty())
|
if (mConfig.host.empty())
|
||||||
throw std::invalid_argument("WebSocket HTTP host cannot be empty");
|
throw std::invalid_argument("WebSocket HTTP host cannot be empty");
|
||||||
|
|
||||||
if (mPath.empty())
|
if (mConfig.path.empty())
|
||||||
throw std::invalid_argument("WebSocket HTTP path cannot be empty");
|
throw std::invalid_argument("WebSocket HTTP path cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ void WsTransport::close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WsTransport::sendHttpRequest() {
|
bool WsTransport::sendHttpRequest() {
|
||||||
PLOG_DEBUG << "Sending WebSocket HTTP request for path " << mPath;
|
PLOG_DEBUG << "Sending WebSocket HTTP request for path " << mConfig.path;
|
||||||
changeState(State::Connecting);
|
changeState(State::Connecting);
|
||||||
|
|
||||||
auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
|
auto seed = static_cast<unsigned int>(system_clock::now().time_since_epoch().count());
|
||||||
@@ -166,27 +166,26 @@ bool WsTransport::sendHttpRequest() {
|
|||||||
std::generate(k, k + key.size(), [&]() { return uint8_t(generator()); });
|
std::generate(k, k + key.size(), [&]() { return uint8_t(generator()); });
|
||||||
|
|
||||||
string appendHeader = "";
|
string appendHeader = "";
|
||||||
if(mConfig.protocols.size() > 0) {
|
if (mConfig.protocols.size() > 0) {
|
||||||
appendHeader += "Sec-WebSocket-Protocol: " +
|
appendHeader +=
|
||||||
std::accumulate(mConfig.protocols.begin(), mConfig.protocols.end(), string(), [](const string& a, const string& b) -> string {
|
"Sec-WebSocket-Protocol: " +
|
||||||
return a + (a.length() > 0 ? "," : "") + b;
|
std::accumulate(mConfig.protocols.begin(), mConfig.protocols.end(), string(),
|
||||||
}) +
|
[](const string &a, const string &b) -> string {
|
||||||
"\r\n";
|
return a + (a.length() > 0 ? "," : "") + b;
|
||||||
|
}) +
|
||||||
|
"\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
const string request = "GET " + mPath +
|
const string request = "GET " + mConfig.path +
|
||||||
" HTTP/1.1\r\n"
|
" HTTP/1.1\r\n"
|
||||||
"Host: " +
|
"Host: " +
|
||||||
mHost +
|
mConfig.host +
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"Connection: Upgrade\r\n"
|
"Connection: Upgrade\r\n"
|
||||||
"Upgrade: websocket\r\n"
|
"Upgrade: websocket\r\n"
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
"Sec-WebSocket-Key: " +
|
"Sec-WebSocket-Key: " +
|
||||||
to_base64(key) +
|
to_base64(key) + "\r\n" + std::move(appendHeader) + "\r\n";
|
||||||
"\r\n" +
|
|
||||||
std::move(appendHeader) +
|
|
||||||
"\r\n";
|
|
||||||
|
|
||||||
auto data = reinterpret_cast<const byte *>(request.data());
|
auto data = reinterpret_cast<const byte *>(request.data());
|
||||||
auto size = request.size();
|
auto size = request.size();
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ class TlsTransport;
|
|||||||
class WsTransport : public Transport {
|
class WsTransport : public Transport {
|
||||||
public:
|
public:
|
||||||
struct Configuration {
|
struct Configuration {
|
||||||
|
string host;
|
||||||
|
string path = "/";
|
||||||
std::vector<string> protocols;
|
std::vector<string> protocols;
|
||||||
};
|
};
|
||||||
|
|
||||||
WsTransport(std::optional<Configuration> config, std::shared_ptr<Transport> lower, string host, string path,
|
WsTransport(std::shared_ptr<Transport> lower, Configuration config,
|
||||||
message_callback recvCallback, state_callback stateCallback);
|
message_callback recvCallback, state_callback stateCallback);
|
||||||
~WsTransport();
|
~WsTransport();
|
||||||
|
|
||||||
@@ -72,14 +74,12 @@ private:
|
|||||||
void recvFrame(const Frame &frame);
|
void recvFrame(const Frame &frame);
|
||||||
bool sendFrame(const Frame &frame);
|
bool sendFrame(const Frame &frame);
|
||||||
|
|
||||||
const string mHost;
|
const Configuration mConfig;
|
||||||
const string mPath;
|
|
||||||
|
|
||||||
binary mBuffer;
|
binary mBuffer;
|
||||||
binary mPartial;
|
binary mPartial;
|
||||||
Opcode mPartialOpcode;
|
Opcode mPartialOpcode;
|
||||||
|
|
||||||
const Configuration mConfig;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|||||||
Reference in New Issue
Block a user