gecko-dev/netwerk/dns/DNSRequestChild.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

377 строки
11 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentChild.h"
#include "mozilla/net/ChildDNSService.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/SocketProcessChild.h"
#include "mozilla/SystemGroup.h"
#include "mozilla/Unused.h"
#include "nsIDNSRecord.h"
#include "nsIDNSByTypeRecord.h"
#include "nsHostResolver.h"
#include "nsTArray.h"
#include "nsNetAddr.h"
#include "nsIThread.h"
#include "nsThreadUtils.h"
using namespace mozilla::ipc;
namespace mozilla {
namespace net {
//-----------------------------------------------------------------------------
// ChildDNSRecord:
// A simple class to provide nsIDNSRecord on the child
//-----------------------------------------------------------------------------
class ChildDNSRecord : public nsIDNSRecord {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSRECORD
ChildDNSRecord(const DNSRecord& reply, uint16_t flags);
private:
virtual ~ChildDNSRecord() = default;
nsCString mCanonicalName;
nsTArray<NetAddr> mAddresses;
uint32_t mCurrent; // addr iterator
uint32_t mLength; // number of addrs
uint16_t mFlags;
};
NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord)
ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
: mCurrent(0), mFlags(flags) {
mCanonicalName = reply.canonicalName();
// A shame IPDL gives us no way to grab ownership of array: so copy it.
const nsTArray<NetAddr>& addrs = reply.addrs();
uint32_t i = 0;
mLength = addrs.Length();
for (; i < mLength; i++) {
mAddresses.AppendElement(addrs[i]);
}
}
//-----------------------------------------------------------------------------
// ChildDNSRecord::nsIDNSRecord
//-----------------------------------------------------------------------------
NS_IMETHODIMP
ChildDNSRecord::GetCanonicalName(nsACString& result) {
if (!(mFlags & nsHostResolver::RES_CANON_NAME)) {
return NS_ERROR_NOT_AVAILABLE;
}
result = mCanonicalName;
return NS_OK;
}
bug 1434852 - introducing TRR (DOH); r=mcmanus,valentin Provides an optional resolver mechanism for Firefox that allows running together with or instead of the native resolver. TRR offers resolving of host names using a dedicated DNS-over-HTTPS server (HTTPS is required, HTTP/2 is preferable). DNS-over-HTTPS (DOH) allows DNS resolves with enhanced privacy, secure transfers and improved performance. To keep the failure rate at a minimum, the TRR system manages a dynamic persistent blacklist for host names that can't be resolved with DOH but works with the native resolver. Blacklisted entries will not be retried over DOH for a couple of days. "localhost" and names in the ".local" TLD will not be resolved via DOH. TRR is preffed OFF by default and you need to set a URI for an available DOH server to be able to use it. Since the URI for DOH is set with a name itself, it may have to use the native resolver for bootstrapping. (Optionally, the user can set the IP address of the DOH server in a pref to avoid the required initial native resolve.) When TRR starts up, it will first verify that it works by checking a "confirmation" domain name. This confirmation domain is a pref by default set to "example.com". TRR will also by default await the captive-portal detection to raise its green flag before getting activated. All prefs for TRR are under the "network.trr" hierarchy. The DNS-over-HTTPS spec: https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-03 MozReview-Commit-ID: GuuU6vjTjlm --HG-- extra : rebase_source : 53fcca757334090ac05fec540ef29d109d5ceed3
2018-02-01 12:20:49 +03:00
NS_IMETHODIMP
ChildDNSRecord::IsTRR(bool* retval) {
bug 1434852 - introducing TRR (DOH); r=mcmanus,valentin Provides an optional resolver mechanism for Firefox that allows running together with or instead of the native resolver. TRR offers resolving of host names using a dedicated DNS-over-HTTPS server (HTTPS is required, HTTP/2 is preferable). DNS-over-HTTPS (DOH) allows DNS resolves with enhanced privacy, secure transfers and improved performance. To keep the failure rate at a minimum, the TRR system manages a dynamic persistent blacklist for host names that can't be resolved with DOH but works with the native resolver. Blacklisted entries will not be retried over DOH for a couple of days. "localhost" and names in the ".local" TLD will not be resolved via DOH. TRR is preffed OFF by default and you need to set a URI for an available DOH server to be able to use it. Since the URI for DOH is set with a name itself, it may have to use the native resolver for bootstrapping. (Optionally, the user can set the IP address of the DOH server in a pref to avoid the required initial native resolve.) When TRR starts up, it will first verify that it works by checking a "confirmation" domain name. This confirmation domain is a pref by default set to "example.com". TRR will also by default await the captive-portal detection to raise its green flag before getting activated. All prefs for TRR are under the "network.trr" hierarchy. The DNS-over-HTTPS spec: https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-03 MozReview-Commit-ID: GuuU6vjTjlm --HG-- extra : rebase_source : 53fcca757334090ac05fec540ef29d109d5ceed3
2018-02-01 12:20:49 +03:00
*retval = false;
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr* addr) {
if (mCurrent >= mLength) {
return NS_ERROR_NOT_AVAILABLE;
}
memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr));
// both Ipv4/6 use same bits for port, so safe to just use ipv4's field
addr->inet.port = htons(port);
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::GetAddresses(nsTArray<NetAddr>& aAddressArray) {
aAddressArray = mAddresses;
return NS_OK;
}
// shamelessly copied from nsDNSRecord
NS_IMETHODIMP
ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr** result) {
NetAddr addr;
nsresult rv = GetNextAddr(port, &addr);
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*result = new nsNetAddr(&addr));
return NS_OK;
}
// also copied from nsDNSRecord
NS_IMETHODIMP
ChildDNSRecord::GetNextAddrAsString(nsACString& result) {
NetAddr addr;
nsresult rv = GetNextAddr(0, &addr);
if (NS_FAILED(rv)) {
return rv;
}
char buf[kIPv6CStrBufSize];
if (NetAddrToString(&addr, buf, sizeof(buf))) {
result.Assign(buf);
return NS_OK;
}
NS_ERROR("NetAddrToString failed unexpectedly");
return NS_ERROR_FAILURE; // conversion failed for some reason
}
NS_IMETHODIMP
ChildDNSRecord::HasMore(bool* result) {
*result = mCurrent < mLength;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::Rewind() {
mCurrent = 0;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::ReportUnusable(uint16_t aPort) {
// "We thank you for your feedback" == >/dev/null
// TODO: we could send info back to parent.
return NS_OK;
}
class ChildDNSByTypeRecord : public nsIDNSByTypeRecord {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSBYTYPERECORD
explicit ChildDNSByTypeRecord(const nsTArray<nsCString>& reply);
private:
virtual ~ChildDNSByTypeRecord() = default;
nsTArray<nsCString> mRecords;
};
NS_IMPL_ISUPPORTS(ChildDNSByTypeRecord, nsIDNSByTypeRecord)
ChildDNSByTypeRecord::ChildDNSByTypeRecord(const nsTArray<nsCString>& reply) {
mRecords = reply;
}
NS_IMETHODIMP
ChildDNSByTypeRecord::GetRecords(nsTArray<nsCString>& aRecords) {
aRecords = mRecords;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) {
// deep copy
for (uint32_t i = 0; i < mRecords.Length(); i++) {
aRecords.Append(mRecords[i]);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// CancelDNSRequestEvent
//-----------------------------------------------------------------------------
class CancelDNSRequestEvent : public Runnable {
public:
CancelDNSRequestEvent(DNSRequestChild* aDnsReq, nsresult aReason)
: Runnable("net::CancelDNSRequestEvent"),
mDnsRequest(aDnsReq),
mReasonForCancel(aReason) {}
NS_IMETHOD Run() override {
if (mDnsRequest->mIPCOpen) {
// Send request to Parent process.
mDnsRequest->SendCancelDNSRequest(mDnsRequest->mHost, mDnsRequest->mType,
mDnsRequest->mOriginAttributes,
mDnsRequest->mFlags, mReasonForCancel);
}
return NS_OK;
}
private:
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<DNSRequestChild> mDnsRequest;
nsresult mReasonForCancel;
};
//-----------------------------------------------------------------------------
// DNSRequestChild
//-----------------------------------------------------------------------------
DNSRequestChild::DNSRequestChild(const nsACString& aHost, const uint16_t& aType,
const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags,
nsIDNSListener* aListener,
nsIEventTarget* target)
: mListener(aListener),
mTarget(target),
mResultStatus(NS_OK),
mHost(aHost),
mType(aType),
mOriginAttributes(aOriginAttributes),
mFlags(aFlags),
mIPCOpen(false) {}
void DNSRequestChild::StartRequest() {
// we can only do IPDL on the main thread
if (!NS_IsMainThread()) {
SystemGroup::Dispatch(
TaskCategory::Other,
NewRunnableMethod("net::DNSRequestChild::StartRequest", this,
&DNSRequestChild::StartRequest));
return;
}
if (XRE_IsContentProcess()) {
nsCOMPtr<nsIEventTarget> systemGroupEventTarget =
SystemGroup::EventTargetFor(TaskCategory::Other);
gNeckoChild->SetEventTargetForActor(this, systemGroupEventTarget);
mozilla::dom::ContentChild* cc =
static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
if (cc->IsShuttingDown()) {
return;
}
// Send request to Parent process.
gNeckoChild->SendPDNSRequestConstructor(this, mHost, mOriginAttributes,
mFlags);
} else if (XRE_IsSocketProcess()) {
SocketProcessChild* child = SocketProcessChild::GetSingleton();
if (!child->CanSend()) {
return;
}
child->SendPDNSRequestConstructor(this, mHost, mOriginAttributes, mFlags);
} else {
MOZ_ASSERT(false, "Wrong process");
return;
}
mIPCOpen = true;
// IPDL holds a reference until IPDL channel gets destroyed
AddIPDLReference();
}
void DNSRequestChild::CallOnLookupComplete() {
MOZ_ASSERT(mListener);
mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
}
void DNSRequestChild::CallOnLookupByTypeComplete() {
MOZ_ASSERT(mListener);
MOZ_ASSERT(mType != nsIDNSService::RESOLVE_TYPE_DEFAULT);
mListener->OnLookupByTypeComplete(this, mResultByTypeRecords, mResultStatus);
}
mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
const DNSRequestResponse& reply) {
mIPCOpen = false;
MOZ_ASSERT(mListener);
switch (reply.type()) {
case DNSRequestResponse::TDNSRecord: {
mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
break;
}
case DNSRequestResponse::Tnsresult: {
mResultStatus = reply.get_nsresult();
break;
}
case DNSRequestResponse::TArrayOfnsCString: {
MOZ_ASSERT(mType != nsIDNSService::RESOLVE_TYPE_DEFAULT);
mResultByTypeRecords =
new ChildDNSByTypeRecord(reply.get_ArrayOfnsCString());
break;
}
default:
MOZ_ASSERT_UNREACHABLE("unknown type");
return IPC_FAIL_NO_REASON(this);
}
MOZ_ASSERT(NS_IsMainThread());
bool targetIsMain = false;
if (!mTarget) {
targetIsMain = true;
} else {
mTarget->IsOnCurrentThread(&targetIsMain);
}
if (targetIsMain) {
if (mType == nsIDNSService::RESOLVE_TYPE_DEFAULT) {
CallOnLookupComplete();
} else {
CallOnLookupByTypeComplete();
}
} else {
if (mType == nsIDNSService::RESOLVE_TYPE_DEFAULT) {
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod("net::DNSRequestChild::CallOnLookupComplete", this,
&DNSRequestChild::CallOnLookupComplete);
mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
} else {
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod("net::DNSRequestChild::CallOnLookupByTypeComplete",
this, &DNSRequestChild::CallOnLookupByTypeComplete);
mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
}
}
Unused << Send__delete__(this);
return IPC_OK();
}
void DNSRequestChild::ReleaseIPDLReference() {
// Request is done or destroyed. Remove it from the hash table.
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<ChildDNSService> dnsServiceChild =
dont_AddRef(ChildDNSService::GetSingleton());
dnsServiceChild->NotifyRequestDone(this);
Release();
}
void DNSRequestChild::ActorDestroy(ActorDestroyReason why) { mIPCOpen = false; }
//-----------------------------------------------------------------------------
// DNSRequestChild::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(DNSRequestChild, nsICancelable)
//-----------------------------------------------------------------------------
// DNSRequestChild::nsICancelable
//-----------------------------------------------------------------------------
NS_IMETHODIMP
DNSRequestChild::Cancel(nsresult reason) {
if (mIPCOpen) {
// We can only do IPDL on the main thread
nsCOMPtr<nsIRunnable> runnable = new CancelDNSRequestEvent(this, reason);
SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
}
return NS_OK;
}
//------------------------------------------------------------------------------
} // namespace net
} // namespace mozilla