Browse Source

Made SRTP policies to be made in flight rather than during configuration. Added some missing API fields.

Staz M 4 years ago
parent
commit
41cf60c18b

+ 4 - 1
include/rtc/description.hpp

@@ -130,6 +130,8 @@ public:
         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<uint32_t> getSSRCs();
 
@@ -171,7 +173,8 @@ public:
 
 	public:
         void addRTPMap(const RTPMap& map);
-	};
+
+    };
 
 	class Audio : public Media {
 	public:

+ 1 - 1
include/rtc/peerconnection.hpp

@@ -83,6 +83,7 @@ public:
 	bool hasMedia() const;
 
 	void setLocalDescription();
+    void processLocalDescription(Description description);
 	void setRemoteDescription(Description description);
 	void addRemoteCandidate(Candidate candidate);
 
@@ -136,7 +137,6 @@ private:
 	void incomingTrack(Description::Media description);
 	void openTracks();
 
-	void processLocalDescription(Description description);
 	void processLocalCandidate(Candidate candidate);
 	void triggerDataChannel(std::weak_ptr<DataChannel> weakDataChannel);
 	void triggerTrack(std::shared_ptr<Track> track);

+ 8 - 0
include/rtc/rtp.hpp

@@ -73,6 +73,10 @@ public:
     inline void setSsrc(uint32_t ssrc) {
         _ssrc = htonl(ssrc);
     }
+
+    void setTimestamp(uint32_t i) {
+        _timestamp = htonl(i);
+    }
 };
 
 struct RTCP_ReportBlock {
@@ -293,6 +297,10 @@ public:
         return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock);
     }
 
+    inline bool isSenderReport() {
+        return header.payloadType() == 200;
+    }
+
     inline bool isReceiverReport() {
         return header.payloadType() == 201;
     }

+ 2 - 0
include/rtc/track.hpp

@@ -42,6 +42,7 @@ public:
 
 	string mid() const;
 	Description::Media description() const;
+    void replaceSSRC(SSRC oldSSRC, SSRC ssrc, string cname);
 
 	void close(void) override;
 	bool send(message_variant data) override;
@@ -59,6 +60,7 @@ public:
 
 	// RTCP handler
 	void setRtcpHandler(std::shared_ptr<RtcpHandler> handler);
+	std::shared_ptr<RtcpHandler> getRtcpHandler();
 
 private:
 #if RTC_ENABLE_MEDIA

+ 16 - 0
src/description.cpp

@@ -446,6 +446,21 @@ void Description::Media::addSSRC(uint32_t ssrc, std::string name) {
     mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + name);
 }
 
+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);
+}
+
+void Description::Media::addSSRC(uint32_t ssrc) {
+    mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
+}
+
 bool Description::Media::hasSSRC(uint32_t ssrc) {
     for (auto &val : mAttributes) {
         if (val.find("ssrc:" + std::to_string(ssrc)) != std::string ::npos)
@@ -725,6 +740,7 @@ std::vector<uint32_t> Description::Media::getSSRCs() {
 }
 
 
+
 Description::Media::RTPMap::RTPMap(string_view mline) {
 	size_t p = mline.find(' ');
 

+ 32 - 1
src/dtlssrtptransport.cpp

@@ -112,7 +112,14 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
 		if (srtp_err_status_t err = srtp_protect_rtcp(mSrtpOut, message->data(), &size)) {
 			if (err == srtp_err_status_replay_fail)
 				throw std::runtime_error("SRTCP packet is a replay");
-			else
+			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<int>(err)));
+            }else
 				throw std::runtime_error("SRTCP protect error, status=" +
 				                         to_string(static_cast<int>(err)));
 		}
@@ -121,6 +128,14 @@ bool DtlsSrtpTransport::sendMedia(message_ptr message) {
 		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");
+            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<int>(err)));
+            }
 			else
 				throw std::runtime_error("SRTP protect error, status=" +
 				                         to_string(static_cast<int>(err)));
@@ -177,6 +192,14 @@ 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<int>(err)));
+                }
 				else {
                     PLOG_WARNING << "SRTCP unprotect error, status=" << err << " SSRC="
                                  << ((RTCP_SR *) message->data())->senderSSRC();
@@ -194,6 +217,14 @@ 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<int>(err)));
+                }
 				else
 					PLOG_WARNING << "SRTP unprotect error, status=" << err << " SSRC=" << ((RTP*)message->data())->ssrc();
 				return;

+ 27 - 26
src/peerconnection.cpp

@@ -115,8 +115,8 @@ void PeerConnection::setRemoteDescription(Description description) {
 		                    }},
 		    description.media(i));
 
-	if (activeMediaCount == 0)
-		throw std::invalid_argument("Remote description has no active media");
+//	if (activeMediaCount == 0)
+//		throw std::invalid_argument("Remote description has no active media");
 
 	if (!description.fingerprint())
 		throw std::invalid_argument("Remote description has no fingerprint");
@@ -552,12 +552,12 @@ void PeerConnection::forwardMedia(message_ptr message) {
 	unsigned int ssrc = message->stream;
 	std::optional<string> mid = getMidFromSSRC(ssrc);
 
-	// Because chrome likes to send all report blocks as SSRC=1
+	// 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->senderSSRC() == 1 && sr->isReceiverReport()) {
-        bool hasFound = false;
+        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();
@@ -576,7 +576,13 @@ void PeerConnection::forwardMedia(message_ptr message) {
     }
 
 	if (!mid) {
-		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;
 	}
 
@@ -726,28 +732,23 @@ void PeerConnection::openTracks() {
 	if (auto transport = std::atomic_load(&mDtlsTransport)) {
 		auto srtpTransport = std::reinterpret_pointer_cast<DtlsSrtpTransport>(transport);
 		std::shared_lock lock(mTracksMutex); // read-only
-//		for (auto it = mTracks.begin(); it != mTracks.end(); ++it)
-        if (mTrackLines.size() == remoteDescription()->mediaCount()) {
-        for (unsigned int i = 0; i < mTrackLines.size(); i++) {
-            if (auto track = mTrackLines[i].lock()) {
-                if (!track->isOpen()) {
-//                    if (track->description().direction() == rtc::Description::Direction::RecvOnly || track->description().direction() == rtc::Description::Direction::SendRecv)
-//                        srtpTransport->addInboundSSRC(0);
-//                    if (track->description().direction() == rtc::Description::Direction::SendOnly || track->description().direction() == rtc::Description::Direction::SendRecv)
-
-                    for (auto ssrc : track->description().getSSRCs()) {
-                        PLOG_DEBUG << "Adding " << ssrc << " to list";
-                        srtpTransport->addSSRC(ssrc);
-                    }
-                    for (auto ssrc : std::get<rtc::Description::Media *>(remoteDescription()->media(i))->getSSRCs()) {
-                        PLOG_DEBUG << "Adding " << ssrc << " to list";
-                        srtpTransport->addSSRC(ssrc);
-                    }
+            for (unsigned int i = 0; i < mTrackLines.size(); i++) {
+                if (auto track = mTrackLines[i].lock()) {
+//                    srtpTransport->addSSRC(0);
+
+//                    for (auto ssrc : track->description().getSSRCs()) {
+//                        PLOG_DEBUG << "Adding " << ssrc << " to list";
+//                        srtpTransport->addSSRC(ssrc);
+//                    }
+//                    for (auto ssrc : std::get<rtc::Description::Media *>(remoteDescription()->media(i))->getSSRCs()) {
+//                        PLOG_DEBUG << "Adding " << ssrc << " to list";
+//                        srtpTransport->addSSRC(ssrc);
+//                    }
 
+                if (!track->isOpen()) {
                     track->open(srtpTransport);
                 }
             }
-            }
         }
 	}
 #endif
@@ -836,8 +837,8 @@ void PeerConnection::processLocalDescription(Description description) {
 	}
 
 	// There must be at least one active media to negociate
-	if (activeMediaCount == 0)
-		throw std::runtime_error("Nothing to negociate");
+//	if (activeMediaCount == 0)
+//		throw std::runtime_error("Nothing to negociate");
 
 	// Set local fingerprint (wait for certificate if necessary)
 	description.setFingerprint(mCertificate.get()->fingerprint());

+ 8 - 0
src/track.cpp

@@ -32,6 +32,10 @@ string Track::mid() const { return mMediaDescription.mid(); }
 
 Description::Media Track::description() const { return mMediaDescription; }
 
+void Track::replaceSSRC(SSRC oldSSRC, SSRC ssrc, std::string cname) {
+    mMediaDescription.replaceSSRC(oldSSRC, ssrc, cname);
+}
+
 void Track::close() {
 	mIsClosed = true;
 	resetCallbacks();
@@ -158,5 +162,9 @@ bool Track::requestKeyframe() {
     return false;
 }
 
+std::shared_ptr<RtcpHandler> Track::getRtcpHandler() {
+    return mRtcpHandler;
+}
+
 } // namespace rtc