Bug 1713796 - P1: Move nsHostRecord to another file, r=necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D117322
This commit is contained in:
Kershaw Chang 2021-06-16 08:14:10 +00:00
Родитель b45ba442df
Коммит 0c9e5842a2
14 изменённых файлов: 945 добавлений и 911 удалений

26
netwerk/dns/DNSLogging.h Normal file
Просмотреть файл

@ -0,0 +1,26 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_DNSLogging_h
#define mozilla_DNSLogging_h
#include "mozilla/Logging.h"
#undef LOG
namespace mozilla {
namespace net {
extern LazyLogModule gHostResolverLog;
} // namespace net
} // namespace mozilla
#define LOG(msg) \
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug, msg)
#define LOG1(msg) \
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Error, msg)
#define LOG_ENABLED() \
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
#endif // mozilla_DNSLogging_h

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

@ -8,17 +8,12 @@
#include "mozilla/EndianUtils.h"
#include "mozilla/ScopeExit.h"
#include "ODoHService.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
namespace mozilla {
namespace net {
extern mozilla::LazyLogModule gHostResolverLog;
#undef LOG
#undef LOG_ENABLED
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
#define LOG_ENABLED() \
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
static uint16_t get16bit(const unsigned char* aData, unsigned int index) {
return ((aData[index] << 8) | aData[index + 1]);
}

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

@ -10,17 +10,12 @@
#include "nsIURIMutator.h"
#include "ODoHService.h"
#include "TRRService.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
namespace mozilla {
namespace net {
#undef LOG
#undef LOG_ENABLED
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
#define LOG_ENABLED() \
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
NS_IMETHODIMP
ODoH::Run() {
if (!gODoHService) {

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

@ -18,6 +18,8 @@
#include "ODoH.h"
#include "TRRService.h"
#include "nsURLHelper.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
static const char kODoHProxyURIPref[] = "network.trr.odoh.proxy_uri";
static const char kODoHTargetHostPref[] = "network.trr.odoh.target_host";
@ -29,9 +31,6 @@ namespace net {
ODoHService* gODoHService = nullptr;
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
NS_IMPL_ISUPPORTS(ODoHService, nsIDNSListener, nsIObserver,
nsISupportsWeakReference, nsITimerCallback,
nsIStreamLoaderObserver)

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

@ -37,17 +37,12 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/Tokenizer.h"
#include "mozilla/UniquePtr.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
namespace mozilla {
namespace net {
#undef LOG
#undef LOG_ENABLED
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
#define LOG_ENABLED() \
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor,
nsIStreamListener, nsIRunnable, nsITimerCallback)
@ -1026,8 +1021,5 @@ void TRR::Cancel(nsresult aStatus) {
bool TRR::UseDefaultServer() { return !mRec || mRec->mTrrServer.IsEmpty(); }
#undef LOG
// namespace
} // namespace net
} // namespace mozilla

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

@ -5,14 +5,12 @@
#include "TRRQuery.h"
#include "TRR.h"
#include "ODoH.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
namespace mozilla {
namespace net {
#undef LOG
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
static already_AddRefed<AddrInfo> merge_rrset(AddrInfo* rrto,
AddrInfo* rrfrom) {
MOZ_ASSERT(rrto && rrfrom);

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

@ -24,6 +24,8 @@
#include "mozilla/TelemetryComms.h"
#include "mozilla/Tokenizer.h"
#include "mozilla/net/rust_helper.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
#if defined(XP_WIN) && !defined(__MINGW32__)
# include <shlobj_core.h> // for SHGetSpecialFolderPathA
@ -40,10 +42,6 @@ static const char kDisableIpv6Pref[] = "network.dns.disableIPv6";
namespace mozilla {
namespace net {
#undef LOG
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
TRRService* gTRRService = nullptr;
StaticRefPtr<nsIThread> sTRRBackgroundThread;
static Atomic<TRRService*> sTRRServicePtr;
@ -1302,7 +1300,5 @@ AHostResolver::LookupStatus TRRService::CompleteLookupByType(
return LOOKUP_OK;
}
#undef LOG
} // namespace net
} // namespace mozilla

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

@ -6,20 +6,17 @@
#include "TRRServiceBase.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "nsHostResolver.h"
#include "nsNetUtil.h"
#include "nsIOService.h"
#include "nsIDNSService.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
namespace mozilla {
namespace net {
#undef LOG
extern mozilla::LazyLogModule gHostResolverLog;
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
TRRServiceBase::TRRServiceBase()
: mMode(nsIDNSService::MODE_NATIVEONLY), mURISetByDetection(false) {}

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

@ -54,7 +54,6 @@ EXPORTS.mozilla.net += [
SOURCES += [
"GetAddrInfo.cpp", # Undefines UNICODE
"nsEffectiveTLDService.cpp", # Excluded from UNIFIED_SOURCES due to special build flags.
"nsHostResolver.cpp", # Redefines LOG
]
UNIFIED_SOURCES += [
@ -71,6 +70,8 @@ UNIFIED_SOURCES += [
"NativeDNSResolverOverrideChild.cpp",
"NativeDNSResolverOverrideParent.cpp",
"nsDNSService2.cpp",
"nsHostRecord.cpp",
"nsHostResolver.cpp",
"nsIDNService.cpp",
"ODoH.cpp",
"ODoHService.cpp",

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

@ -0,0 +1,532 @@
/* vim:set ts=4 sw=2 sts=2 et cin: */
/* 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 "nsHostRecord.h"
#include "TRRQuery.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
//----------------------------------------------------------------------------
// this macro filters out any flags that are not used when constructing the
// host key. the significant flags are those that would affect the resulting
// host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
#define RES_KEY_FLAGS(_f) \
((_f) & \
(nsHostResolver::RES_CANON_NAME | nsHostResolver::RES_DISABLE_TRR | \
nsIDNSService::RESOLVE_TRR_MODE_MASK | nsHostResolver::RES_IP_HINT))
#define IS_ADDR_TYPE(_type) ((_type) == nsIDNSService::RESOLVE_TYPE_DEFAULT)
#define IS_OTHER_TYPE(_type) ((_type) != nsIDNSService::RESOLVE_TYPE_DEFAULT)
//----------------------------------------------------------------------------
nsHostKey::nsHostKey(const nsACString& aHost, const nsACString& aTrrServer,
uint16_t aType, uint16_t aFlags, uint16_t aAf, bool aPb,
const nsACString& aOriginsuffix)
: host(aHost),
mTrrServer(aTrrServer),
type(aType),
flags(aFlags),
af(aAf),
pb(aPb),
originSuffix(aOriginsuffix) {}
bool nsHostKey::operator==(const nsHostKey& other) const {
return host == other.host && mTrrServer == other.mTrrServer &&
type == other.type &&
RES_KEY_FLAGS(flags) == RES_KEY_FLAGS(other.flags) && af == other.af &&
originSuffix == other.originSuffix;
}
PLDHashNumber nsHostKey::Hash() const {
return AddToHash(HashString(host.get()), HashString(mTrrServer.get()), type,
RES_KEY_FLAGS(flags), af, HashString(originSuffix.get()));
}
size_t nsHostKey::SizeOfExcludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = 0;
n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += mTrrServer.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
return n;
}
//----------------------------------------------------------------------------
// nsHostRecord
//----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS0(nsHostRecord)
nsHostRecord::nsHostRecord(const nsHostKey& key)
: nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
void nsHostRecord::Invalidate() { mDoomed = true; }
void nsHostRecord::Cancel() {
RefPtr<TRRQuery> query;
{
auto lock = mTRRQuery.Lock();
query.swap(lock.ref());
}
if (query) {
query->Cancel(NS_ERROR_ABORT);
}
}
nsHostRecord::ExpirationStatus nsHostRecord::CheckExpiration(
const mozilla::TimeStamp& now) const {
if (!mGraceStart.IsNull() && now >= mGraceStart && !mValidEnd.IsNull() &&
now < mValidEnd) {
return nsHostRecord::EXP_GRACE;
}
if (!mValidEnd.IsNull() && now < mValidEnd) {
return nsHostRecord::EXP_VALID;
}
return nsHostRecord::EXP_EXPIRED;
}
void nsHostRecord::SetExpiration(const mozilla::TimeStamp& now,
unsigned int valid, unsigned int grace) {
mValidStart = now;
if ((valid + grace) < 60) {
grace = 60 - valid;
LOG(("SetExpiration: artificially bumped grace to %d\n", grace));
}
mGraceStart = now + TimeDuration::FromSeconds(valid);
mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
mTtl = valid;
}
void nsHostRecord::CopyExpirationTimesAndFlagsFrom(
const nsHostRecord* aFromHostRecord) {
// This is used to copy information from a cache entry to a record. All
// information necessary for HasUsableRecord needs to be copied.
mValidStart = aFromHostRecord->mValidStart;
mValidEnd = aFromHostRecord->mValidEnd;
mGraceStart = aFromHostRecord->mGraceStart;
mDoomed = aFromHostRecord->mDoomed;
}
bool nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
if (mDoomed) {
return false;
}
return HasUsableResultInternal(now, queryFlags);
}
//----------------------------------------------------------------------------
// AddrHostRecord
//----------------------------------------------------------------------------
static size_t SizeOfResolveHostCallbackListExcludingHead(
const mozilla::LinkedList<RefPtr<nsResolveHostCallback>>& aCallbacks,
MallocSizeOf mallocSizeOf) {
size_t n = aCallbacks.sizeOfExcludingThis(mallocSizeOf);
for (const nsResolveHostCallback* t = aCallbacks.getFirst(); t;
t = t->getNext()) {
n += t->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
AddrHostRecord::~AddrHostRecord() {
mCallbacks.clear();
Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mUnusableCount);
}
bool AddrHostRecord::Blocklisted(const NetAddr* aQuery) {
addr_info_lock.AssertCurrentThreadOwns();
LOG(("Checking unusable list for host [%s], host record [%p].\n", host.get(),
this));
// skip the string conversion for the common case of no blocklist
if (!mUnusableItems.Length()) {
return false;
}
char buf[kIPv6CStrBufSize];
if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
return false;
}
nsDependentCString strQuery(buf);
for (uint32_t i = 0; i < mUnusableItems.Length(); i++) {
if (mUnusableItems.ElementAt(i).Equals(strQuery)) {
LOG(("Address [%s] is blocklisted for host [%s].\n", buf, host.get()));
return true;
}
}
return false;
}
void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
addr_info_lock.AssertCurrentThreadOwns();
LOG(
("Adding address to blocklist for host [%s], host record [%p]."
"used trr=%d\n",
host.get(), this, mTRRSuccess));
++mUnusableCount;
char buf[kIPv6CStrBufSize];
if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
LOG(
("Successfully adding address [%s] to blocklist for host "
"[%s].\n",
buf, host.get()));
mUnusableItems.AppendElement(nsCString(buf));
}
}
void AddrHostRecord::ResetBlocklist() {
addr_info_lock.AssertCurrentThreadOwns();
LOG(("Resetting blocklist for host [%s], host record [%p].\n", host.get(),
this));
mUnusableItems.Clear();
}
size_t AddrHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
n += mallocSizeOf(addr.get());
n += mUnusableItems.ShallowSizeOfExcludingThis(mallocSizeOf);
for (size_t i = 0; i < mUnusableItems.Length(); i++) {
n += mUnusableItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
}
return n;
}
bool AddrHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
// don't use cached negative results for high priority queries.
if (negative && IsHighPriority(queryFlags)) {
return false;
}
if (CheckExpiration(now) == EXP_EXPIRED) {
return false;
}
if (negative) {
return true;
}
return addr_info || addr;
}
// Returns true if the entry can be removed, or false if it should be left.
// Sets ResolveAgain true for entries being resolved right now.
bool AddrHostRecord::RemoveOrRefresh(bool aTrrToo) {
// no need to flush TRRed names, they're not resolved "locally"
MutexAutoLock lock(addr_info_lock);
if (addr_info && !aTrrToo && addr_info->IsTRROrODoH()) {
return false;
}
if (LoadNative()) {
if (!onQueue()) {
// The request has been passed to the OS resolver. The resultant DNS
// record should be considered stale and not trusted; set a flag to
// ensure it is called again.
StoreResolveAgain(true);
}
// if onQueue is true, the host entry is already added to the cache
// but is still pending to get resolved: just leave it in hash.
return false;
}
// Already resolved; not in a pending state; remove from cache
return true;
}
void AddrHostRecord::ResolveComplete() {
if (LoadNativeUsed()) {
if (mNativeSuccess) {
uint32_t millis = static_cast<uint32_t>(mNativeDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_NATIVE_LOOKUP_TIME, millis);
}
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
mNativeSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osOK
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osFail);
}
if (mResolverType == DNSResolverType::ODoH) {
// XXX(kershaw): Consider adding the failed host name into a blocklist.
if (mTRRSuccess) {
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_ODOH_LOOKUP_TIME, millis);
}
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
Telemetry::Accumulate(Telemetry::ODOH_SKIP_REASON_ODOH_FIRST,
static_cast<uint32_t>(mTRRSkippedReason));
}
return;
}
if (mResolverType == DNSResolverType::TRR) {
if (mTRRSuccess) {
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_TRR_LOOKUP_TIME3,
TRRService::ProviderKey(), millis);
}
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
mTRRSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrOK
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrFail);
}
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_TRR_FIRST2,
TRRService::ProviderKey(),
static_cast<uint32_t>(mTRRSkippedReason));
if (!mTRRSuccess) {
Telemetry::Accumulate(
mNativeSuccess ? Telemetry::TRR_SKIP_REASON_NATIVE_SUCCESS
: Telemetry::TRR_SKIP_REASON_NATIVE_FAILED,
TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
}
}
if (mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
if (flags & nsIDNSService::RESOLVE_DISABLE_TRR) {
// TRR is disabled on request, which is a next-level back-off method.
Telemetry::Accumulate(Telemetry::DNS_TRR_DISABLED3,
TRRService::ProviderKey(), mNativeSuccess);
} else {
if (mTRRSuccess) {
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::TRR);
} else if (mNativeSuccess) {
if (mResolverType == DNSResolverType::TRR) {
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::NativeAfterTRR);
} else {
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::Native);
}
} else {
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::BothFailed);
}
}
}
switch (mEffectiveTRRMode) {
case nsIRequest::TRR_DISABLED_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::nativeOnly);
break;
case nsIRequest::TRR_FIRST_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrFirst);
break;
case nsIRequest::TRR_ONLY_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrOnly);
break;
case nsIRequest::TRR_DEFAULT_MODE:
MOZ_ASSERT_UNREACHABLE("We should not have a default value here");
break;
}
if (mResolverType == DNSResolverType::TRR && !mTRRSuccess && mNativeSuccess &&
gTRRService) {
gTRRService->AddToBlocklist(nsCString(host), originSuffix, pb, true);
}
}
AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(uint16_t aFlags) {
if (IsHighPriority(aFlags)) {
return AddrHostRecord::DNS_PRIORITY_HIGH;
}
if (IsMediumPriority(aFlags)) {
return AddrHostRecord::DNS_PRIORITY_MEDIUM;
}
return AddrHostRecord::DNS_PRIORITY_LOW;
}
//----------------------------------------------------------------------------
// TypeHostRecord
//----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
: nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
bool TypeHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
if (CheckExpiration(now) == EXP_EXPIRED) {
return false;
}
if (negative) {
return true;
}
return !mResults.is<Nothing>();
}
bool TypeHostRecord::RefreshForNegativeResponse() const { return false; }
NS_IMETHODIMP TypeHostRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
// deep copy
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordTxt>()) {
return NS_ERROR_NOT_AVAILABLE;
}
aRecords = mResults.as<CopyableTArray<nsCString>>();
return NS_OK;
}
NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
// deep copy
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordTxt>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<CopyableTArray<nsCString>>();
for (uint32_t i = 0; i < results.Length(); i++) {
aRecords.Append(results[i]);
}
return NS_OK;
}
size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
return n;
}
uint32_t TypeHostRecord::GetType() {
MutexAutoLock lock(mResultsLock);
return mResults.match(
[](TypeRecordEmpty&) {
MOZ_ASSERT(false, "This should never be the case");
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
},
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
}
TypeRecordResultType TypeHostRecord::GetResults() {
MutexAutoLock lock(mResultsLock);
return mResults;
}
NS_IMETHODIMP
TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
for (const SVCB& r : results) {
RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
aRecords.AppendElement(rec);
}
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
nsISVCBRecord** aRecord) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
aNoHttp2, aNoHttp3, results, mAllRecordsExcluded);
if (!result) {
return NS_ERROR_NOT_AVAILABLE;
}
result.forget(aRecord);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetAllRecordsWithEchConfig(
bool aNoHttp2, bool aNoHttp3, bool* aAllRecordsHaveEchConfig,
bool* aAllRecordsInH3ExcludedList,
nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& records = mResults.as<TypeRecordHTTPSSVC>();
GetAllRecordsWithEchConfigInternal(aNoHttp2, aNoHttp3, records,
aAllRecordsHaveEchConfig,
aAllRecordsInH3ExcludedList, aResult);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetHasIPAddresses(bool* aResult) {
NS_ENSURE_ARG(aResult);
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
*aResult = HasIPAddressesInternal(results);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetAllRecordsExcluded(bool* aResult) {
NS_ENSURE_ARG(aResult);
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
*aResult = mAllRecordsExcluded;
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetTtl(uint32_t* aResult) {
NS_ENSURE_ARG(aResult);
*aResult = mTtl;
return NS_OK;
}

365
netwerk/dns/nsHostRecord.h Normal file
Просмотреть файл

@ -0,0 +1,365 @@
/* vim:set ts=4 sw=2 sts=2 et cin: */
/* 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/. */
#ifndef nsHostRecord_h__
#define nsHostRecord_h__
#include "mozilla/LinkedList.h"
#include "mozilla/net/HTTPSSVC.h"
#include "nsIDNSService.h"
#include "nsIDNSByTypeRecord.h"
#include "PLDHashTable.h"
#include "TRRSkippedReason.h"
class nsHostRecord;
class nsHostResolver;
namespace mozilla {
namespace net {
class TRR;
class TRRQuery;
} // namespace net
} // namespace mozilla
/**
* This class is used to notify listeners when a ResolveHost operation is
* complete. Classes that derive it must implement threadsafe nsISupports
* to be able to use RefPtr with this class.
*/
class nsResolveHostCallback
: public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>,
public nsISupports {
public:
/**
* OnResolveHostComplete
*
* this function is called to complete a host lookup initiated by
* nsHostResolver::ResolveHost. it may be invoked recursively from
* ResolveHost or on an unspecified background thread.
*
* NOTE: it is the responsibility of the implementor of this method
* to handle the callback in a thread safe manner.
*
* @param resolver
* nsHostResolver object associated with this result
* @param record
* the host record containing the results of the lookup
* @param status
* if successful, |record| contains non-null results
*/
virtual void OnResolveHostComplete(nsHostResolver* resolver,
nsHostRecord* record, nsresult status) = 0;
/**
* EqualsAsyncListener
*
* Determines if the listener argument matches the listener member var.
* For subclasses not implementing a member listener, should return false.
* For subclasses having a member listener, the function should check if
* they are the same. Used for cases where a pointer to an object
* implementing nsResolveHostCallback is unknown, but a pointer to
* the original listener is known.
*
* @param aListener
* nsIDNSListener object associated with the original request
*/
virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
protected:
virtual ~nsResolveHostCallback() = default;
};
struct nsHostKey {
const nsCString host;
const nsCString mTrrServer;
uint16_t type = 0;
uint16_t flags = 0;
uint16_t af = 0;
bool pb = false;
const nsCString originSuffix;
explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
uint16_t type, uint16_t flags, uint16_t af, bool pb,
const nsACString& originSuffix);
bool operator==(const nsHostKey& other) const;
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
PLDHashNumber Hash() const;
};
/**
* nsHostRecord - ref counted object type stored in host resolver cache.
*/
class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
public nsHostKey,
public nsISupports {
using TRRSkippedReason = mozilla::net::TRRSkippedReason;
public:
NS_DECL_THREADSAFE_ISUPPORTS
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return 0;
}
// Returns the TRR mode encoded by the flags
nsIRequest::TRRMode TRRMode();
// Records the first reason that caused TRR to be skipped or to fail.
void RecordReason(TRRSkippedReason reason) {
if (mTRRSkippedReason == TRRSkippedReason::TRR_UNSET) {
mTRRSkippedReason = reason;
}
}
enum DnsPriority {
DNS_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
DNS_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
DNS_PRIORITY_HIGH,
};
protected:
friend class nsHostResolver;
friend class mozilla::net::TRR;
friend class mozilla::net::TRRQuery;
explicit nsHostRecord(const nsHostKey& key);
virtual ~nsHostRecord() = default;
// Mark hostrecord as not usable
void Invalidate();
enum ExpirationStatus {
EXP_VALID,
EXP_GRACE,
EXP_EXPIRED,
};
ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
// Convenience function for setting the timestamps above (mValidStart,
// mValidEnd, and mGraceStart). valid and grace are durations in seconds.
void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
unsigned int grace);
void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord);
// Checks if the record is usable (not expired and has a value)
bool HasUsableResult(const mozilla::TimeStamp& now,
uint16_t queryFlags = 0) const;
static DnsPriority GetPriority(uint16_t aFlags);
virtual void Cancel();
virtual bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const = 0;
virtual bool RefreshForNegativeResponse() const { return true; }
mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks;
bool IsAddrRecord() const {
return type == nsIDNSService::RESOLVE_TYPE_DEFAULT;
}
// When the record began being valid. Used mainly for bookkeeping.
mozilla::TimeStamp mValidStart;
// When the record is no longer valid (it's time of expiration)
mozilla::TimeStamp mValidEnd;
// When the record enters its grace period. This must be before mValidEnd.
// If a record is in its grace period (and not expired), it will be used
// but a request to refresh it will be made.
mozilla::TimeStamp mGraceStart;
uint32_t mTtl = 0;
// The computed TRR mode that is actually used by the request.
// It is set in nsHostResolver::NameLookup and is based on the mode of the
// default resolver and the TRRMode encoded in the flags.
// The mode into account if the TRR service is disabled,
// parental controls are on, domain matches exclusion list, etc.
nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
TRRSkippedReason mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
TRRSkippedReason mTRRAFailReason = TRRSkippedReason::TRR_UNSET;
TRRSkippedReason mTRRAAAAFailReason = TRRSkippedReason::TRR_UNSET;
mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
// counter of outstanding resolving calls
mozilla::Atomic<int32_t> mResolving{0};
// True if this record is a cache of a failed lookup. Negative cache
// entries are valid just like any other (though never for more than 60
// seconds), but a use of that negative entry forces an asynchronous refresh.
bool negative = false;
// Explicitly expired
bool mDoomed = false;
};
// b020e996-f6ab-45e5-9bf5-1da71dd0053a
#define ADDRHOSTRECORD_IID \
{ \
0xb020e996, 0xf6ab, 0x45e5, { \
0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \
} \
}
class AddrHostRecord final : public nsHostRecord {
using Mutex = mozilla::Mutex;
using DNSResolverType = mozilla::net::DNSResolverType;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
NS_DECL_ISUPPORTS_INHERITED
/* a fully resolved host record has either a non-null |addr_info| or |addr|
* field. if |addr_info| is null, it implies that the |host| is an IP
* address literal. in which case, |addr| contains the parsed address.
* otherwise, if |addr_info| is non-null, then it contains one or many
* IP addresses corresponding to the given host name. if both |addr_info|
* and |addr| are null, then the given host has not yet been fully resolved.
* |af| is the address family of the record we are querying for.
*/
/* the lock protects |addr_info| and |addr_info_gencnt| because they
* are mutable and accessed by the resolver worker thread and the
* nsDNSService2 class. |addr| doesn't change after it has been
* assigned a value. only the resolver worker thread modifies
* nsHostRecord (and only in nsHostResolver::CompleteLookup);
* the other threads just read it. therefore the resolver worker
* thread doesn't need to lock when reading |addr_info|.
*/
Mutex addr_info_lock{"AddrHostRecord.addr_info_lock"};
// generation count of |addr_info|
int addr_info_gencnt = 0;
RefPtr<mozilla::net::AddrInfo> addr_info;
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
// hold addr_info_lock when calling the blocklist functions
bool Blocklisted(const mozilla::net::NetAddr* query);
void ResetBlocklist();
void ReportUnusable(const mozilla::net::NetAddr* aAddress);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; }
private:
friend class nsHostResolver;
friend class mozilla::net::TRR;
friend class mozilla::net::TRRQuery;
explicit AddrHostRecord(const nsHostKey& key);
~AddrHostRecord();
// Checks if the record is usable (not expired and has a value)
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const override;
bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved
// as needed to resolve again.
void ResolveComplete();
static DnsPriority GetPriority(uint16_t aFlags);
// true if pending and on the queue (not yet given to getaddrinfo())
bool onQueue() { return LoadNative() && isInList(); }
// When the lookups of this record started and their durations
mozilla::TimeStamp mTrrStart;
mozilla::TimeStamp mNativeStart;
mozilla::TimeDuration mTrrDuration;
mozilla::TimeDuration mNativeDuration;
// TRR or ODoH was used on this record
mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
uint8_t mTRRSuccess = 0; // number of successful TRR responses
uint8_t mNativeSuccess = 0; // number of native lookup responses
// clang-format off
MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
// true if this record is being resolved "natively", which means that
// it is either on the pending queue or owned by one of the worker threads.
(uint16_t, Native, 1),
(uint16_t, NativeUsed, 1),
// true if off queue and contributing to mActiveAnyThreadCount
(uint16_t, UsingAnyThread, 1),
(uint16_t, GetTtl, 1),
(uint16_t, ResolveAgain, 1)
))
// clang-format on
// The number of times ReportUnusable() has been called in the record's
// lifetime.
uint32_t mUnusableCount = 0;
// a list of addresses associated with this record that have been reported
// as unusable. the list is kept as a set of strings to make it independent
// of gencnt.
nsTArray<nsCString> mUnusableItems;
};
NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
// 77b786a7-04be-44f2-987c-ab8aa96676e0
#define TYPEHOSTRECORD_IID \
{ \
0x77b786a7, 0x04be, 0x44f2, { \
0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \
} \
}
class TypeHostRecord final : public nsHostRecord,
public nsIDNSTXTRecord,
public nsIDNSHTTPSSVCRecord,
public mozilla::net::DNSHTTPSSVCRecordBase {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDNSTXTRECORD
NS_DECL_NSIDNSHTTPSSVCRECORD
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
uint32_t GetType();
mozilla::net::TypeRecordResultType GetResults();
private:
friend class nsHostResolver;
friend class mozilla::net::TRRQuery;
explicit TypeHostRecord(const nsHostKey& key);
~TypeHostRecord();
// Checks if the record is usable (not expired and has a value)
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const override;
bool RefreshForNegativeResponse() const override;
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
mozilla::Mutex mResultsLock{"TypeHostRecord.mResultsLock"};
// When the lookups of this record started (for telemetry).
mozilla::TimeStamp mStart;
bool mAllRecordsExcluded = false;
};
NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID)
static inline bool IsHighPriority(uint16_t flags) {
return !(flags & (nsHostRecord::DNS_PRIORITY_LOW |
nsHostRecord::DNS_PRIORITY_MEDIUM));
}
static inline bool IsMediumPriority(uint16_t flags) {
return flags & nsHostRecord::DNS_PRIORITY_MEDIUM;
}
static inline bool IsLowPriority(uint16_t flags) {
return flags & nsHostRecord::DNS_PRIORITY_LOW;
}
#endif // nsHostRecord_h__

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

@ -47,6 +47,8 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_network.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
using namespace mozilla;
using namespace mozilla::net;
@ -86,12 +88,6 @@ static_assert(
namespace mozilla::net {
LazyLogModule gHostResolverLog("nsHostResolver");
#define LOG(args) \
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug, args)
#define LOG1(args) \
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Error, args)
#define LOG_ENABLED() \
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
} // namespace mozilla::net
//----------------------------------------------------------------------------
@ -137,530 +133,6 @@ class nsResState {
//----------------------------------------------------------------------------
static inline bool IsHighPriority(uint16_t flags) {
return !(flags & (nsHostResolver::RES_PRIORITY_LOW |
nsHostResolver::RES_PRIORITY_MEDIUM));
}
static inline bool IsMediumPriority(uint16_t flags) {
return flags & nsHostResolver::RES_PRIORITY_MEDIUM;
}
static inline bool IsLowPriority(uint16_t flags) {
return flags & nsHostResolver::RES_PRIORITY_LOW;
}
//----------------------------------------------------------------------------
// this macro filters out any flags that are not used when constructing the
// host key. the significant flags are those that would affect the resulting
// host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
#define RES_KEY_FLAGS(_f) \
((_f) & \
(nsHostResolver::RES_CANON_NAME | nsHostResolver::RES_DISABLE_TRR | \
nsIDNSService::RESOLVE_TRR_MODE_MASK | nsHostResolver::RES_IP_HINT))
#define IS_ADDR_TYPE(_type) ((_type) == nsIDNSService::RESOLVE_TYPE_DEFAULT)
#define IS_OTHER_TYPE(_type) ((_type) != nsIDNSService::RESOLVE_TYPE_DEFAULT)
nsHostKey::nsHostKey(const nsACString& aHost, const nsACString& aTrrServer,
uint16_t aType, uint16_t aFlags, uint16_t aAf, bool aPb,
const nsACString& aOriginsuffix)
: host(aHost),
mTrrServer(aTrrServer),
type(aType),
flags(aFlags),
af(aAf),
pb(aPb),
originSuffix(aOriginsuffix) {}
bool nsHostKey::operator==(const nsHostKey& other) const {
return host == other.host && mTrrServer == other.mTrrServer &&
type == other.type &&
RES_KEY_FLAGS(flags) == RES_KEY_FLAGS(other.flags) && af == other.af &&
originSuffix == other.originSuffix;
}
PLDHashNumber nsHostKey::Hash() const {
return AddToHash(HashString(host.get()), HashString(mTrrServer.get()), type,
RES_KEY_FLAGS(flags), af, HashString(originSuffix.get()));
}
size_t nsHostKey::SizeOfExcludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = 0;
n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += mTrrServer.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
return n;
}
NS_IMPL_ISUPPORTS0(nsHostRecord)
nsHostRecord::nsHostRecord(const nsHostKey& key)
: nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
void nsHostRecord::Invalidate() { mDoomed = true; }
void nsHostRecord::Cancel() {
RefPtr<TRRQuery> query;
{
auto lock = mTRRQuery.Lock();
query.swap(lock.ref());
}
if (query) {
query->Cancel(NS_ERROR_ABORT);
}
}
nsHostRecord::ExpirationStatus nsHostRecord::CheckExpiration(
const mozilla::TimeStamp& now) const {
if (!mGraceStart.IsNull() && now >= mGraceStart && !mValidEnd.IsNull() &&
now < mValidEnd) {
return nsHostRecord::EXP_GRACE;
}
if (!mValidEnd.IsNull() && now < mValidEnd) {
return nsHostRecord::EXP_VALID;
}
return nsHostRecord::EXP_EXPIRED;
}
void nsHostRecord::SetExpiration(const mozilla::TimeStamp& now,
unsigned int valid, unsigned int grace) {
mValidStart = now;
if ((valid + grace) < 60) {
grace = 60 - valid;
LOG(("SetExpiration: artificially bumped grace to %d\n", grace));
}
mGraceStart = now + TimeDuration::FromSeconds(valid);
mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
mTtl = valid;
}
void nsHostRecord::CopyExpirationTimesAndFlagsFrom(
const nsHostRecord* aFromHostRecord) {
// This is used to copy information from a cache entry to a record. All
// information necessary for HasUsableRecord needs to be copied.
mValidStart = aFromHostRecord->mValidStart;
mValidEnd = aFromHostRecord->mValidEnd;
mGraceStart = aFromHostRecord->mGraceStart;
mDoomed = aFromHostRecord->mDoomed;
}
bool nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
if (mDoomed) {
return false;
}
return HasUsableResultInternal(now, queryFlags);
}
static size_t SizeOfResolveHostCallbackListExcludingHead(
const mozilla::LinkedList<RefPtr<nsResolveHostCallback>>& aCallbacks,
MallocSizeOf mallocSizeOf) {
size_t n = aCallbacks.sizeOfExcludingThis(mallocSizeOf);
for (const nsResolveHostCallback* t = aCallbacks.getFirst(); t;
t = t->getNext()) {
n += t->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
AddrHostRecord::~AddrHostRecord() {
mCallbacks.clear();
Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mUnusableCount);
}
bool AddrHostRecord::Blocklisted(const NetAddr* aQuery) {
addr_info_lock.AssertCurrentThreadOwns();
LOG(("Checking unusable list for host [%s], host record [%p].\n", host.get(),
this));
// skip the string conversion for the common case of no blocklist
if (!mUnusableItems.Length()) {
return false;
}
char buf[kIPv6CStrBufSize];
if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
return false;
}
nsDependentCString strQuery(buf);
for (uint32_t i = 0; i < mUnusableItems.Length(); i++) {
if (mUnusableItems.ElementAt(i).Equals(strQuery)) {
LOG(("Address [%s] is blocklisted for host [%s].\n", buf, host.get()));
return true;
}
}
return false;
}
void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
addr_info_lock.AssertCurrentThreadOwns();
LOG(
("Adding address to blocklist for host [%s], host record [%p]."
"used trr=%d\n",
host.get(), this, mTRRSuccess));
++mUnusableCount;
char buf[kIPv6CStrBufSize];
if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
LOG(
("Successfully adding address [%s] to blocklist for host "
"[%s].\n",
buf, host.get()));
mUnusableItems.AppendElement(nsCString(buf));
}
}
void AddrHostRecord::ResetBlocklist() {
addr_info_lock.AssertCurrentThreadOwns();
LOG(("Resetting blocklist for host [%s], host record [%p].\n", host.get(),
this));
mUnusableItems.Clear();
}
size_t AddrHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
n += mallocSizeOf(addr.get());
n += mUnusableItems.ShallowSizeOfExcludingThis(mallocSizeOf);
for (size_t i = 0; i < mUnusableItems.Length(); i++) {
n += mUnusableItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
}
return n;
}
bool AddrHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
// don't use cached negative results for high priority queries.
if (negative && IsHighPriority(queryFlags)) {
return false;
}
if (CheckExpiration(now) == EXP_EXPIRED) {
return false;
}
if (negative) {
return true;
}
return addr_info || addr;
}
// Returns true if the entry can be removed, or false if it should be left.
// Sets ResolveAgain true for entries being resolved right now.
bool AddrHostRecord::RemoveOrRefresh(bool aTrrToo) {
// no need to flush TRRed names, they're not resolved "locally"
MutexAutoLock lock(addr_info_lock);
if (addr_info && !aTrrToo && addr_info->IsTRROrODoH()) {
return false;
}
if (LoadNative()) {
if (!onQueue()) {
// The request has been passed to the OS resolver. The resultant DNS
// record should be considered stale and not trusted; set a flag to
// ensure it is called again.
StoreResolveAgain(true);
}
// if onQueue is true, the host entry is already added to the cache
// but is still pending to get resolved: just leave it in hash.
return false;
}
// Already resolved; not in a pending state; remove from cache
return true;
}
void AddrHostRecord::ResolveComplete() {
if (LoadNativeUsed()) {
if (mNativeSuccess) {
uint32_t millis = static_cast<uint32_t>(mNativeDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_NATIVE_LOOKUP_TIME, millis);
}
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
mNativeSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osOK
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osFail);
}
if (mResolverType == DNSResolverType::ODoH) {
// XXX(kershaw): Consider adding the failed host name into a blocklist.
if (mTRRSuccess) {
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_ODOH_LOOKUP_TIME, millis);
}
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
Telemetry::Accumulate(Telemetry::ODOH_SKIP_REASON_ODOH_FIRST,
static_cast<uint32_t>(mTRRSkippedReason));
}
return;
}
if (mResolverType == DNSResolverType::TRR) {
if (mTRRSuccess) {
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
Telemetry::Accumulate(Telemetry::DNS_TRR_LOOKUP_TIME3,
TRRService::ProviderKey(), millis);
}
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
mTRRSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrOK
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrFail);
}
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_TRR_FIRST2,
TRRService::ProviderKey(),
static_cast<uint32_t>(mTRRSkippedReason));
if (!mTRRSuccess) {
Telemetry::Accumulate(
mNativeSuccess ? Telemetry::TRR_SKIP_REASON_NATIVE_SUCCESS
: Telemetry::TRR_SKIP_REASON_NATIVE_FAILED,
TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
}
}
if (mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
if (flags & nsIDNSService::RESOLVE_DISABLE_TRR) {
// TRR is disabled on request, which is a next-level back-off method.
Telemetry::Accumulate(Telemetry::DNS_TRR_DISABLED3,
TRRService::ProviderKey(), mNativeSuccess);
} else {
if (mTRRSuccess) {
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::TRR);
} else if (mNativeSuccess) {
if (mResolverType == DNSResolverType::TRR) {
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::NativeAfterTRR);
} else {
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::Native);
}
} else {
AccumulateCategoricalKeyed(
TRRService::ProviderKey(),
Telemetry::LABELS_DNS_TRR_FIRST4::BothFailed);
}
}
}
switch (mEffectiveTRRMode) {
case nsIRequest::TRR_DISABLED_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::nativeOnly);
break;
case nsIRequest::TRR_FIRST_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrFirst);
break;
case nsIRequest::TRR_ONLY_MODE:
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrOnly);
break;
case nsIRequest::TRR_DEFAULT_MODE:
MOZ_ASSERT_UNREACHABLE("We should not have a default value here");
break;
}
if (mResolverType == DNSResolverType::TRR && !mTRRSuccess && mNativeSuccess &&
gTRRService) {
gTRRService->AddToBlocklist(nsCString(host), originSuffix, pb, true);
}
}
AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(uint16_t aFlags) {
if (IsHighPriority(aFlags)) {
return AddrHostRecord::DNS_PRIORITY_HIGH;
}
if (IsMediumPriority(aFlags)) {
return AddrHostRecord::DNS_PRIORITY_MEDIUM;
}
return AddrHostRecord::DNS_PRIORITY_LOW;
}
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
: nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
bool TypeHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const {
if (CheckExpiration(now) == EXP_EXPIRED) {
return false;
}
if (negative) {
return true;
}
return !mResults.is<Nothing>();
}
bool TypeHostRecord::RefreshForNegativeResponse() const { return false; }
NS_IMETHODIMP TypeHostRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
// deep copy
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordTxt>()) {
return NS_ERROR_NOT_AVAILABLE;
}
aRecords = mResults.as<CopyableTArray<nsCString>>();
return NS_OK;
}
NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
// deep copy
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordTxt>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<CopyableTArray<nsCString>>();
for (uint32_t i = 0; i < results.Length(); i++) {
aRecords.Append(results[i]);
}
return NS_OK;
}
size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
return n;
}
uint32_t TypeHostRecord::GetType() {
MutexAutoLock lock(mResultsLock);
return mResults.match(
[](TypeRecordEmpty&) {
MOZ_ASSERT(false, "This should never be the case");
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
},
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
}
TypeRecordResultType TypeHostRecord::GetResults() {
MutexAutoLock lock(mResultsLock);
return mResults;
}
NS_IMETHODIMP
TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
for (const SVCB& r : results) {
RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
aRecords.AppendElement(rec);
}
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
nsISVCBRecord** aRecord) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
aNoHttp2, aNoHttp3, results, mAllRecordsExcluded);
if (!result) {
return NS_ERROR_NOT_AVAILABLE;
}
result.forget(aRecord);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetAllRecordsWithEchConfig(
bool aNoHttp2, bool aNoHttp3, bool* aAllRecordsHaveEchConfig,
bool* aAllRecordsInH3ExcludedList,
nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& records = mResults.as<TypeRecordHTTPSSVC>();
GetAllRecordsWithEchConfigInternal(aNoHttp2, aNoHttp3, records,
aAllRecordsHaveEchConfig,
aAllRecordsInH3ExcludedList, aResult);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetHasIPAddresses(bool* aResult) {
NS_ENSURE_ARG(aResult);
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& results = mResults.as<TypeRecordHTTPSSVC>();
*aResult = HasIPAddressesInternal(results);
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetAllRecordsExcluded(bool* aResult) {
NS_ENSURE_ARG(aResult);
MutexAutoLock lock(mResultsLock);
if (!mResults.is<TypeRecordHTTPSSVC>()) {
return NS_ERROR_NOT_AVAILABLE;
}
*aResult = mAllRecordsExcluded;
return NS_OK;
}
NS_IMETHODIMP
TypeHostRecord::GetTtl(uint32_t* aResult) {
NS_ENSURE_ARG(aResult);
*aResult = mTtl;
return NS_OK;
}
//----------------------------------------------------------------------------
static const char kPrefGetTtl[] = "network.dns.get-ttl";
static const char kPrefNativeIsLocalhost[] = "network.dns.native-is-localhost";
static const char kPrefThreadIdleTime[] =

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

@ -14,26 +14,21 @@
#include "mozilla/Mutex.h"
#include "nsISupportsImpl.h"
#include "nsIDNSListener.h"
#include "nsIDNSService.h"
#include "nsTArray.h"
#include "GetAddrInfo.h"
#include "mozilla/net/DNS.h"
#include "mozilla/net/DashboardTypes.h"
#include "mozilla/AtomicBitfields.h"
#include "mozilla/Atomics.h"
#include "mozilla/LinkedList.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h"
#include "nsHostRecord.h"
#include "nsRefPtrHashtable.h"
#include "nsIThreadPool.h"
#include "mozilla/net/NetworkConnectivityService.h"
#include "nsIDNSByTypeRecord.h"
#include "mozilla/net/DNSByTypeRecord.h"
#include "mozilla/Maybe.h"
#include "TRRSkippedReason.h"
class nsHostResolver;
class nsResolveHostCallback;
namespace mozilla {
namespace net {
class TRR;
@ -55,336 +50,6 @@ extern mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost;
(MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
struct nsHostKey {
const nsCString host;
const nsCString mTrrServer;
uint16_t type = 0;
uint16_t flags = 0;
uint16_t af = 0;
bool pb = false;
const nsCString originSuffix;
explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
uint16_t type, uint16_t flags, uint16_t af, bool pb,
const nsACString& originSuffix);
bool operator==(const nsHostKey& other) const;
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
PLDHashNumber Hash() const;
};
/**
* nsHostRecord - ref counted object type stored in host resolver cache.
*/
class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
public nsHostKey,
public nsISupports {
using TRRSkippedReason = mozilla::net::TRRSkippedReason;
public:
NS_DECL_THREADSAFE_ISUPPORTS
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return 0;
}
// Returns the TRR mode encoded by the flags
nsIRequest::TRRMode TRRMode();
// Records the first reason that caused TRR to be skipped or to fail.
void RecordReason(TRRSkippedReason reason) {
if (mTRRSkippedReason == TRRSkippedReason::TRR_UNSET) {
mTRRSkippedReason = reason;
}
}
protected:
friend class nsHostResolver;
friend class mozilla::net::TRR;
friend class mozilla::net::TRRQuery;
explicit nsHostRecord(const nsHostKey& key);
virtual ~nsHostRecord() = default;
// Mark hostrecord as not usable
void Invalidate();
enum ExpirationStatus {
EXP_VALID,
EXP_GRACE,
EXP_EXPIRED,
};
ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
// Convenience function for setting the timestamps above (mValidStart,
// mValidEnd, and mGraceStart). valid and grace are durations in seconds.
void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
unsigned int grace);
void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord);
// Checks if the record is usable (not expired and has a value)
bool HasUsableResult(const mozilla::TimeStamp& now,
uint16_t queryFlags = 0) const;
enum DnsPriority {
DNS_PRIORITY_LOW,
DNS_PRIORITY_MEDIUM,
DNS_PRIORITY_HIGH,
};
static DnsPriority GetPriority(uint16_t aFlags);
virtual void Cancel();
virtual bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const = 0;
virtual bool RefreshForNegativeResponse() const { return true; }
mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks;
bool IsAddrRecord() const {
return type == nsIDNSService::RESOLVE_TYPE_DEFAULT;
}
// When the record began being valid. Used mainly for bookkeeping.
mozilla::TimeStamp mValidStart;
// When the record is no longer valid (it's time of expiration)
mozilla::TimeStamp mValidEnd;
// When the record enters its grace period. This must be before mValidEnd.
// If a record is in its grace period (and not expired), it will be used
// but a request to refresh it will be made.
mozilla::TimeStamp mGraceStart;
uint32_t mTtl = 0;
// The computed TRR mode that is actually used by the request.
// It is set in nsHostResolver::NameLookup and is based on the mode of the
// default resolver and the TRRMode encoded in the flags.
// The mode into account if the TRR service is disabled,
// parental controls are on, domain matches exclusion list, etc.
nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
TRRSkippedReason mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
TRRSkippedReason mTRRAFailReason = TRRSkippedReason::TRR_UNSET;
TRRSkippedReason mTRRAAAAFailReason = TRRSkippedReason::TRR_UNSET;
mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
// counter of outstanding resolving calls
mozilla::Atomic<int32_t> mResolving{0};
// True if this record is a cache of a failed lookup. Negative cache
// entries are valid just like any other (though never for more than 60
// seconds), but a use of that negative entry forces an asynchronous refresh.
bool negative = false;
// Explicitly expired
bool mDoomed = false;
};
// b020e996-f6ab-45e5-9bf5-1da71dd0053a
#define ADDRHOSTRECORD_IID \
{ \
0xb020e996, 0xf6ab, 0x45e5, { \
0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \
} \
}
class AddrHostRecord final : public nsHostRecord {
using Mutex = mozilla::Mutex;
using DNSResolverType = mozilla::net::DNSResolverType;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
NS_DECL_ISUPPORTS_INHERITED
/* a fully resolved host record has either a non-null |addr_info| or |addr|
* field. if |addr_info| is null, it implies that the |host| is an IP
* address literal. in which case, |addr| contains the parsed address.
* otherwise, if |addr_info| is non-null, then it contains one or many
* IP addresses corresponding to the given host name. if both |addr_info|
* and |addr| are null, then the given host has not yet been fully resolved.
* |af| is the address family of the record we are querying for.
*/
/* the lock protects |addr_info| and |addr_info_gencnt| because they
* are mutable and accessed by the resolver worker thread and the
* nsDNSService2 class. |addr| doesn't change after it has been
* assigned a value. only the resolver worker thread modifies
* nsHostRecord (and only in nsHostResolver::CompleteLookup);
* the other threads just read it. therefore the resolver worker
* thread doesn't need to lock when reading |addr_info|.
*/
Mutex addr_info_lock{"AddrHostRecord.addr_info_lock"};
// generation count of |addr_info|
int addr_info_gencnt = 0;
RefPtr<mozilla::net::AddrInfo> addr_info;
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
// hold addr_info_lock when calling the blocklist functions
bool Blocklisted(const mozilla::net::NetAddr* query);
void ResetBlocklist();
void ReportUnusable(const mozilla::net::NetAddr* aAddress);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; }
private:
friend class nsHostResolver;
friend class mozilla::net::TRR;
friend class mozilla::net::TRRQuery;
explicit AddrHostRecord(const nsHostKey& key);
~AddrHostRecord();
// Checks if the record is usable (not expired and has a value)
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const override;
bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved
// as needed to resolve again.
void ResolveComplete();
enum DnsPriority {
DNS_PRIORITY_LOW,
DNS_PRIORITY_MEDIUM,
DNS_PRIORITY_HIGH,
};
static DnsPriority GetPriority(uint16_t aFlags);
// true if pending and on the queue (not yet given to getaddrinfo())
bool onQueue() { return LoadNative() && isInList(); }
// When the lookups of this record started and their durations
mozilla::TimeStamp mTrrStart;
mozilla::TimeStamp mNativeStart;
mozilla::TimeDuration mTrrDuration;
mozilla::TimeDuration mNativeDuration;
// TRR or ODoH was used on this record
mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
uint8_t mTRRSuccess = 0; // number of successful TRR responses
uint8_t mNativeSuccess = 0; // number of native lookup responses
// clang-format off
MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
// true if this record is being resolved "natively", which means that
// it is either on the pending queue or owned by one of the worker threads.
(uint16_t, Native, 1),
(uint16_t, NativeUsed, 1),
// true if off queue and contributing to mActiveAnyThreadCount
(uint16_t, UsingAnyThread, 1),
(uint16_t, GetTtl, 1),
(uint16_t, ResolveAgain, 1)
))
// clang-format on
// The number of times ReportUnusable() has been called in the record's
// lifetime.
uint32_t mUnusableCount = 0;
// a list of addresses associated with this record that have been reported
// as unusable. the list is kept as a set of strings to make it independent
// of gencnt.
nsTArray<nsCString> mUnusableItems;
};
NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
// 77b786a7-04be-44f2-987c-ab8aa96676e0
#define TYPEHOSTRECORD_IID \
{ \
0x77b786a7, 0x04be, 0x44f2, { \
0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \
} \
}
class TypeHostRecord final : public nsHostRecord,
public nsIDNSTXTRecord,
public nsIDNSHTTPSSVCRecord,
public mozilla::net::DNSHTTPSSVCRecordBase {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDNSTXTRECORD
NS_DECL_NSIDNSHTTPSSVCRECORD
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
uint32_t GetType();
mozilla::net::TypeRecordResultType GetResults();
private:
friend class nsHostResolver;
friend class mozilla::net::TRRQuery;
explicit TypeHostRecord(const nsHostKey& key);
~TypeHostRecord();
// Checks if the record is usable (not expired and has a value)
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
uint16_t queryFlags) const override;
bool RefreshForNegativeResponse() const override;
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
mozilla::Mutex mResultsLock{"TypeHostRecord.mResultsLock"};
// When the lookups of this record started (for telemetry).
mozilla::TimeStamp mStart;
bool mAllRecordsExcluded = false;
};
NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID)
/**
* This class is used to notify listeners when a ResolveHost operation is
* complete. Classes that derive it must implement threadsafe nsISupports
* to be able to use RefPtr with this class.
*/
class nsResolveHostCallback
: public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>,
public nsISupports {
public:
/**
* OnResolveHostComplete
*
* this function is called to complete a host lookup initiated by
* nsHostResolver::ResolveHost. it may be invoked recursively from
* ResolveHost or on an unspecified background thread.
*
* NOTE: it is the responsibility of the implementor of this method
* to handle the callback in a thread safe manner.
*
* @param resolver
* nsHostResolver object associated with this result
* @param record
* the host record containing the results of the lookup
* @param status
* if successful, |record| contains non-null results
*/
virtual void OnResolveHostComplete(nsHostResolver* resolver,
nsHostRecord* record, nsresult status) = 0;
/**
* EqualsAsyncListener
*
* Determines if the listener argument matches the listener member var.
* For subclasses not implementing a member listener, should return false.
* For subclasses having a member listener, the function should check if
* they are the same. Used for cases where a pointer to an object
* implementing nsResolveHostCallback is unknown, but a pointer to
* the original listener is known.
*
* @param aListener
* nsIDNSListener object associated with the original request
*/
virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
protected:
virtual ~nsResolveHostCallback() = default;
};
class AHostResolver {
public:
AHostResolver() = default;
@ -506,8 +171,8 @@ class nsHostResolver : public nsISupports, public AHostResolver {
enum {
RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
RES_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
RES_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
RES_PRIORITY_MEDIUM = nsHostRecord::DNS_PRIORITY_MEDIUM,
RES_PRIORITY_LOW = nsHostRecord::DNS_PRIORITY_LOW,
RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
// RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,

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

@ -214,6 +214,7 @@ avoid-blacklist-and-whitelist:
- netwerk/base/nsIOService.h
- netwerk/base/nsURLHelper.cpp
- netwerk/cookie/CookieCommons.h
- netwerk/dns/nsHostRecord.cpp
- netwerk/dns/nsHostResolver.cpp
- netwerk/dns/nsIDNService.cpp
- netwerk/dns/nsIDNService.h