Browse Source

Fixed the distribution of RTCP packets regarding RTCP and RTCPFB packets

Staz M 4 years ago
parent
commit
c0756aaa05
3 changed files with 85 additions and 19 deletions
  1. 3 0
      include/rtc/rtp.hpp
  2. 1 1
      src/dtlssrtptransport.cpp
  3. 81 18
      src/peerconnection.cpp

+ 3 - 0
include/rtc/rtp.hpp

@@ -171,6 +171,9 @@ public:
     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); }

+ 1 - 1
src/dtlssrtptransport.cpp

@@ -124,7 +124,7 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
 	} else {
 		if (srtp_err_status_t err = srtp_protect(mSrtpOut, message->data(), &size)) {
 			if (err == srtp_err_status_replay_fail)
-				throw std::runtime_error("SRTP packet is a replay");
+				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;

+ 81 - 18
src/peerconnection.cpp

@@ -549,32 +549,95 @@ void PeerConnection::forwardMedia(message_ptr message) {
 	if (!message)
 		return;
 
-	unsigned int ssrc = message->stream;
-	std::optional<string> mid = getMidFromSSRC(ssrc);
 
 	// Browsers like to compound their packets with a random SSRC.
 	// we have to do this monstrosity to distribute the report blocks
-    if (!mid && message->type == Message::Control) {
-        RTCP_RR* sr = (RTCP_RR*) message->data();
-        if (sr->isReceiverReport() ||sr->isSenderReport()) {
-            bool hasFound = false;
-            for (int i = 0; i < sr->header.reportCount(); i++) {
-                auto block = sr->getReportBlock(i);
-                auto ssrc = block->getSSRC();
-                auto mid = getMidFromSSRC(ssrc);
-                if (mid.has_value()) {
-                    hasFound = true;
-                    std::shared_lock lock(mTracksMutex); // read-only
-                    if (auto it = mTracks.find(*mid); it != mTracks.end())
-                        if (auto track = it->second.lock())
-                            track->incoming(message);
+    std::optional<string> mid;
+    if (message->type == Message::Control) {
+        unsigned int offset = 0;
+        std::vector<SSRC> 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;
+            } else {
+                if (header->payloadType() == 205 || header->payloadType() == 206) {
+                     auto rtcpfb = (RTCP_FB_HEADER*) header;
+                     auto ssrc = rtcpfb->getPacketSenderSSRC();
+                    mid = getMidFromSSRC(ssrc);
+                    if (mid.has_value() && std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
+                        hasFound = true;
+                        std::shared_lock lock(mTracksMutex); // read-only
+                        if (auto it = mTracks.find(*mid); it != mTracks.end()) {
+                            if (auto track = it->second.lock()) {
+                                track->incoming(message);
+                                break;
+                            }
+                        }
+                        ssrcsFound.emplace_back(ssrc);
+                    }
+
+                    ssrc = rtcpfb->getMediaSourceSSRC();
+                    mid = getMidFromSSRC(ssrc);
+                    if (mid.has_value() && std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
+                        hasFound = true;
+                        std::shared_lock lock(mTracksMutex); // read-only
+                        if (auto it = mTracks.find(*mid); it != mTracks.end()) {
+                            if (auto track = it->second.lock()) {
+                                track->incoming(message);
+                                break;
+                            }
+                        }
+                        ssrcsFound.emplace_back(ssrc);
+                    }
+                }else if (header->payloadType() == 200 || header->payloadType() == 201) {
+                    auto rtcpsr = (RTCP_SR*) header;
+                    auto ssrc = rtcpsr->senderSSRC();
+                    mid = getMidFromSSRC(ssrc);
+                    if (mid.has_value() && std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
+                        hasFound = true;
+                        std::shared_lock lock(mTracksMutex); // read-only
+                        if (auto it = mTracks.find(*mid); it != mTracks.end()) {
+                            if (auto track = it->second.lock()) {
+                                track->incoming(message);
+                                break;
+                            }
+                        }
+                        ssrcsFound.emplace_back(ssrc);
+                    }
+                    for (int i = 0; i < rtcpsr->header.reportCount(); i++) {
+                        auto block = rtcpsr->getReportBlock(i);
+                        ssrc = block->getSSRC();
+                        mid = getMidFromSSRC(ssrc);
+                        if (mid.has_value() && std::find(ssrcsFound.begin(), ssrcsFound.end(), ssrc) == ssrcsFound.end()) {
+                            hasFound = true;
+                            std::shared_lock lock(mTracksMutex); // read-only
+                            if (auto it = mTracks.find(*mid); it != mTracks.end()) {
+                                if (auto track = it->second.lock()) {
+                                    track->incoming(message);
+                                    break;
+                                }
+                            }
+                            ssrcsFound.emplace_back(ssrc);
+                        }
+                    }
+                }else {
+                    PLOG_WARNING << "Unknown packet type: " << header->payloadType();
                 }
             }
-            if (hasFound)
-                return;
+            offset += header->lengthInBytes();
         }
+
+        if (hasFound)
+            return;
     }
 
+    unsigned int ssrc = message->stream;
+    mid = getMidFromSSRC(ssrc);
+
 	if (!mid) {
 	    /* TODO
 	     *   So the problem is that when stop sending streams, we stop getting report blocks for those streams