diff --git a/examples/sfu-media/CMakeLists.txt b/examples/sfu-media/CMakeLists.txt index 0fcb676..7b81180 100644 --- a/examples/sfu-media/CMakeLists.txt +++ b/examples/sfu-media/CMakeLists.txt @@ -2,13 +2,14 @@ cmake_minimum_required(VERSION 3.7) add_executable(datachannel-sfu-media main.cpp) set_target_properties(datachannel-sfu-media PROPERTIES - CXX_STANDARD 17 - OUTPUT_NAME sfu-media) + CXX_STANDARD 17 + OUTPUT_NAME sfu-media) if(WIN32) - target_link_libraries(datachannel-sfu-media datachannel-static) # DLL exports only the C API + target_link_libraries(datachannel-sfu-media datachannel-static) # DLL exports only the C API else() - target_link_libraries(datachannel-sfu-media datachannel) + target_link_libraries(datachannel-sfu-media datachannel) endif() -target_link_libraries(datachannel-sfu-media datachannel nlohmann_json) \ No newline at end of file +target_link_libraries(datachannel-sfu-media datachannel nlohmann_json) + diff --git a/examples/sfu-media/main.cpp b/examples/sfu-media/main.cpp index 871632f..053260d 100644 --- a/examples/sfu-media/main.cpp +++ b/examples/sfu-media/main.cpp @@ -29,11 +29,11 @@ using nlohmann::json; struct Receiver { - std::shared_ptr conn; - std::shared_ptr track; + std::shared_ptr conn; + std::shared_ptr track; }; int main() { - std::vector> receivers; + std::vector> receivers; try { rtc::InitLogger(rtc::LogLevel::Info); @@ -47,16 +47,17 @@ int main() { auto description = pc->localDescription(); json message = {{"type", description->typeString()}, {"sdp", std::string(description.value())}}; - std::cout << "Please copy/paste this offer to the SENDER: " << message << std::endl; + std::cout << "Please copy/paste this offer to the SENDER: " << message << std::endl; } }); rtc::Description::Video media("video", rtc::Description::Direction::RecvOnly); media.addH264Codec(96); - media.setBitrate(3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) + media.setBitrate( + 3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) auto track = pc->addTrack(media); - pc->setLocalDescription(); + pc->setLocalDescription(); auto session = std::make_shared(); track->setRtcpHandler(session); @@ -66,63 +67,65 @@ int main() { track->onMessage( [&receivers](rtc::binary message) { // This is an RTP packet - auto rtp = (rtc::RTP*) message.data(); + auto rtp = (rtc::RTP *)message.data(); rtp->setSsrc(targetSSRC); for (auto pc : receivers) { - if (pc->track != nullptr && pc->track->isOpen()) { - pc->track->send(message); - } + if (pc->track != nullptr && pc->track->isOpen()) { + pc->track->send(message); + } } }, nullptr); - // Set the SENDERS Answer - { - std::cout << "Please copy/paste the answer provided by the SENDER: " << std::endl; - std::string sdp; - std::getline(std::cin, sdp); - std::cout << "Got answer" << sdp << std::endl; - json j = json::parse(sdp); - rtc::Description answer(j["sdp"].get(), j["type"].get()); - pc->setRemoteDescription(answer); - } + // Set the SENDERS Answer + { + std::cout << "Please copy/paste the answer provided by the SENDER: " << std::endl; + std::string sdp; + std::getline(std::cin, sdp); + std::cout << "Got answer" << sdp << std::endl; + json j = json::parse(sdp); + rtc::Description answer(j["sdp"].get(), j["type"].get()); + pc->setRemoteDescription(answer); + } - // For each receiver + // For each receiver while (true) { - auto pc = std::make_shared(); - pc->conn = std::make_shared(); - pc->conn->onStateChange( - [](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; }); - pc->conn->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) { - std::cout << "Gathering State: " << state << std::endl; - if (state == rtc::PeerConnection::GatheringState::Complete) { - auto description = pc->conn->localDescription(); - json message = {{"type", description->typeString()}, - {"sdp", std::string(description.value())}}; - std::cout << "Please copy/paste this offer to the RECEIVER: " << message << std::endl; - } - }); - rtc::Description::Video media("video", rtc::Description::Direction::SendOnly); - media.addH264Codec(96); - media.setBitrate( - 3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) + auto pc = std::make_shared(); + pc->conn = std::make_shared(); + pc->conn->onStateChange([](rtc::PeerConnection::State state) { + std::cout << "State: " << state << std::endl; + }); + pc->conn->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) { + std::cout << "Gathering State: " << state << std::endl; + if (state == rtc::PeerConnection::GatheringState::Complete) { + auto description = pc->conn->localDescription(); + json message = {{"type", description->typeString()}, + {"sdp", std::string(description.value())}}; + std::cout << "Please copy/paste this offer to the RECEIVER: " << message + << std::endl; + } + }); + rtc::Description::Video media("video", rtc::Description::Direction::SendOnly); + media.addH264Codec(96); + media.setBitrate( + 3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) - media.addSSRC(targetSSRC, "video-send"); + media.addSSRC(targetSSRC, "video-send"); - pc->track = pc->conn->addTrack(media); - pc->conn->setLocalDescription(); + pc->track = pc->conn->addTrack(media); + pc->conn->setLocalDescription(); - pc->track->onMessage([](rtc::binary var){}, nullptr); + pc->track->onMessage([](rtc::binary var) {}, nullptr); - std::cout << "Please copy/paste the answer provided by the RECEIVER: " << std::endl; - std::string sdp; - std::getline(std::cin, sdp); - std::cout << "Got answer" << sdp << std::endl; - json j = json::parse(sdp); - rtc::Description answer(j["sdp"].get(), j["type"].get()); - pc->conn->setRemoteDescription(answer); + std::cout << "Please copy/paste the answer provided by the RECEIVER: " << std::endl; + std::string sdp; + std::getline(std::cin, sdp); + std::cout << "Got answer" << sdp << std::endl; + json j = json::parse(sdp); + rtc::Description answer(j["sdp"].get(), j["type"].get()); + pc->conn->setRemoteDescription(answer); - receivers.push_back(pc); + receivers.push_back(pc); } } catch (const std::exception &e) { diff --git a/include/rtc/candidate.hpp b/include/rtc/candidate.hpp index bf154e4..af63db1 100644 --- a/include/rtc/candidate.hpp +++ b/include/rtc/candidate.hpp @@ -72,4 +72,3 @@ std::ostream &operator<<(std::ostream &out, const rtc::Candidate::Type &type); std::ostream &operator<<(std::ostream &out, const rtc::Candidate::TransportType &transportType); #endif - diff --git a/include/rtc/datachannel.hpp b/include/rtc/datachannel.hpp index c3e705b..b8c30fa 100644 --- a/include/rtc/datachannel.hpp +++ b/include/rtc/datachannel.hpp @@ -38,8 +38,8 @@ class PeerConnection; class DataChannel : public std::enable_shared_from_this, public Channel { public: - DataChannel(std::weak_ptr pc, uint16_t stream, string label, - string protocol, Reliability reliability); + DataChannel(std::weak_ptr pc, uint16_t stream, string label, string protocol, + Reliability reliability); virtual ~DataChannel(); uint16_t stream() const; @@ -90,9 +90,9 @@ private: class NegociatedDataChannel final : public DataChannel { public: NegociatedDataChannel(std::weak_ptr pc, uint16_t stream, string label, - string protocol, Reliability reliability); + string protocol, Reliability reliability); NegociatedDataChannel(std::weak_ptr pc, std::weak_ptr transport, - uint16_t stream); + uint16_t stream); ~NegociatedDataChannel(); private: diff --git a/include/rtc/description.hpp b/include/rtc/description.hpp index 8c07b9c..4b12dd9 100644 --- a/include/rtc/description.hpp +++ b/include/rtc/description.hpp @@ -77,11 +77,9 @@ public: virtual void parseSdpLine(string_view line); - - std::vector::iterator beginAttributes(); - std::vector::iterator endAttributes(); - std::vector::iterator removeAttribute(std::vector::iterator iterator); - + std::vector::iterator beginAttributes(); + std::vector::iterator endAttributes(); + std::vector::iterator removeAttribute(std::vector::iterator iterator); protected: Entry(const string &mline, string mid, Direction dir = Direction::Unknown); @@ -130,13 +128,13 @@ public: string description() const override; Media reciprocate() const; - void removeFormat(const string &fmt); + void removeFormat(const string &fmt); - void addSSRC(uint32_t ssrc, std::string name); - void addSSRC(uint32_t ssrc); - void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, string name); - bool hasSSRC(uint32_t ssrc); - std::vector getSSRCs(); + void addSSRC(uint32_t ssrc, std::string name); + void addSSRC(uint32_t ssrc); + void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, string name); + bool hasSSRC(uint32_t ssrc); + std::vector getSSRCs(); void setBitrate(int bitrate); int getBitrate() const; @@ -145,32 +143,29 @@ public: virtual void parseSdpLine(string_view line) override; - struct RTPMap { - RTPMap(string_view mline); - RTPMap() {} + struct RTPMap { + RTPMap(string_view mline); + RTPMap() {} - void removeFB(const string &string); - void addFB(const string &string); - void addAttribute(std::string attr) { - fmtps.emplace_back(attr); - } + void removeFB(const string &string); + void addFB(const string &string); + void addAttribute(std::string attr) { fmtps.emplace_back(attr); } + int pt; + string format; + int clockRate; + string encParams; - int pt; - string format; - int clockRate; - string encParams; + std::vector rtcpFbs; + std::vector fmtps; - std::vector rtcpFbs; - std::vector fmtps; + static int parsePT(string_view view); + void setMLine(string_view view); + }; - static int parsePT(string_view view); - void setMLine(string_view view); - }; - - std::map::iterator beginMaps(); - std::map::iterator endMaps(); - std::map::iterator removeMap(std::map::iterator iterator); + std::map::iterator beginMaps(); + std::map::iterator endMaps(); + std::map::iterator removeMap(std::map::iterator iterator); private: virtual string generateSdpLines(string_view eol) const override; @@ -184,26 +179,25 @@ public: std::vector mSsrcs; public: - void addRTPMap(const RTPMap& map); - - }; + void addRTPMap(const RTPMap &map); + }; class Audio : public Media { public: Audio(string mid = "audio", Direction dir = Direction::SendOnly); - void addAudioCodec(int payloadType, const string &codec); - void addOpusCodec(int payloadType); + void addAudioCodec(int payloadType, const string &codec); + void addOpusCodec(int payloadType); }; class Video : public Media { public: Video(string mid = "video", Direction dir = Direction::SendOnly); - void addVideoCodec(int payloadType, const string &codec); - void addH264Codec(int payloadType); - void addVP8Codec(int payloadType); - void addVP9Codec(int payloadType); + void addVideoCodec(int payloadType, const string &codec); + void addH264Codec(int payloadType); + void addVP8Codec(int payloadType); + void addVP9Codec(int payloadType); }; bool hasApplication() const; diff --git a/include/rtc/log.hpp b/include/rtc/log.hpp index 6639457..ff4e907 100644 --- a/include/rtc/log.hpp +++ b/include/rtc/log.hpp @@ -49,6 +49,6 @@ enum class LogLevel { // Don't change, it must match plog severity void InitLogger(LogLevel level); void InitLogger(plog::Severity severity, plog::IAppender *appender = nullptr); -} +} // namespace rtc #endif diff --git a/include/rtc/peerconnection.hpp b/include/rtc/peerconnection.hpp index c518f77..4da55c6 100644 --- a/include/rtc/peerconnection.hpp +++ b/include/rtc/peerconnection.hpp @@ -139,8 +139,8 @@ private: void forwardMessage(message_ptr message); void forwardMedia(message_ptr message); void forwardBufferedAmount(uint16_t stream, size_t amount); - std::optional getMidFromSSRC(SSRC ssrc); - std::optional getMLineFromSSRC(SSRC ssrc); + std::optional getMidFromSSRC(SSRC ssrc); + std::optional getMLineFromSSRC(SSRC ssrc); std::shared_ptr emplaceDataChannel(Description::Role role, string label, DataChannelInit init); @@ -153,7 +153,6 @@ private: void incomingTrack(Description::Media description); void openTracks(); - void validateRemoteDescription(const Description &description); void processLocalDescription(Description description); void processLocalCandidate(Candidate candidate); @@ -182,13 +181,13 @@ private: std::shared_ptr mDtlsTransport; std::shared_ptr mSctpTransport; - std::unordered_map> mDataChannels; // by stream ID - std::unordered_map> mTracks; // by mid - std::vector> mTrackLines; // by SDP order + std::unordered_map> mDataChannels; // by stream ID + std::unordered_map> mTracks; // by mid + std::vector> mTrackLines; // by SDP order std::shared_mutex mDataChannelsMutex, mTracksMutex; - std::unordered_map mMidFromSssrc; // cache - std::unordered_map mMLineFromSssrc; // cache + std::unordered_map mMidFromSssrc; // cache + std::unordered_map mMLineFromSssrc; // cache std::atomic mState; std::atomic mGatheringState; diff --git a/include/rtc/queue.hpp b/include/rtc/queue.hpp index e1d7a74..1ffc41d 100644 --- a/include/rtc/queue.hpp +++ b/include/rtc/queue.hpp @@ -170,4 +170,3 @@ template std::optional Queue::popImpl() { } // namespace rtc #endif - diff --git a/include/rtc/reliability.hpp b/include/rtc/reliability.hpp index 37ab397..fc03a76 100644 --- a/include/rtc/reliability.hpp +++ b/include/rtc/reliability.hpp @@ -37,4 +37,3 @@ struct Reliability { } // namespace rtc #endif - diff --git a/include/rtc/rtc.h b/include/rtc/rtc.h index 155fcba..fbf3eca 100644 --- a/include/rtc/rtc.h +++ b/include/rtc/rtc.h @@ -102,12 +102,14 @@ typedef struct { const char *protocol; // empty string if NULL bool negotiated; bool manualStream; - uint16_t stream; // numeric ID 0-65534, ignored if manualStream is false + uint16_t stream; // numeric ID 0-65534, ignored if manualStream is false } rtcDataChannelInit; typedef void(RTC_API *rtcLogCallbackFunc)(rtcLogLevel level, const char *message); -typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const char *type, void *ptr); -typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid, void *ptr); +typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const char *type, + void *ptr); +typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid, + void *ptr); typedef void(RTC_API *rtcStateChangeCallbackFunc)(int pc, rtcState state, void *ptr); typedef void(RTC_API *rtcGatheringStateCallbackFunc)(int pc, rtcGatheringState state, void *ptr); typedef void(RTC_API *rtcSignalingStateCallbackFunc)(int pc, rtcSignalingState state, void *ptr); @@ -147,15 +149,18 @@ RTC_EXPORT int rtcGetRemoteDescription(int pc, char *buffer, int size); RTC_EXPORT int rtcGetLocalAddress(int pc, char *buffer, int size); RTC_EXPORT int rtcGetRemoteAddress(int pc, char *buffer, int size); -RTC_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote, int remoteSize); +RTC_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote, + int remoteSize); // DataChannel RTC_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb); RTC_EXPORT int rtcAddDataChannel(int pc, const char *label); // returns dc id -RTC_EXPORT int rtcAddDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init); // returns dc id +RTC_EXPORT int rtcAddDataChannelEx(int pc, const char *label, + const rtcDataChannelInit *init); // returns dc id // Equivalent to calling rtcAddDataChannel() and rtcSetLocalDescription() RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id -RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init); // returns dc id +RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label, + const rtcDataChannelInit *init); // returns dc id RTC_EXPORT int rtcDeleteDataChannel(int dc); RTC_EXPORT int rtcGetDataChannelStream(int dc); diff --git a/include/rtc/rtc.hpp b/include/rtc/rtc.hpp index b78502d..261e4db 100644 --- a/include/rtc/rtc.hpp +++ b/include/rtc/rtc.hpp @@ -27,4 +27,3 @@ // C API #include "rtc.h" - diff --git a/include/rtc/rtcp.hpp b/include/rtc/rtcp.hpp index fc3277b..dbc7465 100644 --- a/include/rtc/rtcp.hpp +++ b/include/rtc/rtcp.hpp @@ -31,35 +31,34 @@ namespace rtc { class RtcpHandler { protected: - /** - * Use this callback when trying to send custom data (such as RTCP) to the client. - */ - synchronized_callback outgoingCallback; + /** + * Use this callback when trying to send custom data (such as RTCP) to the client. + */ + synchronized_callback outgoingCallback; + public: - /** - * Called when there is traffic coming from the peer - * @param ptr - * @return - */ - virtual rtc::message_ptr incoming(rtc::message_ptr ptr) = 0; + /** + * Called when there is traffic coming from the peer + * @param ptr + * @return + */ + virtual rtc::message_ptr incoming(rtc::message_ptr ptr) = 0; - /** - * Called when there is traffic that needs to be sent to the peer - * @param ptr - * @return - */ - virtual rtc::message_ptr outgoing(rtc::message_ptr ptr) = 0; + /** + * Called when there is traffic that needs to be sent to the peer + * @param ptr + * @return + */ + virtual rtc::message_ptr outgoing(rtc::message_ptr ptr) = 0; + /** + * This callback is used to send traffic back to the peer. + * This callback skips calling the track's methods. + * @param cb + */ + void onOutgoing(const std::function &cb); - /** - * This callback is used to send traffic back to the peer. - * This callback skips calling the track's methods. - * @param cb - */ - void onOutgoing(const std::function& cb); - - virtual bool requestKeyframe() {return false;} - + virtual bool requestKeyframe() { return false; } }; class Track; @@ -67,20 +66,19 @@ class Track; // An RtcpSession can be plugged into a Track to handle the whole RTCP session class RtcpReceivingSession : public RtcpHandler { public: - - rtc::message_ptr incoming(rtc::message_ptr ptr) override; - rtc::message_ptr outgoing(rtc::message_ptr ptr) override; - bool send(rtc::message_ptr ptr); + rtc::message_ptr incoming(rtc::message_ptr ptr) override; + rtc::message_ptr outgoing(rtc::message_ptr ptr) override; + bool send(rtc::message_ptr ptr); void requestBitrate(unsigned int newBitrate); - bool requestKeyframe() override; + bool requestKeyframe() override; protected: void pushREMB(unsigned int bitrate); void pushRR(unsigned int lastSR_delay); - void pushPLI(); + void pushPLI(); unsigned int mRequestedBitrate = 0; SSRC mSsrc = 0; diff --git a/include/rtc/rtp.hpp b/include/rtc/rtp.hpp index 94a2d5e..348cb04 100644 --- a/include/rtc/rtp.hpp +++ b/include/rtc/rtp.hpp @@ -37,491 +37,456 @@ #endif namespace rtc { - typedef uint32_t SSRC; +typedef uint32_t SSRC; #pragma pack(push, 1) struct RTP { private: - uint8_t _first; - uint8_t _payloadType; - uint16_t _seqNumber; - uint32_t _timestamp; - SSRC _ssrc; + uint8_t _first; + uint8_t _payloadType; + uint16_t _seqNumber; + uint32_t _timestamp; + SSRC _ssrc; public: - SSRC csrc[16]; + SSRC csrc[16]; - inline uint8_t version() const { return _first >> 6; } - inline bool padding() const { return (_first >> 5) & 0x01; } - inline uint8_t csrcCount() const { return _first & 0x0F; } - inline uint8_t marker() const { return _payloadType & 0b10000000; } - inline uint8_t payloadType() const { return _payloadType & 0b01111111; } - inline uint16_t seqNumber() const { return ntohs(_seqNumber); } - inline uint32_t timestamp() const { return ntohl(_timestamp); } - inline uint32_t ssrc() const { return ntohl(_ssrc);} + inline uint8_t version() const { return _first >> 6; } + inline bool padding() const { return (_first >> 5) & 0x01; } + inline uint8_t csrcCount() const { return _first & 0x0F; } + inline uint8_t marker() const { return _payloadType & 0b10000000; } + inline uint8_t payloadType() const { return _payloadType & 0b01111111; } + inline uint16_t seqNumber() const { return ntohs(_seqNumber); } + inline uint32_t timestamp() const { return ntohl(_timestamp); } + inline uint32_t ssrc() const { return ntohl(_ssrc); } - inline size_t getSize() const { - return ((char*)&csrc) - ((char*)this) + sizeof(SSRC)*csrcCount(); - } + inline size_t getSize() const { + return ((char *)&csrc) - ((char *)this) + sizeof(SSRC) * csrcCount(); + } - char * getBody() const { - return ((char*) &csrc) + sizeof(SSRC)*csrcCount(); - } + char *getBody() const { return ((char *)&csrc) + sizeof(SSRC) * csrcCount(); } - inline void setSeqNumber(uint16_t newSeqNo) { - _seqNumber = htons(newSeqNo); - } - inline void setPayloadType(uint8_t newPayloadType) { - _payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType); - } - inline void setSsrc(uint32_t ssrc) { - _ssrc = htonl(ssrc); - } + inline void setSeqNumber(uint16_t newSeqNo) { _seqNumber = htons(newSeqNo); } + inline void setPayloadType(uint8_t newPayloadType) { + _payloadType = (_payloadType & 0b10000000u) | (0b01111111u & newPayloadType); + } + inline void setSsrc(uint32_t ssrc) { _ssrc = htonl(ssrc); } - void setTimestamp(uint32_t i) { - _timestamp = htonl(i); - } + void setTimestamp(uint32_t i) { _timestamp = htonl(i); } }; struct RTCP_ReportBlock { - SSRC ssrc; + SSRC ssrc; private: - uint32_t _fractionLostAndPacketsLost; // fraction lost is 8-bit, packets lost is 24-bit - uint16_t _seqNoCycles; - uint16_t _highestSeqNo; - uint32_t _jitter; - uint32_t _lastReport; - uint32_t _delaySinceLastReport; + uint32_t _fractionLostAndPacketsLost; // fraction lost is 8-bit, packets lost is 24-bit + uint16_t _seqNoCycles; + uint16_t _highestSeqNo; + uint32_t _jitter; + uint32_t _lastReport; + uint32_t _delaySinceLastReport; public: - inline void preparePacket(SSRC ssrc, [[maybe_unused]] unsigned int packetsLost, - [[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo, - uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP, - uint64_t lastSR_DELAY) { - setSeqNo(highestSeqNo, seqNoCycles); - setJitter(jitter); - setSSRC(ssrc); + inline void preparePacket(SSRC ssrc, [[maybe_unused]] unsigned int packetsLost, + [[maybe_unused]] unsigned int totalPackets, uint16_t highestSeqNo, + uint16_t seqNoCycles, uint32_t jitter, uint64_t lastSR_NTP, + uint64_t lastSR_DELAY) { + setSeqNo(highestSeqNo, seqNoCycles); + setJitter(jitter); + setSSRC(ssrc); - // Middle 32 bits of NTP Timestamp - // this->lastReport = lastSR_NTP >> 16u; - setNTPOfSR(uint64_t(lastSR_NTP)); - setDelaySinceSR(uint32_t(lastSR_DELAY)); + // Middle 32 bits of NTP Timestamp + // this->lastReport = lastSR_NTP >> 16u; + setNTPOfSR(uint64_t(lastSR_NTP)); + setDelaySinceSR(uint32_t(lastSR_DELAY)); - // The delay, expressed in units of 1/65536 seconds - // this->delaySinceLastReport = lastSR_DELAY; - } + // The delay, expressed in units of 1/65536 seconds + // this->delaySinceLastReport = lastSR_DELAY; + } - inline void setSSRC(SSRC ssrc) { this->ssrc = htonl(ssrc); } - inline SSRC getSSRC() const { return ntohl(ssrc); } + inline void setSSRC(SSRC ssrc) { this->ssrc = htonl(ssrc); } + inline SSRC getSSRC() const { return ntohl(ssrc); } - inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost, - [[maybe_unused]] unsigned int totalPackets) { - // TODO Implement loss percentages. - _fractionLostAndPacketsLost = 0; - } - inline unsigned int getLossPercentage() const { - // TODO Implement loss percentages. - return 0; - } - inline unsigned int getPacketLostCount() const { - // TODO Implement total packets lost. - return 0; - } + inline void setPacketsLost([[maybe_unused]] unsigned int packetsLost, + [[maybe_unused]] unsigned int totalPackets) { + // TODO Implement loss percentages. + _fractionLostAndPacketsLost = 0; + } + inline unsigned int getLossPercentage() const { + // TODO Implement loss percentages. + return 0; + } + inline unsigned int getPacketLostCount() const { + // TODO Implement total packets lost. + return 0; + } - inline uint16_t seqNoCycles() const { return ntohs(_seqNoCycles); } - inline uint16_t highestSeqNo() const { return ntohs(_highestSeqNo); } - inline uint32_t jitter() const { return ntohl(_jitter); } + inline uint16_t seqNoCycles() const { return ntohs(_seqNoCycles); } + inline uint16_t highestSeqNo() const { return ntohs(_highestSeqNo); } + inline uint32_t jitter() const { return ntohl(_jitter); } - inline void setSeqNo(uint16_t highestSeqNo, uint16_t seqNoCycles) { - _highestSeqNo = htons(highestSeqNo); - _seqNoCycles = htons(seqNoCycles); - } + inline void setSeqNo(uint16_t highestSeqNo, uint16_t seqNoCycles) { + _highestSeqNo = htons(highestSeqNo); + _seqNoCycles = htons(seqNoCycles); + } - 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 uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; } + inline void setNTPOfSR(uint64_t ntp) { _lastReport = htonll(ntp >> 16u); } + inline uint32_t getNTPOfSR() const { return ntohl(_lastReport) << 16u; } - inline void setDelaySinceSR(uint32_t sr) { - // The delay, expressed in units of 1/65536 seconds - _delaySinceLastReport = htonl(sr); - } - inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); } + inline void setDelaySinceSR(uint32_t sr) { + // The delay, expressed in units of 1/65536 seconds + _delaySinceLastReport = htonl(sr); + } + inline uint32_t getDelaySinceSR() const { return ntohl(_delaySinceLastReport); } - inline void log() const { - PLOG_VERBOSE << "RTCP report block: " - << "ssrc=" - << ntohl(ssrc) - // TODO: Implement these reports - // << ", fractionLost=" << fractionLost - // << ", packetsLost=" << packetsLost - << ", highestSeqNo=" << highestSeqNo() << ", seqNoCycles=" << seqNoCycles() - << ", jitter=" << jitter() << ", lastSR=" << getNTPOfSR() - << ", lastSRDelay=" << getDelaySinceSR(); - } + inline void log() const { + PLOG_VERBOSE << "RTCP report block: " + << "ssrc=" + << ntohl(ssrc) + // TODO: Implement these reports + // << ", fractionLost=" << fractionLost + // << ", packetsLost=" << packetsLost + << ", highestSeqNo=" << highestSeqNo() << ", seqNoCycles=" << seqNoCycles() + << ", jitter=" << jitter() << ", lastSR=" << getNTPOfSR() + << ", lastSRDelay=" << getDelaySinceSR(); + } }; struct RTCP_HEADER { private: - uint8_t _first; - uint8_t _payloadType; - uint16_t _length; + uint8_t _first; + uint8_t _payloadType; + uint16_t _length; public: - inline uint8_t version() const { return _first >> 6; } - inline bool padding() const { return (_first >> 5) & 0x01; } - inline uint8_t reportCount() const { return _first & 0x0F; } - inline uint8_t payloadType() const { return _payloadType; } - inline uint16_t length() const { return ntohs(_length); } - inline size_t lengthInBytes() const { - return (1+length())*4; - } + inline uint8_t version() const { return _first >> 6; } + inline bool padding() const { return (_first >> 5) & 0x01; } + inline uint8_t reportCount() const { return _first & 0x0F; } + inline uint8_t payloadType() const { return _payloadType; } + inline uint16_t length() const { return ntohs(_length); } + inline size_t lengthInBytes() const { return (1 + length()) * 4; } - inline void setPayloadType(uint8_t type) { _payloadType = type; } - inline void setReportCount(uint8_t count) { _first = (_first & 0b11100000u) | (count & 0b00011111u); } - inline void setLength(uint16_t length) { _length = htons(length); } + inline void setPayloadType(uint8_t type) { _payloadType = type; } + inline void setReportCount(uint8_t count) { + _first = (_first & 0b11100000u) | (count & 0b00011111u); + } + inline void setLength(uint16_t length) { _length = htons(length); } - inline void prepareHeader(uint8_t payloadType, uint8_t reportCount, uint16_t length) { - _first = 0b10000000; // version 2, no padding - setReportCount(reportCount); - setPayloadType(payloadType); - setLength(length); - } + inline void prepareHeader(uint8_t payloadType, uint8_t reportCount, uint16_t length) { + _first = 0b10000000; // version 2, no padding + setReportCount(reportCount); + setPayloadType(payloadType); + setLength(length); + } - inline void log() const { - PLOG_INFO << "RTCP header: " - << "version=" << unsigned(version()) << ", padding=" << padding() - << ", reportCount=" << unsigned(reportCount()) - << ", payloadType=" << unsigned(payloadType()) << ", length=" << length(); - } + inline void log() const { + PLOG_INFO << "RTCP header: " + << "version=" << unsigned(version()) << ", padding=" << padding() + << ", reportCount=" << unsigned(reportCount()) + << ", payloadType=" << unsigned(payloadType()) << ", length=" << length(); + } }; struct RTCP_FB_HEADER { - RTCP_HEADER header; - SSRC packetSender; - SSRC mediaSource; + RTCP_HEADER header; + SSRC packetSender; + SSRC mediaSource; - [[nodiscard]] SSRC getPacketSenderSSRC() const { - return ntohl(packetSender); - } + [[nodiscard]] SSRC getPacketSenderSSRC() const { return ntohl(packetSender); } - [[nodiscard]] SSRC getMediaSourceSSRC() const { - return ntohl(mediaSource); - } + [[nodiscard]] SSRC getMediaSourceSSRC() const { return ntohl(mediaSource); } - void setPacketSenderSSRC(SSRC ssrc) { - this->packetSender = htonl(ssrc); - } + void setPacketSenderSSRC(SSRC ssrc) { this->packetSender = htonl(ssrc); } - void setMediaSourceSSRC(SSRC ssrc) { - this->mediaSource = htonl(ssrc); - } + void setMediaSourceSSRC(SSRC ssrc) { this->mediaSource = htonl(ssrc); } - void log() { - header.log(); - PLOG_VERBOSE << "FB: " << " packet sender: " << getPacketSenderSSRC() << " media source: " << getMediaSourceSSRC(); - } + void log() { + header.log(); + PLOG_VERBOSE << "FB: " + << " packet sender: " << getPacketSenderSSRC() + << " media source: " << getMediaSourceSSRC(); + } }; struct RTCP_SR { - RTCP_HEADER header; - SSRC _senderSSRC; + RTCP_HEADER header; + SSRC _senderSSRC; private: - uint64_t _ntpTimestamp; - uint32_t _rtpTimestamp; - uint32_t _packetCount; - uint32_t _octetCount; + uint64_t _ntpTimestamp; + uint32_t _rtpTimestamp; + uint32_t _packetCount; + uint32_t _octetCount; - RTCP_ReportBlock _reportBlocks; + RTCP_ReportBlock _reportBlocks; public: - inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) { - unsigned int length = - ((sizeof(header) + 24 + reportCount * sizeof(RTCP_ReportBlock)) / 4) - 1; - header.prepareHeader(200, reportCount, uint16_t(length)); - this->_senderSSRC = htonl(senderSSRC); - } + inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) { + unsigned int length = + ((sizeof(header) + 24 + reportCount * sizeof(RTCP_ReportBlock)) / 4) - 1; + header.prepareHeader(200, reportCount, uint16_t(length)); + this->_senderSSRC = htonl(senderSSRC); + } - inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; } - inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; } + inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; } + inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; } - [[nodiscard]] inline size_t getSize() const { - // "length" in packet is one less than the number of 32 bit words in the packet. - return sizeof(uint32_t) * (1 + size_t(header.length())); - } + [[nodiscard]] inline size_t getSize() const { + // "length" in packet is one less than the number of 32 bit words in the packet. + return sizeof(uint32_t) * (1 + size_t(header.length())); + } - inline uint64_t ntpTimestamp() const { return ntohll(_ntpTimestamp); } - inline uint32_t rtpTimestamp() const { return ntohl(_rtpTimestamp); } - inline uint32_t packetCount() const { return ntohl(_packetCount); } - inline uint32_t octetCount() const { return ntohl(_octetCount); } - inline uint32_t senderSSRC() const {return ntohl(_senderSSRC);} + inline uint64_t ntpTimestamp() const { return ntohll(_ntpTimestamp); } + inline uint32_t rtpTimestamp() const { return ntohl(_rtpTimestamp); } + inline uint32_t packetCount() const { return ntohl(_packetCount); } + inline uint32_t octetCount() const { return ntohl(_octetCount); } + inline uint32_t senderSSRC() const { return ntohl(_senderSSRC); } - inline void setNtpTimestamp(uint32_t ts) { _ntpTimestamp = htonll(ts); } - inline void setRtpTimestamp(uint32_t ts) { _rtpTimestamp = htonl(ts); } + inline void setNtpTimestamp(uint32_t ts) { _ntpTimestamp = htonll(ts); } + inline void setRtpTimestamp(uint32_t ts) { _rtpTimestamp = htonl(ts); } - inline void log() const { - header.log(); - PLOG_VERBOSE << "RTCP SR: " - << " SSRC=" << senderSSRC() << ", NTP_TS=" << ntpTimestamp() - << ", RTP_TS=" << rtpTimestamp() << ", packetCount=" << packetCount() - << ", octetCount=" << octetCount(); + inline void log() const { + header.log(); + PLOG_VERBOSE << "RTCP SR: " + << " SSRC=" << senderSSRC() << ", NTP_TS=" << ntpTimestamp() + << ", RTP_TS=" << rtpTimestamp() << ", packetCount=" << packetCount() + << ", octetCount=" << octetCount(); - for (unsigned i = 0; i < unsigned(header.reportCount()); i++) { - getReportBlock(i)->log(); - } - } + for (unsigned i = 0; i < unsigned(header.reportCount()); i++) { + getReportBlock(i)->log(); + } + } }; struct RTCP_RR { - RTCP_HEADER header; - SSRC _senderSSRC; + RTCP_HEADER header; + SSRC _senderSSRC; private: - RTCP_ReportBlock _reportBlocks; + RTCP_ReportBlock _reportBlocks; public: - inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; } - inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; } + inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; } + inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; } - inline SSRC senderSSRC() const { return ntohl(_senderSSRC); } - inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); } + inline SSRC senderSSRC() const { return ntohl(_senderSSRC); } + inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); } - [[nodiscard]] inline size_t getSize() const { - // "length" in packet is one less than the number of 32 bit words in the packet. - return sizeof(uint32_t) * (1 + size_t(header.length())); - } + [[nodiscard]] inline size_t getSize() const { + // "length" in packet is one less than the number of 32 bit words in the packet. + return sizeof(uint32_t) * (1 + size_t(header.length())); + } - inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) { - // "length" in packet is one less than the number of 32 bit words in the packet. - size_t length = (sizeWithReportBlocks(reportCount) / 4) - 1; - header.prepareHeader(201, reportCount, uint16_t(length)); - this->_senderSSRC = htonl(senderSSRC); - } + inline void preparePacket(SSRC senderSSRC, uint8_t reportCount) { + // "length" in packet is one less than the number of 32 bit words in the packet. + size_t length = (sizeWithReportBlocks(reportCount) / 4) - 1; + header.prepareHeader(201, reportCount, uint16_t(length)); + this->_senderSSRC = htonl(senderSSRC); + } - inline static size_t sizeWithReportBlocks(uint8_t reportCount) { - return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock); - } + inline static size_t sizeWithReportBlocks(uint8_t reportCount) { + return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock); + } - inline bool isSenderReport() { - return header.payloadType() == 200; - } + inline bool isSenderReport() { return header.payloadType() == 200; } - inline bool isReceiverReport() { - return header.payloadType() == 201; - } + inline bool isReceiverReport() { return header.payloadType() == 201; } - inline void log() const { - header.log(); - PLOG_VERBOSE << "RTCP RR: " - << " SSRC=" << ntohl(_senderSSRC); + inline void log() const { + header.log(); + PLOG_VERBOSE << "RTCP RR: " + << " SSRC=" << ntohl(_senderSSRC); - for (unsigned i = 0; i < unsigned(header.reportCount()); i++) { - getReportBlock(i)->log(); - } - } + for (unsigned i = 0; i < unsigned(header.reportCount()); i++) { + getReportBlock(i)->log(); + } + } }; - struct RTCP_REMB { - RTCP_FB_HEADER header; + RTCP_FB_HEADER header; - /*! \brief Unique identifier ('R' 'E' 'M' 'B') */ - char id[4]; + /*! \brief Unique identifier ('R' 'E' 'M' 'B') */ + char id[4]; - /*! \brief Num SSRC, Br Exp, Br Mantissa (bit mask) */ - uint32_t bitrate; + /*! \brief Num SSRC, Br Exp, Br Mantissa (bit mask) */ + uint32_t bitrate; - SSRC ssrc[1]; + SSRC ssrc[1]; - [[nodiscard]] unsigned int getSize() const { - // "length" in packet is one less than the number of 32 bit words in the packet. - return sizeof(uint32_t) * (1 + header.header.length()); - } + [[nodiscard]] unsigned int getSize() const { + // "length" in packet is one less than the number of 32 bit words in the packet. + return sizeof(uint32_t) * (1 + header.header.length()); + } - void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int bitrate) { + void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int bitrate) { - // Report Count becomes the format here. - header.header.prepareHeader(206, 15, 0); + // Report Count becomes the format here. + header.header.prepareHeader(206, 15, 0); - // Always zero. - header.setMediaSourceSSRC(0); + // Always zero. + header.setMediaSourceSSRC(0); - header.setPacketSenderSSRC(senderSSRC); + header.setPacketSenderSSRC(senderSSRC); - id[0] = 'R'; - id[1] = 'E'; - id[2] = 'M'; - id[3] = 'B'; + id[0] = 'R'; + id[1] = 'E'; + id[2] = 'M'; + id[3] = 'B'; - setBitrate(numSSRC, bitrate); - } + setBitrate(numSSRC, bitrate); + } - void setBitrate(unsigned int numSSRC, unsigned int bitrate) { - unsigned int exp = 0; - while (bitrate > pow(2, 18) - 1) { - exp++; - bitrate /= 2; - } + void setBitrate(unsigned int numSSRC, unsigned int bitrate) { + unsigned int exp = 0; + while (bitrate > pow(2, 18) - 1) { + exp++; + bitrate /= 2; + } - // "length" in packet is one less than the number of 32 bit words in the packet. - header.header.setLength(uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC)); + // "length" in packet is one less than the number of 32 bit words in the packet. + header.header.setLength( + uint16_t((offsetof(RTCP_REMB, ssrc) / sizeof(uint32_t)) - 1 + numSSRC)); - this->bitrate = htonl( - (numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | bitrate - ); - } + this->bitrate = htonl((numSSRC << (32u - 8u)) | (exp << (32u - 8u - 6u)) | bitrate); + } - void setSsrc(int iterator, SSRC newSssrc){ - ssrc[iterator] = htonl(newSssrc); - } + void setSsrc(int iterator, SSRC newSssrc) { ssrc[iterator] = htonl(newSssrc); } - size_t static inline sizeWithSSRCs(int count) { - return sizeof(RTCP_REMB) + (count-1)*sizeof(SSRC); - } + size_t static inline sizeWithSSRCs(int count) { + return sizeof(RTCP_REMB) + (count - 1) * sizeof(SSRC); + } }; - struct RTCP_PLI { - RTCP_FB_HEADER header; + RTCP_FB_HEADER header; - void preparePacket(SSRC messageSSRC) { - header.header.prepareHeader(206, 1, 2); - header.setPacketSenderSSRC(messageSSRC); - header.setMediaSourceSSRC(messageSSRC); - } + void preparePacket(SSRC messageSSRC) { + header.header.prepareHeader(206, 1, 2); + header.setPacketSenderSSRC(messageSSRC); + header.setMediaSourceSSRC(messageSSRC); + } - void print() { - header.log(); - } + void print() { header.log(); } - [[nodiscard]] static unsigned int size() { - return sizeof(RTCP_FB_HEADER); - } + [[nodiscard]] static unsigned int size() { return sizeof(RTCP_FB_HEADER); } }; struct RTCP_FIR_PART { - uint32_t ssrc; + uint32_t ssrc; #if __BYTE_ORDER == __BIG_ENDIAN - uint32_t seqNo: 8; - uint32_t: 24; + uint32_t seqNo : 8; + uint32_t : 24; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint32_t: 24; - uint32_t seqNo: 8; + uint32_t : 24; + uint32_t seqNo : 8; #endif }; struct RTCP_FIR { - RTCP_FB_HEADER header; - RTCP_FIR_PART parts[1]; + RTCP_FB_HEADER header; + RTCP_FIR_PART parts[1]; - void preparePacket(SSRC messageSSRC, uint8_t seqNo) { - header.header.prepareHeader(206, 4, 2 + 2 * 1); - header.setPacketSenderSSRC(messageSSRC); - header.setMediaSourceSSRC(messageSSRC); - parts[0].ssrc = htonl(messageSSRC); - parts[0].seqNo = seqNo; - } + void preparePacket(SSRC messageSSRC, uint8_t seqNo) { + header.header.prepareHeader(206, 4, 2 + 2 * 1); + header.setPacketSenderSSRC(messageSSRC); + header.setMediaSourceSSRC(messageSSRC); + parts[0].ssrc = htonl(messageSSRC); + parts[0].seqNo = seqNo; + } - void print() { - header.log(); - } + void print() { header.log(); } - [[nodiscard]] static unsigned int size() { - return sizeof(RTCP_FB_HEADER) + sizeof(RTCP_FIR_PART); - } + [[nodiscard]] static unsigned int size() { + return sizeof(RTCP_FB_HEADER) + sizeof(RTCP_FIR_PART); + } }; struct RTCP_NACK_PART { - uint16_t pid; - uint16_t blp; + uint16_t pid; + uint16_t blp; }; class RTCP_NACK { public: - RTCP_FB_HEADER header; - RTCP_NACK_PART parts[1]; + RTCP_FB_HEADER header; + RTCP_NACK_PART parts[1]; + public: - void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) { - header.header.prepareHeader(205, 1, 2 + discreteSeqNoCount); - header.setMediaSourceSSRC(ssrc); - header.setPacketSenderSSRC(ssrc); - } + void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount) { + header.header.prepareHeader(205, 1, 2 + discreteSeqNoCount); + header.setMediaSourceSSRC(ssrc); + header.setPacketSenderSSRC(ssrc); + } - /** - * Add a packet to the list of missing packets. - * @param fciCount The number of FCI fields that are present in this packet. - * Let the number start at zero and let this function grow the number. - * @param fciPID The seq no of the active FCI. It will be initialized automatically, and will change automatically. - * @param missingPacket The seq no of the missing packet. This will be added to the queue. - * @return true if the packet has grown, false otherwise. - */ - bool addMissingPacket(unsigned int *fciCount, uint16_t *fciPID, const uint16_t &missingPacket) { - if (*fciCount == 0 || missingPacket < *fciPID || missingPacket > (*fciPID + 16)) { - parts[*fciCount].pid = htons(missingPacket); - parts[*fciCount].blp = 0; - *fciPID = missingPacket; - (*fciCount)++; - return true; - } else { - // TODO SPEEED! - parts[(*fciCount) - 1].blp = htons( - ntohs(parts[(*fciCount) - 1].blp) | (1u << (unsigned int) (missingPacket - *fciPID))); - return false; - } - } + /** + * Add a packet to the list of missing packets. + * @param fciCount The number of FCI fields that are present in this packet. + * Let the number start at zero and let this function grow the number. + * @param fciPID The seq no of the active FCI. It will be initialized automatically, and will + * change automatically. + * @param missingPacket The seq no of the missing packet. This will be added to the queue. + * @return true if the packet has grown, false otherwise. + */ + bool addMissingPacket(unsigned int *fciCount, uint16_t *fciPID, const uint16_t &missingPacket) { + if (*fciCount == 0 || missingPacket < *fciPID || missingPacket > (*fciPID + 16)) { + parts[*fciCount].pid = htons(missingPacket); + parts[*fciCount].blp = 0; + *fciPID = missingPacket; + (*fciCount)++; + return true; + } else { + // TODO SPEEED! + parts[(*fciCount) - 1].blp = htons(ntohs(parts[(*fciCount) - 1].blp) | + (1u << (unsigned int)(missingPacket - *fciPID))); + return false; + } + } - [[nodiscard]] static unsigned int getSize(unsigned int discreteSeqNoCount) { - return offsetof(RTCP_NACK, parts) + sizeof(RTCP_NACK_PART) * discreteSeqNoCount; - } + [[nodiscard]] static unsigned int getSize(unsigned int discreteSeqNoCount) { + return offsetof(RTCP_NACK, parts) + sizeof(RTCP_NACK_PART) * discreteSeqNoCount; + } - [[nodiscard]] unsigned int getSeqNoCount() { - return header.header.length() - 2; - } + [[nodiscard]] unsigned int getSeqNoCount() { return header.header.length() - 2; } }; class RTP_RTX { private: - RTP header; + RTP header; + public: + size_t copyTo(RTP *dest, size_t totalSize, uint8_t originalPayloadType) { + memmove((char *)dest, (char *)this, header.getSize()); + dest->setSeqNumber(getOriginalSeqNo()); + dest->setPayloadType(originalPayloadType); + memmove(dest->getBody(), getBody(), getBodySize(totalSize)); + return totalSize; + } - size_t copyTo(RTP *dest, size_t totalSize, uint8_t originalPayloadType) { - memmove((char*)dest, (char*)this, header.getSize()); - dest->setSeqNumber(getOriginalSeqNo()); - dest->setPayloadType(originalPayloadType); - memmove(dest->getBody(), getBody(), getBodySize(totalSize)); - return totalSize; - } + [[nodiscard]] uint16_t getOriginalSeqNo() const { + return ntohs(*(uint16_t *)(header.getBody())); + } - [[nodiscard]] uint16_t getOriginalSeqNo() const { - return ntohs(*(uint16_t *) (header.getBody())); - } + char *getBody() { return header.getBody() + sizeof(uint16_t); } - char *getBody() { - return header.getBody() + sizeof(uint16_t); - } + size_t getBodySize(size_t totalSize) { return totalSize - ((char *)getBody() - (char *)this); } - size_t getBodySize(size_t totalSize) { - return totalSize - ((char *) getBody() - (char *) this); - } + RTP &getHeader() { return header; } - RTP &getHeader() { - return header; - } - - size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) { - header.setSeqNumber(getOriginalSeqNo()); - header.setSsrc(originalSSRC); // TODO Endianess - header.setPayloadType(originalPayloadType); - // TODO, the -12 is the size of the header (which is variable!) - memmove(header.getBody(), header.getBody() + sizeof(uint16_t), totalSize - 12 - sizeof(uint16_t)); - return totalSize - sizeof(uint16_t); - } + size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType) { + header.setSeqNumber(getOriginalSeqNo()); + header.setSsrc(originalSSRC); // TODO Endianess + header.setPayloadType(originalPayloadType); + // TODO, the -12 is the size of the header (which is variable!) + memmove(header.getBody(), header.getBody() + sizeof(uint16_t), + totalSize - 12 - sizeof(uint16_t)); + return totalSize - sizeof(uint16_t); + } }; - #pragma pack(pop) -}; -#endif //WEBRTC_SERVER_RTP_HPP +}; // namespace rtc +#endif // WEBRTC_SERVER_RTP_HPP diff --git a/include/rtc/track.hpp b/include/rtc/track.hpp index 70b9944..80e906d 100644 --- a/include/rtc/track.hpp +++ b/include/rtc/track.hpp @@ -80,10 +80,8 @@ private: std::shared_ptr mRtcpHandler; friend class PeerConnection; - }; } // namespace rtc #endif - diff --git a/src/base64.cpp b/src/base64.cpp index 401f924..508a898 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -25,8 +25,7 @@ namespace rtc { using std::to_integer; string to_base64(const binary &data) { - static const char tab[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static const char tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; string out; out.reserve(3 * ((data.size() + 3) / 4)); diff --git a/src/candidate.cpp b/src/candidate.cpp index 0340d1c..43cc637 100644 --- a/src/candidate.cpp +++ b/src/candidate.cpp @@ -61,9 +61,8 @@ Candidate::Candidate(string candidate) : Candidate() { mCandidate = std::move(candidate); } -Candidate::Candidate(string candidate, string mid) - : Candidate(std::move(candidate)) { - if(!mid.empty()) +Candidate::Candidate(string candidate, string mid) : Candidate(std::move(candidate)) { + if (!mid.empty()) mMid.emplace(std::move(mid)); } diff --git a/src/capi.cpp b/src/capi.cpp index 936b7f9..5c6e25f 100644 --- a/src/capi.cpp +++ b/src/capi.cpp @@ -304,9 +304,7 @@ int rtcDeletePeerConnection(int pc) { }); } -int rtcAddDataChannel(int pc, const char *label) { - return rtcAddDataChannelEx(pc, label, nullptr); -} +int rtcAddDataChannel(int pc, const char *label) { return rtcAddDataChannelEx(pc, label, nullptr); } int rtcAddDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init) { return WRAP({ diff --git a/src/certificate.cpp b/src/certificate.cpp index f13e8ec..9618b57 100644 --- a/src/certificate.cpp +++ b/src/certificate.cpp @@ -153,22 +153,23 @@ Certificate::Certificate(string crt_pem, string key_pem) { mFingerprint = make_fingerprint(mX509.get()); } -Certificate::Certificate(shared_ptr x509, shared_ptr pkey) : - mX509(std::move(x509)), mPKey(std::move(pkey)) -{ +Certificate::Certificate(shared_ptr x509, shared_ptr pkey) + : mX509(std::move(x509)), mPKey(std::move(pkey)) { mFingerprint = make_fingerprint(mX509.get()); } string Certificate::fingerprint() const { return mFingerprint; } -std::tuple Certificate::credentials() const { return {mX509.get(), mPKey.get()}; } +std::tuple Certificate::credentials() const { + return {mX509.get(), mPKey.get()}; +} string make_fingerprint(X509 *x509) { const size_t size = 32; - unsigned char buffer[size]; - unsigned int len = size; - if (!X509_digest(x509, EVP_sha256(), buffer, &len)) - throw std::runtime_error("X509 fingerprint error"); + unsigned char buffer[size]; + unsigned int len = size; + if (!X509_digest(x509, EVP_sha256(), buffer, &len)) + throw std::runtime_error("X509 fingerprint error"); std::ostringstream oss; oss << std::hex << std::uppercase << std::setfill('0'); @@ -186,10 +187,10 @@ certificate_ptr make_certificate_impl(string commonName) { shared_ptr x509(X509_new(), X509_free); shared_ptr pkey(EVP_PKEY_new(), EVP_PKEY_free); - unique_ptr rsa(RSA_new(), RSA_free); + unique_ptr rsa(RSA_new(), RSA_free); unique_ptr exponent(BN_new(), BN_free); unique_ptr serial_number(BN_new(), BN_free); - unique_ptr name(X509_NAME_new(), X509_NAME_free); + unique_ptr name(X509_NAME_new(), X509_NAME_free); if (!x509 || !pkey || !rsa || !exponent || !serial_number || !name) throw std::runtime_error("Unable allocate structures for certificate generation"); diff --git a/src/channel.cpp b/src/channel.cpp index 17a5ad1..b5d15fe 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -26,13 +26,9 @@ size_t Channel::bufferedAmount() const { return mBufferedAmount; } size_t Channel::availableAmount() const { return 0; } -void Channel::onOpen(std::function callback) { - mOpenCallback = callback; -} +void Channel::onOpen(std::function callback) { mOpenCallback = callback; } -void Channel::onClosed(std::function callback) { - mClosedCallback = callback; -} +void Channel::onClosed(std::function callback) { mClosedCallback = callback; } void Channel::onError(std::function callback) { mErrorCallback = callback; } @@ -57,9 +53,7 @@ void Channel::onBufferedAmountLow(std::function callback) { void Channel::setBufferedAmountLowThreshold(size_t amount) { mBufferedAmountLowThreshold = amount; } -void Channel::onAvailable(std::function callback) { - mAvailableCallback = callback; -} +void Channel::onAvailable(std::function callback) { mAvailableCallback = callback; } void Channel::triggerOpen() { mOpenCallback(); } @@ -96,4 +90,3 @@ void Channel::resetCallbacks() { } } // namespace rtc - diff --git a/src/description.cpp b/src/description.cpp index a9a3e08..30b9c69 100644 --- a/src/description.cpp +++ b/src/description.cpp @@ -137,8 +137,8 @@ Description::Description(const string &sdp, Type type, Role role) } Description::Description(const string &sdp, string typeString) - : Description(sdp, !typeString.empty() ? stringToType(typeString) : Type::Unspec, Role::ActPass) { -} + : Description(sdp, !typeString.empty() ? stringToType(typeString) : Type::Unspec, + Role::ActPass) {} Description::Type Description::type() const { return mType; } @@ -177,7 +177,7 @@ void Description::addCandidate(Candidate candidate) { } void Description::addCandidates(std::vector candidates) { - for(Candidate candidate : candidates) { + for (Candidate candidate : candidates) { candidate.hintMid(bundleMid()); mCandidates.emplace_back(std::move(candidate)); } @@ -385,7 +385,8 @@ int Description::addAudio(string mid, Direction dir) { return addMedia(Audio(std::move(mid), dir)); } -std::variant Description::media(unsigned int index) { +std::variant +Description::media(unsigned int index) { if (index >= mEntries.size()) throw std::out_of_range("Media index out of range"); @@ -432,7 +433,6 @@ Description::Entry::Entry(const string &mline, string mid, Direction dir) ss >> mType; ss >> port; // ignored ss >> mDescription; - } void Description::Entry::setDirection(Direction dir) { mDirection = dir; } @@ -472,9 +472,10 @@ string Description::Entry::generateSdpLines(string_view eol) const { } for (const auto &attr : mAttributes) { - if (attr.find("extmap") == std::string::npos && attr.find("rtcp-rsize") == std::string::npos) - sdp << "a=" << attr << eol; - } + if (attr.find("extmap") == std::string::npos && + attr.find("rtcp-rsize") == std::string::npos) + sdp << "a=" << attr << eol; + } return sdp.str(); } @@ -500,38 +501,35 @@ void Description::Entry::parseSdpLine(string_view line) { mAttributes.emplace_back(line.substr(2)); } } -std::vector< string>::iterator Description::Entry::beginAttributes() { - return mAttributes.begin(); -} -std::vector< string>::iterator Description::Entry::endAttributes() { - return mAttributes.end(); -} -std::vector< string>::iterator Description::Entry::removeAttribute(std::vector::iterator it) { - return mAttributes.erase(it); +std::vector::iterator Description::Entry::beginAttributes() { return mAttributes.begin(); } +std::vector::iterator Description::Entry::endAttributes() { return mAttributes.end(); } +std::vector::iterator +Description::Entry::removeAttribute(std::vector::iterator it) { + return mAttributes.erase(it); } void Description::Media::addSSRC(uint32_t ssrc, std::string name) { - mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name); - mSsrcs.emplace_back(ssrc); + mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name); + mSsrcs.emplace_back(ssrc); } void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::string name) { - auto it = mAttributes.begin(); - while (it != mAttributes.end()) { - if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) { - it = mAttributes.erase(it); - }else - it++; - } - mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name); + auto it = mAttributes.begin(); + while (it != mAttributes.end()) { + if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) { + it = mAttributes.erase(it); + } else + it++; + } + mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name); } void Description::Media::addSSRC(uint32_t ssrc) { - mAttributes.emplace_back("ssrc:" + std::to_string(ssrc)); + mAttributes.emplace_back("ssrc:" + std::to_string(ssrc)); } bool Description::Media::hasSSRC(uint32_t ssrc) { - return std::find(mSsrcs.begin(), mSsrcs.end(), ssrc) != mSsrcs.end(); + return std::find(mSsrcs.begin(), mSsrcs.end(), ssrc) != mSsrcs.end(); } Description::Application::Application(string mid) @@ -682,48 +680,48 @@ void Description::Media::removeFormat(const string &fmt) { void Description::Video::addVideoCodec(int payloadType, const string &codec) { RTPMap map(std::to_string(payloadType) + ' ' + codec + "/90000"); - map.addFB("nack"); - map.addFB("nack pli"); -// map.addFB("nack fir"); + map.addFB("nack"); + map.addFB("nack pli"); + // map.addFB("nack fir"); map.addFB("goog-remb"); if (codec == "H264") { // 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. - map.fmtps.emplace_back("profile-level-id=4de01f;packetization-mode=1;level-asymmetry-allowed=1"); + map.fmtps.emplace_back( + "profile-level-id=4de01f;packetization-mode=1;level-asymmetry-allowed=1"); // Because certain Android devices don't like me, let us just negotiate some random { - RTPMap map(std::to_string(payloadType+1) + ' ' + codec + "/90000"); + RTPMap map(std::to_string(payloadType + 1) + ' ' + codec + "/90000"); map.addFB("nack"); - map.addFB("nack pli"); -// map.addFB("nack fir"); + map.addFB("nack pli"); + // map.addFB("nack fir"); map.addFB("goog-remb"); addRTPMap(map); - } + } } addRTPMap(map); - -// // RTX Packets -/* TODO - * 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 don't negotitate it and (maybe) break RTX support with Edge. - * Two) we do negotiate it and 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. -*/ -// RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000"); -// // TODO rtx-time is how long can a request be stashed for before needing to resend it. Needs to be parameterized -// rtx.addAttribute("apt=" + std::to_string(payloadType) + ";rtx-time=3000"); -// addRTPMap(rtx); + // // RTX Packets + /* TODO + * 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 + * don't negotitate it and (maybe) break RTX support with Edge. Two) we do negotiate it and + * 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. + */ + // RTPMap rtx(std::to_string(payloadType+1) + " rtx/90000"); + // // TODO rtx-time is how long can a request be stashed for before needing to resend it. + // 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) { - // TODO This 48000/2 should be parameterized - RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2"); - map.fmtps.emplace_back("maxaveragebitrate=96000; stereo=1; sprop-stereo=1; useinbandfec=1"); - addRTPMap(map); + // TODO This 48000/2 should be parameterized + RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2"); + map.fmtps.emplace_back("maxaveragebitrate=96000; stereo=1; sprop-stereo=1; useinbandfec=1"); + addRTPMap(map); } void Description::Video::addH264Codec(int pt) { addVideoCodec(pt, "H264"); } @@ -758,9 +756,9 @@ string Description::Media::generateSdpLines(string_view eol) const { sdp << eol; for (const auto &val : map.rtcpFbs) { - if (val != "transport-cc" ) - sdp << "a=rtcp-fb:" << map.pt << ' ' << val << eol; - } + if (val != "transport-cc") + sdp << "a=rtcp-fb:" << map.pt << ' ' << val << eol; + } for (const auto &val : map.fmtps) sdp << "a=fmtp:" << map.pt << ' ' << val << eol; } @@ -774,32 +772,32 @@ void Description::Media::parseSdpLine(string_view line) { auto [key, value] = parse_pair(attr); if (key == "rtpmap") { - auto pt = Description::Media::RTPMap::parsePT(value); - auto it = mRtpMap.find(pt); - if (it == mRtpMap.end()) { - it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap(value))).first; - }else { - it->second.setMLine(value); - } + auto pt = Description::Media::RTPMap::parsePT(value); + auto it = mRtpMap.find(pt); + if (it == mRtpMap.end()) { + it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap(value))).first; + } else { + it->second.setMLine(value); + } } else if (key == "rtcp-fb") { size_t p = value.find(' '); int pt = to_integer(value.substr(0, p)); auto it = mRtpMap.find(pt); if (it == mRtpMap.end()) { - it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first; - } - it->second.rtcpFbs.emplace_back(value.substr(p + 1)); + it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first; + } + it->second.rtcpFbs.emplace_back(value.substr(p + 1)); } else if (key == "fmtp") { size_t p = value.find(' '); int pt = to_integer(value.substr(0, p)); auto it = mRtpMap.find(pt); if (it == mRtpMap.end()) - it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first; - it->second.fmtps.emplace_back(value.substr(p + 1)); + it = mRtpMap.insert(std::make_pair(pt, Description::Media::RTPMap())).first; + it->second.fmtps.emplace_back(value.substr(p + 1)); } else if (key == "rtcp-mux") { - // always added - }else if (key == "ssrc") { - mSsrcs.emplace_back(std::stoul((std::string)value)); + // always added + } else if (key == "ssrc") { + mSsrcs.emplace_back(std::stoul((std::string)value)); } else { Entry::parseSdpLine(line); } @@ -810,37 +808,35 @@ void Description::Media::parseSdpLine(string_view line) { } } -void Description::Media::addRTPMap(const Description::Media::RTPMap& map) { - mRtpMap.emplace(map.pt, map); +void Description::Media::addRTPMap(const Description::Media::RTPMap &map) { + mRtpMap.emplace(map.pt, map); } std::vector Description::Media::getSSRCs() { - std::vector vec; - for (auto &val : mAttributes) { - PLOG_DEBUG << val; - if (val.find("ssrc:") == 0) { - vec.emplace_back(std::stoul((std::string)val.substr(5, val.find(" ")))); - } - } - return vec; + std::vector vec; + for (auto &val : mAttributes) { + PLOG_DEBUG << val; + if (val.find("ssrc:") == 0) { + vec.emplace_back(std::stoul((std::string)val.substr(5, val.find(" ")))); + } + } + return vec; } std::map::iterator Description::Media::beginMaps() { - return mRtpMap.begin(); + return mRtpMap.begin(); } std::map::iterator Description::Media::endMaps() { - return mRtpMap.end(); + return mRtpMap.end(); } std::map::iterator Description::Media::removeMap(std::map::iterator iterator) { - return mRtpMap.erase(iterator); + return mRtpMap.erase(iterator); } -Description::Media::RTPMap::RTPMap(string_view mline) { - setMLine(mline); -} +Description::Media::RTPMap::RTPMap(string_view mline) { setMLine(mline); } void Description::Media::RTPMap::removeFB(const string &str) { auto it = rtcpFbs.begin(); @@ -855,39 +851,37 @@ void Description::Media::RTPMap::removeFB(const string &str) { void Description::Media::RTPMap::addFB(const string &str) { rtcpFbs.emplace_back(str); } int Description::Media::RTPMap::parsePT(string_view view) { - size_t p = view.find(' '); + size_t p = view.find(' '); - return to_integer(view.substr(0, p)); + return to_integer(view.substr(0, p)); } void Description::Media::RTPMap::setMLine(string_view mline) { - size_t p = mline.find(' '); + size_t p = mline.find(' '); - this->pt = to_integer(mline.substr(0, p)); + this->pt = to_integer(mline.substr(0, p)); - string_view line = mline.substr(p + 1); - size_t spl = line.find('/'); - this->format = line.substr(0, spl); + string_view line = mline.substr(p + 1); + size_t spl = line.find('/'); + this->format = line.substr(0, spl); - line = line.substr(spl + 1); - spl = line.find('/'); - if (spl == string::npos) { - spl = line.find(' '); - } - if (spl == string::npos) - this->clockRate = to_integer(line); - else { - this->clockRate = to_integer(line.substr(0, spl)); - this->encParams = line.substr(spl+1); - } + line = line.substr(spl + 1); + spl = line.find('/'); + if (spl == string::npos) { + spl = line.find(' '); + } + if (spl == string::npos) + this->clockRate = to_integer(line); + else { + this->clockRate = to_integer(line.substr(0, spl)); + this->encParams = line.substr(spl + 1); + } } Description::Audio::Audio(string mid, Direction dir) : Media("audio 9 UDP/TLS/RTP/SAVPF", std::move(mid), dir) {} -void Description::Audio::addOpusCodec(int payloadType) { - addAudioCodec(payloadType, "OPUS"); -} +void Description::Audio::addOpusCodec(int payloadType) { addAudioCodec(payloadType, "OPUS"); } Description::Video::Video(string mid, Direction dir) : Media("video 9 UDP/TLS/RTP/SAVPF", std::move(mid), dir) {} diff --git a/src/dtlssrtptransport.cpp b/src/dtlssrtptransport.cpp index 32e9e0d..625172e 100644 --- a/src/dtlssrtptransport.cpp +++ b/src/dtlssrtptransport.cpp @@ -110,31 +110,30 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) { if (err == srtp_err_status_replay_fail) throw std::runtime_error("SRTCP packet is a replay"); else if (err == srtp_err_status_no_ctx) { - auto ssrc = ((RTCP_SR*) message->data())->senderSSRC(); - PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc; - addSSRC(ssrc); - if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size))) - throw std::runtime_error("SRTCP protect error, status=" + - to_string(static_cast(err))); - }else { - throw std::runtime_error("SRTCP protect error, status=" + - to_string(static_cast(err))); - } + auto ssrc = ((RTCP_SR *)message->data())->senderSSRC(); + PLOG_INFO << "Adding SSRC to SRTCP: " << ssrc; + addSSRC(ssrc); + if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size))) + throw std::runtime_error("SRTCP protect error, status=" + + to_string(static_cast(err))); + } else { + throw std::runtime_error("SRTCP protect error, status=" + + to_string(static_cast(err))); + } } PLOG_VERBOSE << "Protected SRTCP packet, size=" << size; } else { if (srtp_err_status_t err = srtp_protect(mSrtpOut, message->data(), &size)) { if (err == srtp_err_status_replay_fail) throw std::runtime_error("Outgoing SRTP packet is a replay"); - else if (err == srtp_err_status_no_ctx) { - auto ssrc = ((RTP*) message->data())->ssrc(); - PLOG_INFO << "Adding SSRC to RTP: " << ssrc; - addSSRC(ssrc); - if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size))) - throw std::runtime_error("SRTCP protect error, status=" + - to_string(static_cast(err))); - } - else + else if (err == srtp_err_status_no_ctx) { + auto ssrc = ((RTP *)message->data())->ssrc(); + PLOG_INFO << "Adding SSRC to RTP: " << ssrc; + addSSRC(ssrc); + if ((err = srtp_protect_rtcp(mSrtpOut, message->data(), &size))) + throw std::runtime_error("SRTCP protect error, status=" + + to_string(static_cast(err))); + } else throw std::runtime_error("SRTP protect error, status=" + to_string(static_cast(err))); } @@ -189,23 +188,22 @@ void DtlsSrtpTransport::incoming(message_ptr message) { PLOG_WARNING << "Incoming SRTCP packet is a replay"; else if (err == srtp_err_status_auth_fail) PLOG_WARNING << "Incoming SRTCP packet failed authentication check"; - else if (err == srtp_err_status_no_ctx) { - auto ssrc = ((RTCP_SR*) message->data())->senderSSRC(); - PLOG_INFO << "Adding SSRC to RTCP: " << ssrc; - addSSRC(ssrc); - if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size))) - throw std::runtime_error("SRTCP unprotect error, status=" + - to_string(static_cast(err))); - } - else { - PLOG_WARNING << "SRTCP unprotect error, status=" << err << " SSRC=" - << ((RTCP_SR *) message->data())->senderSSRC(); - } - return; + else if (err == srtp_err_status_no_ctx) { + auto ssrc = ((RTCP_SR *)message->data())->senderSSRC(); + PLOG_INFO << "Adding SSRC to RTCP: " << ssrc; + addSSRC(ssrc); + if ((err = srtp_unprotect_rtcp(mSrtpIn, message->data(), &size))) + throw std::runtime_error("SRTCP unprotect error, status=" + + to_string(static_cast(err))); + } else { + PLOG_WARNING << "SRTCP unprotect error, status=" << err + << " SSRC=" << ((RTCP_SR *)message->data())->senderSSRC(); + } + return; } PLOG_VERBOSE << "Unprotected SRTCP packet, size=" << size; message->type = Message::Type::Control; - auto rtp = (RTCP_SR*) message->data(); + auto rtp = (RTCP_SR *)message->data(); message->stream = rtp->senderSSRC(); } else { PLOG_VERBOSE << "Incoming SRTP packet, size=" << size; @@ -214,21 +212,21 @@ void DtlsSrtpTransport::incoming(message_ptr message) { PLOG_WARNING << "Incoming SRTP packet is a replay"; else if (err == srtp_err_status_auth_fail) PLOG_WARNING << "Incoming SRTP packet failed authentication check"; - else if (err == srtp_err_status_no_ctx) { - auto ssrc = ((RTP*) message->data())->ssrc(); - PLOG_INFO << "Adding SSRC to RTP: " << ssrc; - addSSRC(ssrc); - if ((err = srtp_unprotect(mSrtpIn, message->data(), &size))) - throw std::runtime_error("SRTCP unprotect error, status=" + - to_string(static_cast(err))); - } - else - PLOG_WARNING << "SRTP unprotect error, status=" << err << " SSRC=" << ((RTP*)message->data())->ssrc(); + else if (err == srtp_err_status_no_ctx) { + auto ssrc = ((RTP *)message->data())->ssrc(); + PLOG_INFO << "Adding SSRC to RTP: " << ssrc; + addSSRC(ssrc); + if ((err = srtp_unprotect(mSrtpIn, message->data(), &size))) + throw std::runtime_error("SRTCP unprotect error, status=" + + to_string(static_cast(err))); + } else + PLOG_WARNING << "SRTP unprotect error, status=" << err + << " SSRC=" << ((RTP *)message->data())->ssrc(); return; } PLOG_VERBOSE << "Unprotected SRTP packet, size=" << size; message->type = Message::Type::Binary; - auto rtp = (RTP*) message->data(); + auto rtp = (RTP *)message->data(); message->stream = rtp->ssrc(); } @@ -301,18 +299,18 @@ void DtlsSrtpTransport::postHandshake() { std::memcpy(mServerSessionKey + SRTP_AES_128_KEY_LEN, serverSalt, SRTP_SALT_LEN); // Add SSRC=1 as an inbound because that is what Chrome does. - srtp_policy_t inbound = {}; - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp); - inbound.ssrc.type = ssrc_specific; - inbound.ssrc.value = 1; - inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey; - inbound.next = nullptr; + srtp_policy_t inbound = {}; + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp); + inbound.ssrc.type = ssrc_specific; + inbound.ssrc.value = 1; + inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey; + inbound.next = nullptr; - if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) { - throw std::runtime_error("SRTP add inbound stream failed, status=" + - to_string(static_cast(err))); - } + if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) { + throw std::runtime_error("SRTP add inbound stream failed, status=" + + to_string(static_cast(err))); + } mInitDone = true; } @@ -321,34 +319,33 @@ void DtlsSrtpTransport::addSSRC(uint32_t ssrc) { if (!mInitDone) throw std::logic_error("Attempted to add SSRC before SRTP keying material is derived"); - srtp_policy_t inbound = {}; - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp); - inbound.ssrc.type = ssrc_specific; - inbound.ssrc.value = ssrc; - inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey; - inbound.next = nullptr; - inbound.allow_repeat_tx = true; + srtp_policy_t inbound = {}; + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&inbound.rtcp); + inbound.ssrc.type = ssrc_specific; + inbound.ssrc.value = ssrc; + inbound.key = mIsClient ? mServerSessionKey : mClientSessionKey; + inbound.next = nullptr; + inbound.allow_repeat_tx = true; - if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) - throw std::runtime_error("SRTP add inbound stream failed, status=" + - to_string(static_cast(err))); + if (srtp_err_status_t err = srtp_add_stream(mSrtpIn, &inbound)) + throw std::runtime_error("SRTP add inbound stream failed, status=" + + to_string(static_cast(err))); - srtp_policy_t outbound = {}; - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtcp); - outbound.ssrc.type = ssrc_specific; - outbound.ssrc.value = ssrc; - outbound.key = mIsClient ? mClientSessionKey : mServerSessionKey; - outbound.next = nullptr; - outbound.allow_repeat_tx = true; + srtp_policy_t outbound = {}; + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&outbound.rtcp); + outbound.ssrc.type = ssrc_specific; + outbound.ssrc.value = ssrc; + outbound.key = mIsClient ? mClientSessionKey : mServerSessionKey; + outbound.next = nullptr; + outbound.allow_repeat_tx = true; - if (srtp_err_status_t err = srtp_add_stream(mSrtpOut, &outbound)) - throw std::runtime_error("SRTP add outbound stream failed, status=" + - to_string(static_cast(err))); + if (srtp_err_status_t err = srtp_add_stream(mSrtpOut, &outbound)) + throw std::runtime_error("SRTP add outbound stream failed, status=" + + to_string(static_cast(err))); } - } // namespace rtc #endif diff --git a/src/dtlstransport.cpp b/src/dtlstransport.cpp index b7e115a..01b74b7 100644 --- a/src/dtlstransport.cpp +++ b/src/dtlstransport.cpp @@ -177,7 +177,7 @@ void DtlsTransport::runRecvLoop() { // Receive loop try { PLOG_INFO << "DTLS handshake finished"; - postHandshake(); + postHandshake(); changeState(State::Connected); const size_t bufferSize = maxMtu; @@ -575,4 +575,3 @@ long DtlsTransport::BioMethodCtrl(BIO * /*bio*/, int cmd, long /*num*/, void * / #endif } // namespace rtc - diff --git a/src/dtlstransport.hpp b/src/dtlstransport.hpp index dc18f56..d262be1 100644 --- a/src/dtlstransport.hpp +++ b/src/dtlstransport.hpp @@ -92,4 +92,3 @@ protected: } // namespace rtc #endif - diff --git a/src/icetransport.cpp b/src/icetransport.cpp index 98d2c3d..ae3b269 100644 --- a/src/icetransport.cpp +++ b/src/icetransport.cpp @@ -130,9 +130,7 @@ IceTransport::~IceTransport() { mAgent.reset(); } -bool IceTransport::stop() { - return Transport::stop(); -} +bool IceTransport::stop() { return Transport::stop(); } Description::Role IceTransport::role() const { return mRole; } @@ -141,11 +139,13 @@ Description IceTransport::getLocalDescription(Description::Type type) const { if (juice_get_local_description(mAgent.get(), sdp, JUICE_MAX_SDP_STRING_LEN) < 0) throw std::runtime_error("Failed to generate local SDP"); - return Description(string(sdp), type, type == Description::Type::Offer ? Description::Role::ActPass : mRole); + return Description(string(sdp), type, + type == Description::Type::Offer ? Description::Role::ActPass : mRole); } void IceTransport::setRemoteDescription(const Description &description) { - mRole = description.role() == Description::Role::Active ? Description::Role::Passive : Description::Role::Active; + mRole = description.role() == Description::Role::Active ? Description::Role::Passive + : Description::Role::Active; mMid = description.bundleMid(); if (juice_set_remote_description(mAgent.get(), @@ -191,7 +191,7 @@ bool IceTransport::getSelectedCandidatePair(Candidate *local, Candidate *remote) char sdpLocal[JUICE_MAX_CANDIDATE_SDP_STRING_LEN]; char sdpRemote[JUICE_MAX_CANDIDATE_SDP_STRING_LEN]; if (juice_get_selected_candidates(mAgent.get(), sdpLocal, JUICE_MAX_CANDIDATE_SDP_STRING_LEN, - sdpRemote, JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0) { + sdpRemote, JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0) { if (local) { *local = Candidate(sdpLocal, mMid); local->resolve(Candidate::ResolveMode::Simple); @@ -736,15 +736,17 @@ void IceTransport::LogCallback(const gchar * /*logDomain*/, GLogLevelFlags logLe bool IceTransport::getSelectedCandidatePair(Candidate *local, Candidate *remote) { NiceCandidate *niceLocal, *niceRemote; - if(!nice_agent_get_selected_pair(mNiceAgent.get(), mStreamId, 1, &niceLocal, &niceRemote)) + if (!nice_agent_get_selected_pair(mNiceAgent.get(), mStreamId, 1, &niceLocal, &niceRemote)) return false; gchar *sdpLocal = nice_agent_generate_local_candidate_sdp(mNiceAgent.get(), niceLocal); - if(local) *local = Candidate(sdpLocal, mMid); + if (local) + *local = Candidate(sdpLocal, mMid); g_free(sdpLocal); gchar *sdpRemote = nice_agent_generate_local_candidate_sdp(mNiceAgent.get(), niceRemote); - if(remote) *remote = Candidate(sdpRemote, mMid); + if (remote) + *remote = Candidate(sdpRemote, mMid); g_free(sdpRemote); if (local) diff --git a/src/icetransport.hpp b/src/icetransport.hpp index 7fe33e5..621ffb4 100644 --- a/src/icetransport.hpp +++ b/src/icetransport.hpp @@ -20,8 +20,8 @@ #define RTC_ICE_TRANSPORT_H #include "candidate.hpp" -#include "description.hpp" #include "configuration.hpp" +#include "description.hpp" #include "include.hpp" #include "peerconnection.hpp" #include "transport.hpp" diff --git a/src/init.cpp b/src/init.cpp index 748c8c6..8430d50 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -142,4 +142,3 @@ Init::~Init() { } } // namespace rtc - diff --git a/src/log.cpp b/src/log.cpp index b6dc6c0..ba783e6 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -44,5 +44,4 @@ void InitLogger(plog::Severity severity, plog::IAppender *appender) { logger->addAppender(appender); } } -} - +} // namespace rtc diff --git a/src/peerconnection.cpp b/src/peerconnection.cpp index fda4b9b..3026460 100644 --- a/src/peerconnection.cpp +++ b/src/peerconnection.cpp @@ -119,7 +119,6 @@ bool PeerConnection::hasMedia() const { void PeerConnection::setLocalDescription(Description::Type type) { PLOG_VERBOSE << "Setting local description, type=" << Description::typeToString(type); - SignalingState signalingState = mSignalingState.load(); if (type == Description::Type::Rollback) { if (signalingState == SignalingState::HaveLocalOffer || @@ -679,205 +678,201 @@ void PeerConnection::forwardMedia(message_ptr message) { if (!message) return; - // Browsers like to compound their packets with a random SSRC. // we have to do this monstrosity to distribute the report blocks - std::optional mediaLine; - if (message->type == Message::Control) { - size_t offset = 0; - std::vector ssrcsFound; - bool hasFound = false; + std::optional mediaLine; + if (message->type == Message::Control) { + size_t offset = 0; + std::vector ssrcsFound; + bool hasFound = false; - while ((sizeof(rtc::RTCP_HEADER) + offset) <= message->size()) { - auto header = (rtc::RTCP_HEADER *) (message->data() + offset); - if (header->lengthInBytes() > message->size() - offset) { - PLOG_WARNING << "Packet was truncated"; - break; - } - offset += header->lengthInBytes(); - if (header->payloadType() == 205 || header->payloadType() == 206) { - auto rtcpfb = (RTCP_FB_HEADER *) header; - auto ssrc = rtcpfb->getPacketSenderSSRC(); - if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { - mediaLine = getMLineFromSSRC(ssrc); - if (mediaLine.has_value()) { - hasFound = true; - std::shared_lock lock(mTracksMutex); // read-only - if (auto track = mTrackLines[*mediaLine].lock()) { - track->incoming(message); - } - ssrcsFound.emplace_back(ssrc); - } - } + while ((sizeof(rtc::RTCP_HEADER) + offset) <= message->size()) { + auto header = (rtc::RTCP_HEADER *)(message->data() + offset); + if (header->lengthInBytes() > message->size() - offset) { + PLOG_WARNING << "Packet was truncated"; + break; + } + offset += header->lengthInBytes(); + if (header->payloadType() == 205 || header->payloadType() == 206) { + auto rtcpfb = (RTCP_FB_HEADER *)header; + auto ssrc = rtcpfb->getPacketSenderSSRC(); + if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { + mediaLine = getMLineFromSSRC(ssrc); + if (mediaLine.has_value()) { + hasFound = true; + std::shared_lock lock(mTracksMutex); // read-only + if (auto track = mTrackLines[*mediaLine].lock()) { + track->incoming(message); + } + ssrcsFound.emplace_back(ssrc); + } + } - ssrc = rtcpfb->getMediaSourceSSRC(); - if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { - mediaLine = getMLineFromSSRC(ssrc); - if (mediaLine.has_value()) { - hasFound = true; - std::shared_lock lock(mTracksMutex); // read-only - if (auto track = mTrackLines[*mediaLine].lock()) { - track->incoming(message); - } - ssrcsFound.emplace_back(ssrc); - } - } - }else if (header->payloadType() == 200 || header->payloadType() == 201) { - auto rtcpsr = (RTCP_SR *) header; - auto ssrc = rtcpsr->senderSSRC(); - if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { - mediaLine = getMLineFromSSRC(ssrc); - if (mediaLine.has_value()) { - hasFound = true; - std::shared_lock lock(mTracksMutex); // read-only - if (auto track = mTrackLines[*mediaLine].lock()) { - track->incoming(message); - } - ssrcsFound.emplace_back(ssrc); - } - } - for (int i = 0; i < rtcpsr->header.reportCount(); i++) { - auto block = rtcpsr->getReportBlock(i); - ssrc = block->getSSRC(); - if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { - mediaLine = getMLineFromSSRC(ssrc); - if (mediaLine.has_value()) { - hasFound = true; - std::shared_lock lock(mTracksMutex); // read-only - if (auto track = mTrackLines[*mediaLine].lock()) { - track->incoming(message); - } - ssrcsFound.emplace_back(ssrc); - } - } - } - } else { - //PT=202 == SDES - //PT=207 == Extended Report - if (header->payloadType() != 202 && header->payloadType() != 207) { - PLOG_WARNING << "Unknown packet type: " << (int) header->version() << " " << header->payloadType() << ""; - } - } - } + ssrc = rtcpfb->getMediaSourceSSRC(); + if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { + mediaLine = getMLineFromSSRC(ssrc); + if (mediaLine.has_value()) { + hasFound = true; + std::shared_lock lock(mTracksMutex); // read-only + if (auto track = mTrackLines[*mediaLine].lock()) { + track->incoming(message); + } + ssrcsFound.emplace_back(ssrc); + } + } + } else if (header->payloadType() == 200 || header->payloadType() == 201) { + auto rtcpsr = (RTCP_SR *)header; + auto ssrc = rtcpsr->senderSSRC(); + if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { + mediaLine = getMLineFromSSRC(ssrc); + if (mediaLine.has_value()) { + hasFound = true; + std::shared_lock lock(mTracksMutex); // read-only + if (auto track = mTrackLines[*mediaLine].lock()) { + track->incoming(message); + } + ssrcsFound.emplace_back(ssrc); + } + } + for (int i = 0; i < rtcpsr->header.reportCount(); i++) { + auto block = rtcpsr->getReportBlock(i); + ssrc = block->getSSRC(); + if (std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) { + mediaLine = getMLineFromSSRC(ssrc); + if (mediaLine.has_value()) { + hasFound = true; + std::shared_lock lock(mTracksMutex); // read-only + if (auto track = mTrackLines[*mediaLine].lock()) { + track->incoming(message); + } + ssrcsFound.emplace_back(ssrc); + } + } + } + } else { + // PT=202 == SDES + // PT=207 == Extended Report + if (header->payloadType() != 202 && header->payloadType() != 207) { + PLOG_WARNING << "Unknown packet type: " << (int)header->version() << " " + << header->payloadType() << ""; + } + } + } - if (hasFound) - return; - } + if (hasFound) + return; + } - unsigned int ssrc = message->stream; - mediaLine = getMLineFromSSRC(ssrc); + unsigned int ssrc = message->stream; + mediaLine = getMLineFromSSRC(ssrc); if (!mediaLine) { - /* TODO - * So the problem is that when stop sending streams, we stop getting report blocks for those streams - * Therefore when we get compound RTCP packets, they are empty, and we can't forward them. - * Therefore, it is expected that we don't know where to forward packets. - * Is this ideal? No! Do I know how to fix it? No! - */ - // PLOG_WARNING << "Track not found for SSRC " << ssrc << ", dropping"; + /* TODO + * So the problem is that when stop sending streams, we stop getting report blocks for + * those streams Therefore when we get compound RTCP packets, they are empty, and we can't + * forward them. Therefore, it is expected that we don't know where to forward packets. Is + * this ideal? No! Do I know how to fix it? No! + */ + // PLOG_WARNING << "Track not found for SSRC " << ssrc << ", dropping"; return; } std::shared_lock lock(mTracksMutex); // read-only - if (auto track = mTrackLines[*mediaLine].lock()) { - track->incoming(message); - } + if (auto track = mTrackLines[*mediaLine].lock()) { + track->incoming(message); + } } std::optional PeerConnection::getMLineFromSSRC(SSRC ssrc) { - if (auto it = mMLineFromSssrc.find(ssrc); it != mMLineFromSssrc.end()) { - return it->second; - }else { - { - std::lock_guard lock(mRemoteDescriptionMutex); - if (!mRemoteDescription) - return nullopt; - for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) { - if (std::visit( - rtc::overloaded{[&](Description::Application *) -> bool { - return false; - }, - [&](Description::Media *media) -> bool { - return media->hasSSRC(ssrc); - }}, - mRemoteDescription->media(i))) { + if (auto it = mMLineFromSssrc.find(ssrc); it != mMLineFromSssrc.end()) { + return it->second; + } else { + { + std::lock_guard lock(mRemoteDescriptionMutex); + if (!mRemoteDescription) + return nullopt; + for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) { + if (std::visit( + rtc::overloaded{[&](Description::Application *) -> bool { return false; }, + [&](Description::Media *media) -> bool { + return media->hasSSRC(ssrc); + }}, + mRemoteDescription->media(i))) { - mMLineFromSssrc.emplace(ssrc, i); - return i; - } - } - } - { - std::lock_guard lock(mLocalDescriptionMutex); - if (!mLocalDescription) - return nullopt; - for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) { - if (std::visit( - rtc::overloaded{[&](Description::Application *) -> bool { - return false; - }, - [&](Description::Media *media) -> bool { - return media->hasSSRC(ssrc); - }}, - mLocalDescription->media(i))) { + mMLineFromSssrc.emplace(ssrc, i); + return i; + } + } + } + { + std::lock_guard lock(mLocalDescriptionMutex); + if (!mLocalDescription) + return nullopt; + for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) { + if (std::visit( + rtc::overloaded{[&](Description::Application *) -> bool { return false; }, + [&](Description::Media *media) -> bool { + return media->hasSSRC(ssrc); + }}, + mLocalDescription->media(i))) { - mMLineFromSssrc.emplace(ssrc, i); - return i; - } - } - } - } - return std::nullopt; + mMLineFromSssrc.emplace(ssrc, i); + return i; + } + } + } + } + return std::nullopt; } std::optional PeerConnection::getMidFromSSRC(SSRC ssrc) { - if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) { - return it->second; - } else { - { - std::lock_guard lock(mRemoteDescriptionMutex); - if (!mRemoteDescription) - return nullopt; - for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) { - if (auto found = std::visit( - rtc::overloaded{[&](Description::Application *) -> std::optional { - return std::nullopt; - }, - [&](Description::Media *media) -> std::optional { - return media->hasSSRC(ssrc) - ? std::make_optional(media->mid()) - : nullopt; - }}, - mRemoteDescription->media(i))) { + if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) { + return it->second; + } else { + { + std::lock_guard lock(mRemoteDescriptionMutex); + if (!mRemoteDescription) + return nullopt; + for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) { + if (auto found = std::visit( + rtc::overloaded{[&](Description::Application *) -> std::optional { + return std::nullopt; + }, + [&](Description::Media *media) -> std::optional { + return media->hasSSRC(ssrc) + ? std::make_optional(media->mid()) + : nullopt; + }}, + mRemoteDescription->media(i))) { - mMidFromSssrc.emplace(ssrc, *found); - return *found; - } - } - } - { - std::lock_guard lock(mLocalDescriptionMutex); - if (!mLocalDescription) - return nullopt; - for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) { - if (auto found = std::visit( - rtc::overloaded{[&](Description::Application *) -> std::optional { - return std::nullopt; - }, - [&](Description::Media *media) -> std::optional { - return media->hasSSRC(ssrc) - ? std::make_optional(media->mid()) - : nullopt; - }}, - mLocalDescription->media(i))) { + mMidFromSssrc.emplace(ssrc, *found); + return *found; + } + } + } + { + std::lock_guard lock(mLocalDescriptionMutex); + if (!mLocalDescription) + return nullopt; + for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) { + if (auto found = std::visit( + rtc::overloaded{[&](Description::Application *) -> std::optional { + return std::nullopt; + }, + [&](Description::Media *media) -> std::optional { + return media->hasSSRC(ssrc) + ? std::make_optional(media->mid()) + : nullopt; + }}, + mLocalDescription->media(i))) { - mMidFromSssrc.emplace(ssrc, *found); - return *found; - } - } - } + mMidFromSssrc.emplace(ssrc, *found); + return *found; + } + } + } } - return nullopt; + return nullopt; } void PeerConnection::forwardBufferedAmount(uint16_t stream, size_t amount) { @@ -979,7 +974,7 @@ void PeerConnection::incomingTrack(Description::Media description) { if (mTracks.find(description.mid()) == mTracks.end()) { auto track = std::make_shared(std::move(description)); mTracks.emplace(std::make_pair(track->mid(), track)); - mTrackLines.emplace_back(track); + mTrackLines.emplace_back(track); triggerTrack(track); } } @@ -1092,21 +1087,21 @@ void PeerConnection::processLocalDescription(Description description) { auto reciprocated = remoteMedia->reciprocate(); #if !RTC_ENABLE_MEDIA - // No media support, mark as inactive - reciprocated.setDirection(Description::Direction::Inactive); + // No media support, mark as inactive + reciprocated.setDirection(Description::Direction::Inactive); #endif - incomingTrack(reciprocated); + incomingTrack(reciprocated); - PLOG_DEBUG - << "Reciprocating media in local description, mid=\"" - << reciprocated.mid() << "\", active=" << std::boolalpha - << (reciprocated.direction() != Description::Direction::Inactive); + PLOG_DEBUG + << "Reciprocating media in local description, mid=\"" + << reciprocated.mid() << "\", active=" << std::boolalpha + << (reciprocated.direction() != Description::Direction::Inactive); - description.addMedia(std::move(reciprocated)); - }, - }, - remote->media(i)); - } + description.addMedia(std::move(reciprocated)); + }, + }, + remote->media(i)); + } if (description.type() == Description::Type::Offer) { // This is an offer, add locally created data channels and tracks @@ -1128,23 +1123,23 @@ void PeerConnection::processLocalDescription(Description description) { // Add media for local tracks std::shared_lock lock(mTracksMutex); - for (auto it = mTrackLines.begin(); it != mTrackLines.end(); ++it) { - if (auto track = it->lock()) { - if (description.hasMid(track->mid())) - continue; + for (auto it = mTrackLines.begin(); it != mTrackLines.end(); ++it) { + if (auto track = it->lock()) { + if (description.hasMid(track->mid())) + continue; - auto media = track->description(); + auto media = track->description(); #if !RTC_ENABLE_MEDIA - // No media support, mark as inactive - media.setDirection(Description::Direction::Inactive); + // No media support, mark as inactive + media.setDirection(Description::Direction::Inactive); #endif - PLOG_DEBUG << "Adding media to local description, mid=\"" << media.mid() - << "\", active=" << std::boolalpha - << (media.direction() != Description::Direction::Inactive); + PLOG_DEBUG << "Adding media to local description, mid=\"" << media.mid() + << "\", active=" << std::boolalpha + << (media.direction() != Description::Direction::Inactive); - description.addMedia(std::move(media)); - } - } + description.addMedia(std::move(media)); + } + } } // Set local fingerprint (wait for certificate if necessary) diff --git a/src/processor.cpp b/src/processor.cpp index 6385be8..01b5c40 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -41,4 +41,3 @@ void Processor::schedule() { } } // namespace rtc - diff --git a/src/processor.hpp b/src/processor.hpp index 466f7b1..6c6f0ec 100644 --- a/src/processor.hpp +++ b/src/processor.hpp @@ -44,8 +44,7 @@ public: void join(); - template - void enqueue(F &&f, Args &&... args); + template void enqueue(F &&f, Args &&... args); protected: void schedule(); diff --git a/src/rtcp.cpp b/src/rtcp.cpp index 80e5a54..f8046ae 100644 --- a/src/rtcp.cpp +++ b/src/rtcp.cpp @@ -19,9 +19,9 @@ #include "rtcp.hpp" +#include "track.hpp" #include #include -#include "track.hpp" #ifdef _WIN32 #include @@ -29,12 +29,9 @@ #include #endif - namespace rtc { -rtc::message_ptr RtcpReceivingSession::outgoing(rtc::message_ptr ptr) { - return ptr; -} +rtc::message_ptr RtcpReceivingSession::outgoing(rtc::message_ptr ptr) { return ptr; } rtc::message_ptr RtcpReceivingSession::incoming(rtc::message_ptr ptr) { if (ptr->type == rtc::Message::Type::Binary) { @@ -98,7 +95,7 @@ void RtcpReceivingSession::pushREMB(unsigned int bitrate) { remb->preparePacket(mSsrc, 1, bitrate); remb->setSsrc(0, mSsrc); - send(msg); + send(msg); } void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) { @@ -109,13 +106,13 @@ void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) { lastSR_delay); rr->log(); - send(msg); + send(msg); } bool RtcpReceivingSession::send(message_ptr msg) { try { - outgoingCallback(std::move(msg)); - return true; + outgoingCallback(std::move(msg)); + return true; } catch (const std::exception &e) { LOG_DEBUG << "RTCP tx failed: " << e.what(); } @@ -123,19 +120,18 @@ bool RtcpReceivingSession::send(message_ptr msg) { } bool RtcpReceivingSession::requestKeyframe() { - pushPLI(); - return true; // TODO Make this false when it is impossible (i.e. Opus). + pushPLI(); + return true; // TODO Make this false when it is impossible (i.e. Opus). } void RtcpReceivingSession::pushPLI() { - auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control); - auto *pli = (rtc::RTCP_PLI *) msg->data(); - pli->preparePacket(mSsrc); - send(msg); + auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control); + auto *pli = (rtc::RTCP_PLI *)msg->data(); + pli->preparePacket(mSsrc); + send(msg); } -void RtcpHandler::onOutgoing(const std::function& cb) { - this->outgoingCallback = synchronized_callback(cb); +void RtcpHandler::onOutgoing(const std::function &cb) { + this->outgoingCallback = synchronized_callback(cb); } } // namespace rtc - diff --git a/src/sctptransport.hpp b/src/sctptransport.hpp index 49781ed..e099877 100644 --- a/src/sctptransport.hpp +++ b/src/sctptransport.hpp @@ -100,7 +100,7 @@ private: std::mutex mWriteMutex; std::condition_variable mWrittenCondition; - std::atomic mWritten = false; // written outside lock + std::atomic mWritten = false; // written outside lock std::atomic mWrittenOnce = false; // same binary mPartialMessage, mPartialNotification; diff --git a/src/threadpool.cpp b/src/threadpool.cpp index 0d5c6b5..f43ee88 100644 --- a/src/threadpool.cpp +++ b/src/threadpool.cpp @@ -75,4 +75,3 @@ std::function ThreadPool::dequeue() { } } // namespace rtc - diff --git a/src/threadpool.hpp b/src/threadpool.hpp index 3ca1464..6df8cfd 100644 --- a/src/threadpool.hpp +++ b/src/threadpool.hpp @@ -75,13 +75,13 @@ auto ThreadPool::enqueue(F &&f, Args &&... args) -> invoke_future_t using R = std::invoke_result_t, std::decay_t...>; auto bound = std::bind(std::forward(f), std::forward(args)...); auto task = std::make_shared>([bound = std::move(bound)]() mutable { - try { - return bound(); - } catch (const std::exception &e) { - PLOG_WARNING << e.what(); - throw; - } - }); + try { + return bound(); + } catch (const std::exception &e) { + PLOG_WARNING << e.what(); + throw; + } + }); std::future result = task->get_future(); mTasks.emplace([task = std::move(task), token = Init::Token()]() { return (*task)(); }); diff --git a/src/tls.cpp b/src/tls.cpp index 75c1233..d91383f 100644 --- a/src/tls.cpp +++ b/src/tls.cpp @@ -127,4 +127,3 @@ bool check(SSL *ssl, int ret, const string &message) { } // namespace rtc::openssl #endif - diff --git a/src/tls.hpp b/src/tls.hpp index 32bc8c4..8a2e150 100644 --- a/src/tls.hpp +++ b/src/tls.hpp @@ -56,12 +56,12 @@ gnutls_datum_t make_datum(char *data, size_t size); #include #include +#include #include #include #include -#include #include -#include +#include #ifndef BIO_EOF #define BIO_EOF -1 diff --git a/src/tlstransport.cpp b/src/tlstransport.cpp index 29c32e1..246c3f1 100644 --- a/src/tlstransport.cpp +++ b/src/tlstransport.cpp @@ -62,10 +62,10 @@ TlsTransport::TlsTransport(shared_ptr lower, string host, state_ca gnutls::check(gnutls_priority_set_direct(mSession, priorities, &err_pos), "Failed to set TLS priorities"); - PLOG_VERBOSE << "Server Name Indication: " << mHost; + PLOG_VERBOSE << "Server Name Indication: " << mHost; gnutls_server_name_set(mSession, GNUTLS_NAME_DNS, mHost.data(), mHost.size()); - gnutls_session_set_ptr(mSession, this); + gnutls_session_set_ptr(mSession, this); gnutls_transport_set_ptr(mSession, this); gnutls_transport_set_push_function(mSession, WriteCallback); gnutls_transport_set_pull_function(mSession, ReadCallback); @@ -110,7 +110,7 @@ bool TlsTransport::send(message_ptr message) { PLOG_VERBOSE << "Send size=" << message->size(); - if(message->size() == 0) + if (message->size() == 0) return true; ssize_t ret; @@ -207,10 +207,10 @@ ssize_t TlsTransport::ReadCallback(gnutls_transport_ptr_t ptr, void *data, size_ message_ptr &message = t->mIncomingMessage; size_t &position = t->mIncomingMessagePosition; - if(message && position >= message->size()) + if (message && position >= message->size()) message.reset(); - if(!message) { + if (!message) { position = 0; while (auto next = t->mIncomingQueue.pop()) { message = *next; @@ -221,15 +221,14 @@ ssize_t TlsTransport::ReadCallback(gnutls_transport_ptr_t ptr, void *data, size_ } } - if(message) { + if (message) { size_t available = message->size() - position; ssize_t len = std::min(maxlen, available); std::memcpy(data, message->data() + position, len); - position+= len; + position += len; gnutls_transport_set_errno(t->mSession, 0); return len; - } - else { + } else { // Closed gnutls_transport_set_errno(t->mSession, 0); return 0; diff --git a/src/track.cpp b/src/track.cpp index e52010d..0a24523 100644 --- a/src/track.cpp +++ b/src/track.cpp @@ -32,9 +32,8 @@ string Track::mid() const { return mMediaDescription.mid(); } Description::Media Track::description() const { return mMediaDescription; } - void Track::setDescription(Description::Media description) { - if(description.mid() != mMediaDescription.mid()) + if (description.mid() != mMediaDescription.mid()) throw std::logic_error("Media description mid does not match track mid"); mMediaDescription = std::move(description); @@ -80,9 +79,7 @@ size_t Track::maxMessageSize() const { return 65535 - 12 - 4; // SRTP/UDP } -size_t Track::availableAmount() const { - return mRecvQueue.amount(); -} +size_t Track::availableAmount() const { return mRecvQueue.amount(); } #if RTC_ENABLE_MEDIA void Track::open(shared_ptr transport) { @@ -93,34 +90,34 @@ void Track::open(shared_ptr transport) { bool Track::outgoing(message_ptr message) { - if (mRtcpHandler) { - message = mRtcpHandler->outgoing(message); - if (!message) - return false; - } + if (mRtcpHandler) { + message = mRtcpHandler->outgoing(message); + if (!message) + return false; + } - auto direction = mMediaDescription.direction(); - if ((direction == Description::Direction::RecvOnly || - direction == Description::Direction::Inactive) && - message->type != Message::Control) { - PLOG_WARNING << "Track media direction does not allow transmission, dropping"; - return false; - } + auto direction = mMediaDescription.direction(); + if ((direction == Description::Direction::RecvOnly || + direction == Description::Direction::Inactive) && + message->type != Message::Control) { + PLOG_WARNING << "Track media direction does not allow transmission, dropping"; + return false; + } - if (mIsClosed) - throw std::runtime_error("Track is closed"); + if (mIsClosed) + throw std::runtime_error("Track is closed"); - if (message->size() > maxMessageSize()) - throw std::runtime_error("Message size exceeds limit"); + if (message->size() > maxMessageSize()) + throw std::runtime_error("Message size exceeds limit"); #if RTC_ENABLE_MEDIA - auto transport = mDtlsSrtpTransport.lock(); - if (!transport) - throw std::runtime_error("Track transport is not open"); + auto transport = mDtlsSrtpTransport.lock(); + if (!transport) + throw std::runtime_error("Track transport is not open"); - return transport->sendMedia(message); + return transport->sendMedia(message); #else - PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)"; + PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)"; return false; #endif } @@ -130,10 +127,10 @@ void Track::incoming(message_ptr message) { return; if (mRtcpHandler) { - message = mRtcpHandler->incoming(message); - if (!message) - return ; - } + message = mRtcpHandler->incoming(message); + if (!message) + return; + } auto direction = mMediaDescription.direction(); if ((direction == Description::Direction::SendOnly || @@ -154,30 +151,27 @@ void Track::incoming(message_ptr message) { void Track::setRtcpHandler(std::shared_ptr handler) { mRtcpHandler = std::move(handler); if (mRtcpHandler) { - mRtcpHandler->onOutgoing([&]([[maybe_unused]] const rtc::message_ptr& message) { - #if RTC_ENABLE_MEDIA + mRtcpHandler->onOutgoing([&]([[maybe_unused]] const rtc::message_ptr &message) { +#if RTC_ENABLE_MEDIA auto transport = mDtlsSrtpTransport.lock(); if (!transport) - throw std::runtime_error("Track transport is not open"); + throw std::runtime_error("Track transport is not open"); return transport->sendMedia(message); - #else +#else PLOG_WARNING << "Ignoring track send (not compiled with SRTP support)"; - return false; - #endif + return false; +#endif }); } } bool Track::requestKeyframe() { - if (mRtcpHandler) - return mRtcpHandler->requestKeyframe(); - return false; + if (mRtcpHandler) + return mRtcpHandler->requestKeyframe(); + return false; } -std::shared_ptr Track::getRtcpHandler() { - return mRtcpHandler; -} +std::shared_ptr Track::getRtcpHandler() { return mRtcpHandler; } } // namespace rtc - diff --git a/src/transport.hpp b/src/transport.hpp index 0a765d7..d88eb14 100644 --- a/src/transport.hpp +++ b/src/transport.hpp @@ -36,8 +36,7 @@ public: using state_callback = std::function; Transport(std::shared_ptr lower = nullptr, state_callback callback = nullptr) - : mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) { - } + : mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) {} virtual ~Transport() { stop(); } diff --git a/src/verifiedtlstransport.cpp b/src/verifiedtlstransport.cpp index 1924639..f03ba65 100644 --- a/src/verifiedtlstransport.cpp +++ b/src/verifiedtlstransport.cpp @@ -28,7 +28,6 @@ using std::weak_ptr; namespace rtc { - VerifiedTlsTransport::VerifiedTlsTransport(shared_ptr lower, string host, state_callback callback) : TlsTransport(std::move(lower), std::move(host), std::move(callback)) { @@ -48,4 +47,3 @@ VerifiedTlsTransport::~VerifiedTlsTransport() {} } // namespace rtc #endif - diff --git a/src/websocket.cpp b/src/websocket.cpp index dfd6211..95dcac6 100644 --- a/src/websocket.cpp +++ b/src/websocket.cpp @@ -256,7 +256,8 @@ shared_ptr WebSocket::initTlsTransport() { if (mConfig.disableTlsVerification) transport = std::make_shared(lower, mHostname, stateChangeCallback); else - transport = std::make_shared(lower, mHostname, stateChangeCallback); + transport = + std::make_shared(lower, mHostname, stateChangeCallback); #endif std::atomic_store(&mTlsTransport, transport); diff --git a/src/wstransport.cpp b/src/wstransport.cpp index 3e7ae23..be31ba3 100644 --- a/src/wstransport.cpp +++ b/src/wstransport.cpp @@ -17,9 +17,9 @@ */ #include "wstransport.hpp" +#include "base64.hpp" #include "tcptransport.hpp" #include "tlstransport.hpp" -#include "base64.hpp" #if RTC_ENABLE_WEBSOCKET diff --git a/test/websocket.cpp b/test/websocket.cpp index c6ca0b9..4f66ec6 100644 --- a/test/websocket.cpp +++ b/test/websocket.cpp @@ -20,11 +20,11 @@ #if RTC_ENABLE_WEBSOCKET +#include #include #include #include #include -#include using namespace rtc; using namespace std; @@ -56,7 +56,7 @@ void test_websocket() { ws->onMessage([&received, &myMessage](variant message) { if (holds_alternative(message)) { string str = std::move(get(message)); - if((received = (str == myMessage))) + if ((received = (str == myMessage))) cout << "WebSocket: Received expected message" << endl; else cout << "WebSocket: Received UNEXPECTED message" << endl; @@ -72,7 +72,7 @@ void test_websocket() { if (!ws->isOpen()) throw runtime_error("WebSocket is not open"); - if(!received) + if (!received) throw runtime_error("Expected message not received"); ws->close(); @@ -86,4 +86,3 @@ void test_websocket() { } #endif -