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
This commit is contained in:
Dan Minor 2019-10-01 12:58:23 +00:00
Родитель 940a75c186
Коммит 90e44f7695
10 изменённых файлов: 102 добавлений и 207 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -81,7 +81,8 @@ parent:
async AddIceCandidate(string transportId,
string candidate,
string ufrag);
string ufrag,
string obfuscatedAddr);
async UpdateNetworkState(bool online);

Просмотреть файл

@ -187,8 +187,8 @@ class LoopbackTransport : public MediaTransportHandler {
const std::vector<std::string>& 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 {}

Просмотреть файл

@ -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<std::string>& 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<std::string, Transport> 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<std::string> 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<std::string> mTokenizedCandidate;
const std::string mUfrag;
nsCOMPtr<nsICancelable> mCancel;
private:
~DNSListener() = default;
};
void PendingDNSRequestResolved(DNSListener* aListener);
nsCOMPtr<nsIDNSService> mDNSService;
std::set<RefPtr<DNSListener>> mPendingDNSRequests;
std::set<std::string> mSignaledAddresses;
// Init can only be done on main, but we want this to be usable on any thread
typedef MozPromise<bool, std::string, false> InitPromise;
RefPtr<InitPromise> mInitPromise;
@ -482,11 +441,6 @@ void MediaTransportHandlerSTS::Destroy() {
mInitPromise->Then(
mStsThread, __func__,
[this, self = RefPtr<MediaTransportHandlerSTS>(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<MediaTransportHandlerSTS>(this)]() {
std::vector<std::string> 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<NrIceMediaStream> 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<MediaTransportHandler::IceLogPromise>
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<net::NetAddr> 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<NrIceMediaStream> 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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
if (mChild) {
mChild->SendAddIceCandidate(aTransportId, aCandidate, aUfrag);
mChild->SendAddIceCandidate(aTransportId, aCandidate, aUfrag,
aObfuscatedAddress);
}
},
[](const nsCString& aError) {});

Просмотреть файл

@ -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;

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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<std::string> 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<PeerConnectionMedia>(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) {

Просмотреть файл

@ -232,6 +232,14 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// Used to store the mDNS hostnames that we have registered
std::set<std::string> mRegisteredMDNSHostnames;
// Used to store the mDNS hostnames that we have queried
struct PendingIceCandidate {
std::vector<std::string> mTokenizedCandidate;
std::string mTransportId;
std::string mUfrag;
};
std::map<std::string, std::list<PendingIceCandidate>> mQueriedMDNSHostnames;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
};