Bug 1096795: (WIP) Put a=rtcp in SDP when gathering ends.
authorByron Campen [:bwc] <docfaraday@gmail.com>
Fri, 08 May 2015 15:52:41 -0700
changeset 262147 f3d4f01f236bfd514a2531c5109ea58306a08d7f
parent 262140 cef2b76b082d36c329e94dfded65ead78ce026f2
child 550844 19d86584536f9287b4d42154dfeb28f0eaf067e3
push id1960
push userbcampen@mozilla.com
push dateFri, 08 May 2015 22:52:52 +0000
reviewersrtcp
bugs1096795
milestone40.0a1
Bug 1096795: (WIP) Put a=rtcp in SDP when gathering ends.
media/mtransport/nricemediastream.cpp
media/mtransport/nricemediastream.h
media/webrtc/signaling/src/jsep/JsepSession.h
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
media/webrtc/signaling/src/jsep/JsepSessionImpl.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
media/webrtc/signaling/test/jsep_session_unittest.cpp
--- a/media/mtransport/nricemediastream.cpp
+++ b/media/mtransport/nricemediastream.cpp
@@ -342,21 +342,22 @@ nsresult NrIceMediaStream::GetCandidateP
 
     out_pairs->push_back(pair);
   }
 
   return NS_OK;
 }
 
 nsresult NrIceMediaStream::GetDefaultCandidate(
-    NrIceCandidate* candidate) const {
+    NrIceCandidate* candidate,
+    int component) const {
 
   nr_ice_candidate *cand;
 
-  int r = nr_ice_media_stream_get_default_candidate(stream_, 1, &cand);
+  int r = nr_ice_media_stream_get_default_candidate(stream_, component, &cand);
   if (r) {
     MOZ_MTLOG(ML_ERROR, "Couldn't get default ICE candidate for '"
               << name_ << "'");
     return NS_ERROR_FAILURE;
   }
 
   if (!ToNrIceCandidate(*cand, candidate)) {
     MOZ_MTLOG(ML_ERROR, "Failed to convert default ICE candidate for '"
--- a/media/mtransport/nricemediastream.h
+++ b/media/mtransport/nricemediastream.h
@@ -133,17 +133,17 @@ class NrIceMediaStream {
   nsresult GetRemoteCandidates(std::vector<NrIceCandidate>* candidates) const;
 
   // Get all candidate pairs, whether in the check list or triggered check
   // queue, in priority order. |out_pairs| is cleared before being filled.
   nsresult GetCandidatePairs(std::vector<NrIceCandidatePair>* out_pairs) const;
 
   // TODO(bug 1096795): This needs to take a component number, so we can get
   // default candidates for rtcp.
-  nsresult GetDefaultCandidate(NrIceCandidate* candidate) const;
+  nsresult GetDefaultCandidate(NrIceCandidate* candidate, int component) const;
 
   // Parse remote attributes
   nsresult ParseAttributes(std::vector<std::string>& candidates);
   bool HasParsedAttributes() const { return has_parsed_attrs_; }
 
   // Parse trickle ICE candidate
   nsresult ParseTrickleCandidate(const std::string& candidate);
 
--- a/media/webrtc/signaling/src/jsep/JsepSession.h
+++ b/media/webrtc/signaling/src/jsep/JsepSession.h
@@ -125,19 +125,22 @@ public:
                                         const std::string& sdp) = 0;
   virtual nsresult AddRemoteIceCandidate(const std::string& candidate,
                                          const std::string& mid,
                                          uint16_t level) = 0;
   virtual nsresult AddLocalIceCandidate(const std::string& candidate,
                                         const std::string& mid,
                                         uint16_t level,
                                         bool* skipped) = 0;
-  virtual nsresult EndOfLocalCandidates(const std::string& defaultCandidateAddr,
-                                        uint16_t defaultCandidatePort,
-                                        uint16_t level) = 0;
+  virtual nsresult EndOfLocalCandidates(
+      const std::string& defaultCandidateAddr,
+      uint16_t defaultCandidatePort,
+      const std::string& defaultRtcpCandidateAddr,
+      uint16_t defaultRtcpCandidatePort,
+      uint16_t level) = 0;
   virtual nsresult Close() = 0;
 
   // ICE controlling or controlled
   virtual bool IsIceControlling() const = 0;
 
   virtual const std::string
   GetLastError() const
   {
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -2554,19 +2554,42 @@ JsepSessionImpl::AddLocalIceCandidate(co
     }
   }
 
   *skipped = false;
 
   return AddCandidateToSdp(sdp, candidate, mid, level);
 }
 
+static void SetDefaultAddresses(const std::string& defaultCandidateAddr,
+                                uint16_t defaultCandidatePort,
+                                const std::string& defaultRtcpCandidateAddr,
+                                uint16_t defaultRtcpCandidatePort,
+                                SdpMediaSection* msection)
+{
+  msection->GetConnection().SetAddress(defaultCandidateAddr);
+  msection->SetPort(defaultCandidatePort);
+  if (!defaultRtcpCandidateAddr.empty()) {
+    sdp::AddrType ipVersion = sdp::kIPv4;
+    if (defaultRtcpCandidateAddr.find(':') != std::string::npos) {
+      ipVersion = sdp::kIPv6;
+    }
+    msection->GetAttributeList().SetAttribute(new SdpRtcpAttribute(
+          defaultRtcpCandidatePort,
+          sdp::kInternet,
+          ipVersion,
+          defaultRtcpCandidateAddr));
+  }
+}
+
 nsresult
 JsepSessionImpl::EndOfLocalCandidates(const std::string& defaultCandidateAddr,
                                       uint16_t defaultCandidatePort,
+                                      const std::string& defaultRtcpCandidateAddr,
+                                      uint16_t defaultRtcpCandidatePort,
                                       uint16_t level)
 {
   mLastError.clear();
 
   mozilla::Sdp* sdp = 0;
 
   if (mPendingLocalDescription) {
     sdp = mPendingLocalDescription.get();
@@ -2599,23 +2622,29 @@ JsepSessionImpl::EndOfLocalCandidates(co
       // Master bundle m-section. Set defaultCandidateAddr and
       // defaultCandidatePort on all bundled m-sections.
       for (auto i = bundleMids.begin(); i != bundleMids.end(); ++i) {
         SdpMediaSection* bundledMsection = FindMsectionByMid(*sdp, *i);
         if (!bundledMsection) {
           MOZ_ASSERT(false);
           continue;
         }
-        bundledMsection->GetConnection().SetAddress(defaultCandidateAddr);
-        bundledMsection->SetPort(defaultCandidatePort);
+        SetDefaultAddresses(defaultCandidateAddr,
+                            defaultCandidatePort,
+                            defaultRtcpCandidateAddr,
+                            defaultRtcpCandidatePort,
+                            bundledMsection);
       }
     }
 
-    msection.GetConnection().SetAddress(defaultCandidateAddr);
-    msection.SetPort(defaultCandidatePort);
+    SetDefaultAddresses(defaultCandidateAddr,
+                        defaultCandidatePort,
+                        defaultRtcpCandidateAddr,
+                        defaultRtcpCandidatePort,
+                        &msection);
 
     // TODO(bug 1095793): Will this have an mid someday?
 
     SdpAttributeList& attrs = msection.GetAttributeList();
     attrs.SetAttribute(
         new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
     if (!mIsOfferer) {
       attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
@@ -115,16 +115,18 @@ public:
 
   virtual nsresult AddLocalIceCandidate(const std::string& candidate,
                                         const std::string& mid,
                                         uint16_t level,
                                         bool* skipped) override;
 
   virtual nsresult EndOfLocalCandidates(const std::string& defaultCandidateAddr,
                                         uint16_t defaultCandidatePort,
+                                        const std::string& defaultRtcpCandidateAddr,
+                                        uint16_t defaultRtcpCandidatePort,
                                         uint16_t level) override;
 
   virtual nsresult Close() override;
 
   virtual const std::string GetLastError() const override;
 
   virtual bool
   IsIceControlling() const override
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2783,19 +2783,25 @@ PeerConnectionImpl::IceGatheringStateCha
   if (mIceGatheringState == PCImplIceGatheringState::Complete) {
     SendLocalIceCandidateToContent(0, "", "");
   }
 }
 
 void
 PeerConnectionImpl::EndOfLocalCandidates(const std::string& defaultAddr,
                                          uint16_t defaultPort,
+                                         const std::string& defaultRtcpAddr,
+                                         uint16_t defaultRtcpPort,
                                          uint16_t level) {
   CSFLogDebug(logTag, "%s", __FUNCTION__);
-  mJsepSession->EndOfLocalCandidates(defaultAddr, defaultPort, level);
+  mJsepSession->EndOfLocalCandidates(defaultAddr,
+                                     defaultPort,
+                                     defaultRtcpAddr,
+                                     defaultRtcpPort,
+                                     level);
 }
 
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
 nsresult
 PeerConnectionImpl::BuildStatsQuery_m(
     mozilla::dom::MediaStreamTrack *aSelector,
     RTCStatsQuery *query) {
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -293,19 +293,20 @@ public:
   // Name suitable for exposing to content
   virtual const std::string& GetName();
 
   // ICE events
   void IceConnectionStateChange(NrIceCtx* ctx,
                                 NrIceCtx::ConnectionState state);
   void IceGatheringStateChange(NrIceCtx* ctx,
                                NrIceCtx::GatheringState state);
-  // TODO(bug 1096795): Need a |component| id here for rtcp.
   void EndOfLocalCandidates(const std::string& defaultAddr,
                             uint16_t defaultPort,
+                            const std::string& defaultRtcpAddr,
+                            uint16_t defaultRtcpPort,
                             uint16_t level);
   void IceStreamReady(NrIceMediaStream *aStream);
 
   static void ListenThread(void *aData);
   static void ConnectThread(void *aData);
 
   // Get the main thread
   nsCOMPtr<nsIThread> GetMainThread() {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -844,20 +844,25 @@ PeerConnectionMedia::IceGatheringStateCh
     // Fire off EndOfLocalCandidates for each stream
     for (size_t i = 0; ; ++i) {
       RefPtr<NrIceMediaStream> stream(ctx->GetStream(i));
       if (!stream) {
         break;
       }
 
       NrIceCandidate candidate;
-      nsresult res = stream->GetDefaultCandidate(&candidate);
+      nsresult res = stream->GetDefaultCandidate(&candidate, 1);
+      NrIceCandidate rtcpCandidate;
+      rtcpCandidate.cand_addr.port = 0; // Avoid valgrind warnings if no rtcp
+      stream->GetDefaultCandidate(&rtcpCandidate, 2); // Optional, ignore errors
       if (NS_SUCCEEDED(res)) {
         EndOfLocalCandidates(candidate.cand_addr.host,
                              candidate.cand_addr.port,
+                             rtcpCandidate.cand_addr.host,
+                             rtcpCandidate.cand_addr.port,
                              i);
       } else {
         CSFLogError(logTag, "%s: GetDefaultCandidate failed for level %u, "
                             "res=%u",
                             __FUNCTION__,
                             static_cast<unsigned>(i),
                             static_cast<unsigned>(res));
       }
@@ -912,22 +917,25 @@ PeerConnectionMedia::OnCandidateFound_s(
                  candidate,
                  aStream->GetLevel()),
     NS_DISPATCH_NORMAL);
 }
 
 void
 PeerConnectionMedia::EndOfLocalCandidates(const std::string& aDefaultAddr,
                                           uint16_t aDefaultPort,
+                                          const std::string& aDefaultRtcpAddr,
+                                          uint16_t aDefaultRtcpPort,
                                           uint16_t aMLine) {
   // We will still be around because we have not started teardown yet
   GetMainThread()->Dispatch(
     WrapRunnable(this,
                  &PeerConnectionMedia::EndOfLocalCandidates_m,
-                 aDefaultAddr, aDefaultPort, aMLine),
+                 aDefaultAddr, aDefaultPort,
+                 aDefaultRtcpAddr, aDefaultRtcpPort, aMLine),
     NS_DISPATCH_NORMAL);
 }
 
 void
 PeerConnectionMedia::IceGatheringStateChange_m(NrIceCtx* ctx,
                                                NrIceCtx::GatheringState state)
 {
   ASSERT_ON_THREAD(mMainThread);
@@ -956,18 +964,24 @@ PeerConnectionMedia::OnCandidateFound_m(
 {
   ASSERT_ON_THREAD(mMainThread);
   SignalCandidate(candidate, aMLine);
 }
 
 void
 PeerConnectionMedia::EndOfLocalCandidates_m(const std::string& aDefaultAddr,
                                             uint16_t aDefaultPort,
+                                            const std::string& aDefaultRtcpAddr,
+                                            uint16_t aDefaultRtcpPort,
                                             uint16_t aMLine) {
-  SignalEndOfLocalCandidates(aDefaultAddr, aDefaultPort, aMLine);
+  SignalEndOfLocalCandidates(aDefaultAddr,
+                             aDefaultPort,
+                             aDefaultRtcpAddr,
+                             aDefaultRtcpPort,
+                             aMLine);
 }
 
 void
 PeerConnectionMedia::DtlsConnected_s(TransportLayer *layer,
                                      TransportLayer::State state)
 {
   MOZ_ASSERT(layer->id() == "dtls");
   TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(layer);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -384,17 +384,18 @@ class PeerConnectionMedia : public sigsl
   // ICE state signals
   sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
       SignalIceGatheringStateChange;
   sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
       SignalIceConnectionStateChange;
   // This passes a candidate:... attribute  and level
   sigslot::signal2<const std::string&, uint16_t> SignalCandidate;
   // This passes address, port, level of the default candidate.
-  sigslot::signal3<const std::string&, uint16_t, uint16_t>
+  sigslot::signal5<const std::string&, uint16_t,
+                   const std::string&, uint16_t, uint16_t>
       SignalEndOfLocalCandidates;
 
  private:
 #if !defined(MOZILLA_XPCOMRT_API)
   class ProtocolProxyQueryHandler : public nsIProtocolProxyCallback {
    public:
     explicit ProtocolProxyQueryHandler(PeerConnectionMedia *pcm) :
       pcm_(pcm) {}
@@ -443,25 +444,29 @@ class PeerConnectionMedia : public sigsl
                                NrIceCtx::GatheringState state);
   void IceConnectionStateChange_s(NrIceCtx* ctx,
                                 NrIceCtx::ConnectionState state);
   void IceStreamReady_s(NrIceMediaStream *aStream);
   void OnCandidateFound_s(NrIceMediaStream *aStream,
                         const std::string &candidate);
   void EndOfLocalCandidates(const std::string& aDefaultAddr,
                             uint16_t aDefaultPort,
+                            const std::string& aDefaultRtcpAddr,
+                            uint16_t aDefaultRtcpPort,
                             uint16_t aMLine);
 
   void IceGatheringStateChange_m(NrIceCtx* ctx,
                                  NrIceCtx::GatheringState state);
   void IceConnectionStateChange_m(NrIceCtx* ctx,
                                   NrIceCtx::ConnectionState state);
   void OnCandidateFound_m(const std::string &candidate, uint16_t aMLine);
   void EndOfLocalCandidates_m(const std::string& aDefaultAddr,
                               uint16_t aDefaultPort,
+                              const std::string& aDefaultRtcpAddr,
+                              uint16_t aDefaultRtcpPort,
                               uint16_t aMLine);
   bool IsIceCtxReady() const {
     return mProxyResolveCompleted;
   }
 
   // The parent PC
   PeerConnectionImpl *mParent;
   // and a loose handle on it for event driven stuff
--- a/media/webrtc/signaling/test/jsep_session_unittest.cpp
+++ b/media/webrtc/signaling/test/jsep_session_unittest.cpp
@@ -574,25 +574,25 @@ protected:
   {
     bool skipped;
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[0], "", 0, &skipped);
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[1], "", 0, &skipped);
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[2], "", 0, &skipped);
-    session.EndOfLocalCandidates("192.168.0.2", 2002, 0);
+    session.EndOfLocalCandidates("192.168.0.2", 2002, "", 0, 0);
 
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[3], "", 1, &skipped);
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[4], "", 1, &skipped);
     session.AddLocalIceCandidate(
         kAEqualsCandidate + kCandidates[5], "", 1, &skipped);
-    session.EndOfLocalCandidates("192.168.1.2", 2012, 1);
+    session.EndOfLocalCandidates("192.168.1.2", 2012, "", 0, 1);
 
     std::cerr << "local SDP after candidates: "
               << session.GetLocalDescription();
   }
 
   void
   TrickleCandidates(JsepSession& session)
   {