From 90e44f769541ad957545eb3f9d6d46673185e396 Mon Sep 17 00:00:00 2001 From: Dan Minor Date: Tue, 1 Oct 2019 12:58:23 +0000 Subject: [PATCH] Bug 1567201 - Use mdns_service to handle mDNS queries; r=mjf Differential Revision: https://phabricator.services.mozilla.com/D46977 --HG-- extra : moz-landing-system : lando --- dom/media/webrtc/MediaTransportParent.h | 3 +- dom/media/webrtc/PMediaTransport.ipdl | 3 +- .../gtest/mediapipeline_unittest.cpp | 4 +- .../peerconnection/MediaTransportHandler.cpp | 198 +----------------- .../peerconnection/MediaTransportHandler.h | 3 +- .../MediaTransportHandlerIPC.cpp | 9 +- .../peerconnection/MediaTransportHandlerIPC.h | 4 +- .../peerconnection/MediaTransportParent.cpp | 6 +- .../peerconnection/PeerConnectionMedia.cpp | 71 ++++++- .../src/peerconnection/PeerConnectionMedia.h | 8 + 10 files changed, 102 insertions(+), 207 deletions(-) diff --git a/dom/media/webrtc/MediaTransportParent.h b/dom/media/webrtc/MediaTransportParent.h index a2084206b770..aea8c0a8a68a 100644 --- a/dom/media/webrtc/MediaTransportParent.h +++ b/dom/media/webrtc/MediaTransportParent.h @@ -49,7 +49,8 @@ class MediaTransportParent : public dom::PMediaTransportParent { const MediaPacket& packet); mozilla::ipc::IPCResult RecvAddIceCandidate(const string& transportId, const string& candidate, - const string& ufrag); + const string& ufrag, + const string& obfuscatedAddress); mozilla::ipc::IPCResult RecvUpdateNetworkState(const bool& online); mozilla::ipc::IPCResult RecvGetIceStats( const string& transportId, const double& now, diff --git a/dom/media/webrtc/PMediaTransport.ipdl b/dom/media/webrtc/PMediaTransport.ipdl index fd0534c31c10..433e0447597e 100644 --- a/dom/media/webrtc/PMediaTransport.ipdl +++ b/dom/media/webrtc/PMediaTransport.ipdl @@ -81,7 +81,8 @@ parent: async AddIceCandidate(string transportId, string candidate, - string ufrag); + string ufrag, + string obfuscatedAddr); async UpdateNetworkState(bool online); diff --git a/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp b/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp index 1b71ef71a732..1d84164ce1ab 100644 --- a/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp @@ -187,8 +187,8 @@ class LoopbackTransport : public MediaTransportHandler { const std::vector& aIceOptions) override {} void AddIceCandidate(const std::string& aTransportId, - const std::string& aCandidate, - const std::string& aUfrag) override {} + const std::string& aCandidate, const std::string& aUfrag, + const std::string& aObfuscatedAddress) override {} void UpdateNetworkState(bool aOnline) override {} diff --git a/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.cpp b/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.cpp index 2a83d52f6505..c36f8d92ede2 100644 --- a/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.cpp +++ b/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.cpp @@ -36,10 +36,6 @@ #include "mozilla/dom/RTCStatsReportBinding.h" -// mDNS -#include "nsIDNSRecord.h" -#include "mozilla/net/DNS.h" - #include "nss.h" // For NSS_NoDB_Init #include "mozilla/PublicSSL.h" // For psm::InitializeCipherSuite @@ -107,8 +103,8 @@ class MediaTransportHandlerSTS : public MediaTransportHandler, const std::vector& aIceOptions) override; void AddIceCandidate(const std::string& aTransportId, - const std::string& aCandidate, - const std::string& aUfrag) override; + const std::string& aCandidate, const std::string& aUfrag, + const std::string& aObfuscatedAddress) override; void UpdateNetworkState(bool aOnline) override; @@ -165,45 +161,8 @@ class MediaTransportHandlerSTS : public MediaTransportHandler, std::map mTransports; bool mObfuscateHostAddresses = false; - // mDNS Support - class DNSListener final : public nsIDNSListener { - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIDNSLISTENER - - public: - DNSListener(MediaTransportHandlerSTS& aTransportHandler, - const std::string& aTransportId, const std::string& aCandidate, - std::vector aTokenizedCandidate, - const std::string& aUfrag) - : mTransportHandler(aTransportHandler), - mTransportId(aTransportId), - mCandidate(aCandidate), - mTokenizedCandidate(aTokenizedCandidate), - mUfrag(aUfrag) {} - - void Cancel() { - mCancel->Cancel(NS_ERROR_ABORT); - mCancel = nullptr; - } - - MediaTransportHandlerSTS& mTransportHandler; - - const std::string mTransportId; - const std::string mCandidate; - std::vector mTokenizedCandidate; - const std::string mUfrag; - - nsCOMPtr mCancel; - - private: - ~DNSListener() = default; - }; - - void PendingDNSRequestResolved(DNSListener* aListener); - - nsCOMPtr mDNSService; - std::set> mPendingDNSRequests; std::set mSignaledAddresses; + // Init can only be done on main, but we want this to be usable on any thread typedef MozPromise InitPromise; RefPtr mInitPromise; @@ -482,11 +441,6 @@ void MediaTransportHandlerSTS::Destroy() { mInitPromise->Then( mStsThread, __func__, [this, self = RefPtr(this)]() { - for (auto& listener : mPendingDNSRequests) { - listener->Cancel(); - } - mPendingDNSRequests.clear(); - disconnect_all(); if (mIceCtx) { NrIceStats stats = mIceCtx->Destroy(); @@ -722,61 +676,15 @@ static void TokenizeCandidate(const std::string& aCandidate, } } -void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId, - const std::string& aCandidate, - const std::string& aUfrag) { +void MediaTransportHandlerSTS::AddIceCandidate( + const std::string& aTransportId, const std::string& aCandidate, + const std::string& aUfrag, const std::string& aObfuscatedAddress) { mInitPromise->Then( mStsThread, __func__, [=, self = RefPtr(this)]() { std::vector tokens; TokenizeCandidate(aCandidate, tokens); - if (tokens.size() > 4) { - std::string addr = tokens[4]; - - // Check for address ending with .local - size_t nPeriods = std::count(addr.begin(), addr.end(), '.'); - size_t dotLocalLength = 6; // length of ".local" - - if (nPeriods == 1 && - addr.rfind(".local") + dotLocalLength == addr.length()) { - CSFLogDebug( - LOGTAG, - "Using mDNS to resolve candidate with transport id: %s: %s", - aTransportId.c_str(), aCandidate.c_str()); - - auto listener = - *(mPendingDNSRequests - .emplace(new DNSListener(*this, aTransportId, aCandidate, - tokens, aUfrag)) - .first); - OriginAttributes attrs; - - if (!mDNSService) { - nsresult rv; - mDNSService = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - MOZ_ASSERT(false); - MOZ_CRASH(); - } - } - - if (NS_FAILED(mDNSService->AsyncResolveNative( - nsAutoCString(tokens[4].c_str()), 0, listener, mStsThread, - attrs, getter_AddRefs(listener->mCancel)))) { - CSFLogError( - LOGTAG, - "Error using mDNS to resolve candidate with transport id " - "%s: %s", - aTransportId.c_str(), aCandidate.c_str()); - } - // TODO: Bug 1535690, we don't want to tell the ICE context that - // remote trickle is done if we are waiting to resolve a mDNS - // candidate. - return; - } - } - RefPtr stream(mIceCtx->GetStream(aTransportId)); if (!stream) { CSFLogError(LOGTAG, @@ -785,7 +693,8 @@ void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId, return; } - nsresult rv = stream->ParseTrickleCandidate(aCandidate, aUfrag, ""); + nsresult rv = stream->ParseTrickleCandidate(aCandidate, aUfrag, + aObfuscatedAddress); if (NS_SUCCEEDED(rv)) { if (mObfuscateHostAddresses && tokens.size() > 4) { mSignaledAddresses.insert(tokens[4]); @@ -1032,11 +941,6 @@ MediaTransportHandlerSTS::GetIceStats( }); } -void MediaTransportHandlerSTS::PendingDNSRequestResolved( - DNSListener* aListener) { - mPendingDNSRequests.erase(aListener); -} - RefPtr MediaTransportHandlerSTS::GetIceLog(const nsCString& aPattern) { return InvokeAsync( @@ -1414,90 +1318,4 @@ void MediaTransportHandlerSTS::EncryptedPacketSending(TransportLayer* aLayer, OnEncryptedSending(aLayer->flow_id(), aPacket); } -NS_IMPL_ISUPPORTS(MediaTransportHandlerSTS::DNSListener, nsIDNSListener); - -nsresult MediaTransportHandlerSTS::DNSListener::OnLookupComplete( - nsICancelable* aRequest, nsIDNSRecord* aRecord, nsresult aStatus) { - if (mCancel) { - MOZ_ASSERT(mTransportHandler.mStsThread->IsOnCurrentThread()); - if (NS_SUCCEEDED(aStatus)) { - nsTArray addresses; - aRecord->GetAddresses(addresses); - - // https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-03#section-3.2.2 - if (addresses.Length() == 1) { - char buf[net::kIPv6CStrBufSize]; - if (!net::NetAddrToString(&addresses[0], buf, sizeof(buf))) { - CSFLogError(LOGTAG, - "Unable to convert mDNS address for candidate with" - " transport id %s: %s", - mTransportId.c_str(), mCandidate.c_str()); - return NS_OK; - } - - CSFLogDebug(LOGTAG, - "Adding mDNS candidate with transport id: %s: %s:" - " resolved to: %s", - mTransportId.c_str(), mCandidate.c_str(), buf); - - // Replace obfuscated address with actual address - std::string obfuscatedAddr = mTokenizedCandidate[4]; - mTokenizedCandidate[4] = buf; - std::ostringstream o; - for (size_t i = 0; i < mTokenizedCandidate.size(); ++i) { - o << mTokenizedCandidate[i]; - if (i + 1 != mTokenizedCandidate.size()) { - o << " "; - } - } - - std::string mungedCandidate = o.str(); - - RefPtr stream( - mTransportHandler.mIceCtx->GetStream(mTransportId)); - if (!stream) { - CSFLogError(LOGTAG, - "No ICE stream for candidate with transport id %s: %s", - mTransportId.c_str(), mCandidate.c_str()); - return NS_OK; - } - - nsresult rv = stream->ParseTrickleCandidate(mungedCandidate, mUfrag, - obfuscatedAddr); - if (NS_FAILED(rv)) { - CSFLogError(LOGTAG, - "Couldn't process ICE candidate with transport id %s: " - "%s", - mTransportId.c_str(), mCandidate.c_str()); - } - } else { - CSFLogError(LOGTAG, - "More than one mDNS result for candidate with transport" - " id: %s: %s, candidate ignored", - mTransportId.c_str(), mCandidate.c_str()); - } - } else { - CSFLogError(LOGTAG, - "Using mDNS failed for candidate with transport id: %s: %s", - mTransportId.c_str(), mCandidate.c_str()); - } - - mCancel = nullptr; - mTransportHandler.PendingDNSRequestResolved(this); - } - - return NS_OK; -} - -nsresult MediaTransportHandlerSTS::DNSListener::OnLookupByTypeComplete( - nsICancelable* aRequest, nsIDNSByTypeRecord* aResult, nsresult aStatus) { - MOZ_ASSERT_UNREACHABLE( - "MediaTranportHandlerSTS::DNSListener::OnLookupByTypeComplete"); - if (mCancel) { - mCancel = nullptr; - mTransportHandler.PendingDNSRequestResolved(this); - } - return NS_OK; -} - } // namespace mozilla diff --git a/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.h b/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.h index e4ade0e367ba..f775b294e202 100644 --- a/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.h +++ b/media/webrtc/signaling/src/peerconnection/MediaTransportHandler.h @@ -110,7 +110,8 @@ class MediaTransportHandler { virtual void AddIceCandidate(const std::string& aTransportId, const std::string& aCandidate, - const std::string& aUFrag) = 0; + const std::string& aUFrag, + const std::string& aObfuscatedAddress) = 0; virtual void UpdateNetworkState(bool aOnline) = 0; diff --git a/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.cpp b/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.cpp index 256da7420f30..65561e6926a1 100644 --- a/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.cpp +++ b/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.cpp @@ -280,14 +280,15 @@ void MediaTransportHandlerIPC::SendPacket(const std::string& aTransportId, [](const nsCString& aError) {}); } -void MediaTransportHandlerIPC::AddIceCandidate(const std::string& aTransportId, - const std::string& aCandidate, - const std::string& aUfrag) { +void MediaTransportHandlerIPC::AddIceCandidate( + const std::string& aTransportId, const std::string& aCandidate, + const std::string& aUfrag, const std::string& aObfuscatedAddress) { mInitPromise->Then( mCallbackThread, __func__, [=, self = RefPtr(this)](bool /*dummy*/) { if (mChild) { - mChild->SendAddIceCandidate(aTransportId, aCandidate, aUfrag); + mChild->SendAddIceCandidate(aTransportId, aCandidate, aUfrag, + aObfuscatedAddress); } }, [](const nsCString& aError) {}); diff --git a/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.h b/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.h index c1be68ea069d..f01b02f542f7 100644 --- a/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.h +++ b/media/webrtc/signaling/src/peerconnection/MediaTransportHandlerIPC.h @@ -66,8 +66,8 @@ class MediaTransportHandlerIPC : public MediaTransportHandler { MediaPacket&& aPacket) override; void AddIceCandidate(const std::string& aTransportId, - const std::string& aCandidate, - const std::string& aUfrag) override; + const std::string& aCandidate, const std::string& aUfrag, + const std::string& aObfuscatedAddress) override; void UpdateNetworkState(bool aOnline) override; diff --git a/media/webrtc/signaling/src/peerconnection/MediaTransportParent.cpp b/media/webrtc/signaling/src/peerconnection/MediaTransportParent.cpp index fd8531bcf5b7..ec78eee99c8c 100644 --- a/media/webrtc/signaling/src/peerconnection/MediaTransportParent.cpp +++ b/media/webrtc/signaling/src/peerconnection/MediaTransportParent.cpp @@ -198,8 +198,10 @@ mozilla::ipc::IPCResult MediaTransportParent::RecvSendPacket( } mozilla::ipc::IPCResult MediaTransportParent::RecvAddIceCandidate( - const string& transportId, const string& candidate, const string& ufrag) { - mImpl->mHandler->AddIceCandidate(transportId, candidate, ufrag); + const string& transportId, const string& candidate, const string& ufrag, + const string& obfuscatedAddr) { + mImpl->mHandler->AddIceCandidate(transportId, candidate, ufrag, + obfuscatedAddr); return ipc::IPCResult::Ok(); } diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 1a5be7bb91ca..16a0e6cbfb7a 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -41,7 +41,28 @@ static const char* pcmLogTag = "PeerConnectionMedia"; #define LOGTAG pcmLogTag void PeerConnectionMedia::StunAddrsHandler::OnMDNSQueryComplete( - const nsCString& hostname, const nsCString& address) {} + const nsCString& hostname, const nsCString& address) { + ASSERT_ON_THREAD(pcm_->mMainThread); + auto itor = pcm_->mQueriedMDNSHostnames.find(hostname.BeginReading()); + if (itor != pcm_->mQueriedMDNSHostnames.end()) { + for (auto& cand : itor->second) { + // Replace obfuscated address with actual address + std::string obfuscatedAddr = cand.mTokenizedCandidate[4]; + cand.mTokenizedCandidate[4] = address.BeginReading(); + std::ostringstream o; + for (size_t i = 0; i < cand.mTokenizedCandidate.size(); ++i) { + o << cand.mTokenizedCandidate[i]; + if (i + 1 != cand.mTokenizedCandidate.size()) { + o << " "; + } + } + std::string mungedCandidate = o.str(); + pcm_->mTransportHandler->AddIceCandidate( + cand.mTransportId, mungedCandidate, cand.mUfrag, obfuscatedAddr); + } + pcm_->mQueriedMDNSHostnames.erase(itor); + } +} void PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable( const mozilla::net::NrIceStunAddrArray& addrs) { @@ -56,8 +77,6 @@ void PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable( if (!pcm_->mStunAddrs.Length()) { pcm_->IceConnectionStateChange_m(dom::RTCIceConnectionState::Failed); } - - pcm_ = nullptr; } } @@ -317,8 +336,52 @@ void PeerConnectionMedia::ConnectSignals() { void PeerConnectionMedia::AddIceCandidate(const std::string& aCandidate, const std::string& aTransportId, const std::string& aUfrag) { + ASSERT_ON_THREAD(mMainThread); MOZ_ASSERT(!aTransportId.empty()); - mTransportHandler->AddIceCandidate(aTransportId, aCandidate, aUfrag); + + bool obfuscate_host_addresses = Preferences::GetBool( + "media.peerconnection.ice.obfuscate_host_addresses", false); + + if (obfuscate_host_addresses) { + std::vector tokens; + TokenizeCandidate(aCandidate, tokens); + + if (tokens.size() > 4) { + std::string addr = tokens[4]; + + // Check for address ending with .local + size_t nPeriods = std::count(addr.begin(), addr.end(), '.'); + size_t dotLocalLength = 6; // length of ".local" + + if (nPeriods == 1 && + addr.rfind(".local") + dotLocalLength == addr.length()) { + if (mStunAddrsRequest) { + PendingIceCandidate cand; + cand.mTokenizedCandidate = std::move(tokens); + cand.mTransportId = aTransportId; + cand.mUfrag = aUfrag; + mQueriedMDNSHostnames[addr].push_back(cand); + + mMainThread->Dispatch(NS_NewRunnableFunction( + "PeerConnectionMedia::SendQueryMDNSHostname", + [self = RefPtr(this), addr]() mutable { + if (self->mStunAddrsRequest) { + self->mStunAddrsRequest->SendQueryMDNSHostname( + nsCString(nsAutoCString(addr.c_str()))); + } + NS_ReleaseOnMainThreadSystemGroup( + "PeerConnectionMedia::SendQueryMDNSHostname", + self.forget()); + })); + } + // TODO: Bug 1535690, we don't want to tell the ICE context that remote + // trickle is done if we are waiting to resolve a mDNS candidate. + return; + } + } + } + + mTransportHandler->AddIceCandidate(aTransportId, aCandidate, aUfrag, ""); } void PeerConnectionMedia::UpdateNetworkState(bool online) { diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 02a0ca9572a0..9661c6901859 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -232,6 +232,14 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Used to store the mDNS hostnames that we have registered std::set mRegisteredMDNSHostnames; + // Used to store the mDNS hostnames that we have queried + struct PendingIceCandidate { + std::vector mTokenizedCandidate; + std::string mTransportId; + std::string mUfrag; + }; + std::map> mQueriedMDNSHostnames; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia) };