зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1691408 - Record confirmation event telemetry r=nhnt11,dragana,necko-reviewers
- Adds new TRR* argument to CompleteLookup so we can extract the channel status from the TRR request. - Record event whenever the confirmation context changes - NetworkID is recorded whenever we start a new confirmation attempt - Captive portal status is updated based on observer notifications - We keep a buffer of the last 32 confirmation results. Differential Revision: https://phabricator.services.mozilla.com/D105173
This commit is contained in:
Родитель
e5e0b8d7a7
Коммит
efa654d3d5
|
@ -633,7 +633,8 @@ void TRR::SaveAdditionalRecords(
|
|||
addrRec->mTrrStart = TimeStamp::Now();
|
||||
LOG(("Completing lookup for additional: %s", nsCString(iter.Key()).get()));
|
||||
(void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB,
|
||||
mOriginSuffix, AddrHostRecord::TRR_OK);
|
||||
mOriginSuffix, AddrHostRecord::TRR_OK,
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -672,7 +673,7 @@ void TRR::StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord) {
|
|||
addrRec->mTrrStart = TimeStamp::Now();
|
||||
|
||||
(void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB, mOriginSuffix,
|
||||
AddrHostRecord::TRR_OK);
|
||||
AddrHostRecord::TRR_OK, this);
|
||||
}
|
||||
|
||||
nsresult TRR::ReturnData(nsIChannel* aChannel) {
|
||||
|
@ -705,7 +706,7 @@ nsresult TRR::ReturnData(nsIChannel* aChannel) {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
(void)mHostResolver->CompleteLookup(mRec, NS_OK, ai, mPB, mOriginSuffix,
|
||||
mTRRSkippedReason);
|
||||
mTRRSkippedReason, this);
|
||||
mHostResolver = nullptr;
|
||||
mRec = nullptr;
|
||||
} else {
|
||||
|
@ -732,7 +733,7 @@ nsresult TRR::FailData(nsresult error) {
|
|||
RefPtr<AddrInfo> ai = new AddrInfo(mHost, mType, std::move(noAddresses));
|
||||
|
||||
(void)mHostResolver->CompleteLookup(mRec, error, ai, mPB, mOriginSuffix,
|
||||
mTRRSkippedReason);
|
||||
mTRRSkippedReason, this);
|
||||
}
|
||||
|
||||
mHostResolver = nullptr;
|
||||
|
@ -862,6 +863,8 @@ TRR::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
channel.swap(mChannel);
|
||||
|
||||
mChannelStatus = aStatusCode;
|
||||
|
||||
{
|
||||
// Cancel the timer since we don't need it anymore.
|
||||
nsCOMPtr<nsITimer> timer;
|
||||
|
|
|
@ -103,6 +103,8 @@ class TRR : public Runnable,
|
|||
|
||||
void SetTimeout(uint32_t aTimeoutMs) { mTimeoutMs = aTimeoutMs; }
|
||||
|
||||
nsresult ChannelStatus() { return mChannelStatus; }
|
||||
|
||||
protected:
|
||||
virtual ~TRR() = default;
|
||||
virtual DNSPacket* GetOrCreateDNSPacket();
|
||||
|
@ -142,6 +144,7 @@ class TRR : public Runnable,
|
|||
bool mFailed = false;
|
||||
bool mPB;
|
||||
DOHresp mDNS;
|
||||
nsresult mChannelStatus = NS_OK;
|
||||
|
||||
// The request timeout in milliseconds. If 0 we will use the default timeout
|
||||
// we get from the prefs.
|
||||
|
|
|
@ -162,10 +162,11 @@ nsresult TRRQuery::DispatchLookup(TRR* pushedTRR, bool aUseODoH) {
|
|||
|
||||
AHostResolver::LookupStatus TRRQuery::CompleteLookup(
|
||||
nsHostRecord* rec, nsresult status, AddrInfo* aNewRRSet, bool pb,
|
||||
const nsACString& aOriginsuffix, nsHostRecord::TRRSkippedReason aReason) {
|
||||
const nsACString& aOriginsuffix, nsHostRecord::TRRSkippedReason aReason,
|
||||
TRR* aTRRRequest) {
|
||||
if (rec != mRecord) {
|
||||
return mHostResolver->CompleteLookup(rec, status, aNewRRSet, pb,
|
||||
aOriginsuffix, aReason);
|
||||
aOriginsuffix, aReason, aTRRRequest);
|
||||
}
|
||||
|
||||
RefPtr<AddrInfo> newRRSet(aNewRRSet);
|
||||
|
@ -270,7 +271,7 @@ AHostResolver::LookupStatus TRRQuery::CompleteLookup(
|
|||
}
|
||||
|
||||
return mHostResolver->CompleteLookup(rec, status, newRRSet, pb, aOriginsuffix,
|
||||
aReason);
|
||||
aReason, aTRRRequest);
|
||||
}
|
||||
|
||||
AHostResolver::LookupStatus TRRQuery::CompleteLookupByType(
|
||||
|
|
|
@ -31,10 +31,11 @@ class TRRQuery : public AHostResolver {
|
|||
AddrHostRecord::TRRSkippedReason mTRRAAAAFailReason =
|
||||
AddrHostRecord::TRR_UNSET;
|
||||
|
||||
virtual LookupStatus CompleteLookup(
|
||||
nsHostRecord*, nsresult, mozilla::net::AddrInfo*, bool pb,
|
||||
const nsACString& aOriginsuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason) override;
|
||||
virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult,
|
||||
mozilla::net::AddrInfo*, bool pb,
|
||||
const nsACString& aOriginsuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason,
|
||||
TRR* aTRRRequest) override;
|
||||
virtual LookupStatus CompleteLookupByType(
|
||||
nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool pb) override;
|
||||
|
|
|
@ -56,10 +56,9 @@ TRRService::TRRService()
|
|||
mConfirmationNS("example.com"_ns),
|
||||
mCaptiveIsPassed(false),
|
||||
mTRRBLStorage("DataMutex::TRRBlocklist"),
|
||||
mConfirmationState(CONFIRM_INIT),
|
||||
mRetryConfirmInterval(125),
|
||||
mTRRFailures(0),
|
||||
mParentalControlEnabled(false) {
|
||||
mConfirmation.mState = CONFIRM_INIT;
|
||||
mConfirmation.mTRRFailures = 0;
|
||||
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
||||
}
|
||||
|
||||
|
@ -171,11 +170,10 @@ nsresult TRRService::Init() {
|
|||
|
||||
mParentalControlEnabled = GetParentalControlEnabledInternal();
|
||||
|
||||
nsCOMPtr<nsINetworkLinkService> nls =
|
||||
do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID);
|
||||
if (nls) {
|
||||
mLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID);
|
||||
if (mLinkService) {
|
||||
nsTArray<nsCString> suffixList;
|
||||
nls->GetDnsSuffixList(suffixList);
|
||||
mLinkService->GetDnsSuffixList(suffixList);
|
||||
RebuildSuffixList(std::move(suffixList));
|
||||
}
|
||||
|
||||
|
@ -203,6 +201,8 @@ nsresult TRRService::Init() {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Telemetry::SetEventRecordingEnabled("network.dns"_ns, true);
|
||||
|
||||
LOG(("Initialized TRRService\n"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -236,27 +236,27 @@ bool TRRService::Enabled(nsIRequest::TRRMode aRequestMode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mConfirmationState == CONFIRM_INIT &&
|
||||
if (mConfirmation.mState == CONFIRM_INIT &&
|
||||
(!StaticPrefs::network_trr_wait_for_portal() || mCaptiveIsPassed ||
|
||||
(mMode == nsIDNSService::MODE_TRRONLY ||
|
||||
aRequestMode == nsIRequest::TRR_ONLY_MODE))) {
|
||||
LOG(("TRRService::Enabled => CONFIRM_TRYING\n"));
|
||||
mConfirmationState = CONFIRM_TRYING;
|
||||
mConfirmation.mState = CONFIRM_TRYING;
|
||||
}
|
||||
|
||||
if (mConfirmationState == CONFIRM_TRYING) {
|
||||
if (mConfirmation.mState == CONFIRM_TRYING) {
|
||||
LOG(("TRRService::Enabled MaybeConfirm()\n"));
|
||||
MaybeConfirm();
|
||||
MaybeConfirm("context-init");
|
||||
if (mMode == nsIDNSService::MODE_TRRONLY) {
|
||||
MOZ_ASSERT(mConfirmationState == CONFIRM_OK,
|
||||
MOZ_ASSERT(mConfirmation.mState == CONFIRM_OK,
|
||||
"Global mode is trr-only, but confirmation failed?");
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("TRRService::Enabled mConfirmationState=%d mCaptiveIsPassed=%d\n",
|
||||
(int)mConfirmationState, (int)mCaptiveIsPassed));
|
||||
LOG(("TRRService::Enabled mConfirmation.mState=%d mCaptiveIsPassed=%d\n",
|
||||
(int)mConfirmation.mState, (int)mCaptiveIsPassed));
|
||||
|
||||
if (mConfirmationState == CONFIRM_OK) {
|
||||
if (mConfirmation.mState == CONFIRM_OK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ bool TRRService::Enabled(nsIRequest::TRRMode aRequestMode) {
|
|||
if ((aRequestMode == nsIRequest::TRR_DEFAULT_MODE &&
|
||||
mMode == nsIDNSService::MODE_TRRFIRST) ||
|
||||
aRequestMode == nsIRequest::TRR_FIRST_MODE) {
|
||||
return mConfirmationState != CONFIRM_FAILED;
|
||||
return mConfirmation.mState != CONFIRM_FAILED;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -352,12 +352,12 @@ nsresult TRRService::ReadPrefs(const char* name) {
|
|||
nsAutoCString old(mConfirmationNS);
|
||||
Preferences::GetCString(TRR_PREF("confirmationNS"), mConfirmationNS);
|
||||
if (name && !old.IsEmpty() && !mConfirmationNS.Equals(old) &&
|
||||
(mConfirmationState > CONFIRM_TRYING) &&
|
||||
(mConfirmation.mState > CONFIRM_TRYING) &&
|
||||
(mMode == nsIDNSService::MODE_TRRFIRST ||
|
||||
mMode == nsIDNSService::MODE_TRRONLY)) {
|
||||
LOG(("TRR::ReadPrefs: restart confirmationNS state\n"));
|
||||
mConfirmationState = CONFIRM_TRYING;
|
||||
MaybeConfirm_locked();
|
||||
mConfirmation.mState = CONFIRM_TRYING;
|
||||
MaybeConfirm_locked("pref-change");
|
||||
}
|
||||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("bootstrapAddress"))) {
|
||||
|
@ -572,18 +572,19 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
||||
ReadPrefs(NS_ConvertUTF16toUTF8(aData).get());
|
||||
|
||||
mConfirmation.RecordEvent("pref-change");
|
||||
MutexAutoLock lock(mLock);
|
||||
if (((mConfirmationState == CONFIRM_INIT) && !mBootstrapAddr.IsEmpty() &&
|
||||
if (((mConfirmation.mState == CONFIRM_INIT) && !mBootstrapAddr.IsEmpty() &&
|
||||
(mMode == nsIDNSService::MODE_TRRONLY)) ||
|
||||
(mConfirmationState == CONFIRM_FAILED)) {
|
||||
mConfirmationState = CONFIRM_TRYING;
|
||||
MaybeConfirm_locked();
|
||||
(mConfirmation.mState == CONFIRM_FAILED)) {
|
||||
mConfirmation.mState = CONFIRM_TRYING;
|
||||
MaybeConfirm_locked("pref-change");
|
||||
}
|
||||
|
||||
} else if (!strcmp(aTopic, kOpenCaptivePortalLoginEvent)) {
|
||||
// We are in a captive portal
|
||||
LOG(("TRRservice in captive portal\n"));
|
||||
mCaptiveIsPassed = false;
|
||||
mConfirmation.mCaptivePortalStatus = nsICaptivePortalService::LOCKED_PORTAL;
|
||||
} else if (!strcmp(aTopic, NS_CAPTIVE_PORTAL_CONNECTIVITY)) {
|
||||
nsAutoCString data = NS_ConvertUTF16toUTF8(aData);
|
||||
LOG(("TRRservice captive portal was %s\n", data.get()));
|
||||
|
@ -592,19 +593,23 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
// unless the service is in a TRR=enabled mode.
|
||||
if (mMode == nsIDNSService::MODE_TRRFIRST ||
|
||||
mMode == nsIDNSService::MODE_TRRONLY) {
|
||||
if (mRetryConfirmTimer) {
|
||||
mRetryConfirmTimer->Cancel();
|
||||
mRetryConfirmTimer = nullptr;
|
||||
if (mConfirmation.mTimer) {
|
||||
mConfirmation.mTimer->Cancel();
|
||||
mConfirmation.mTimer = nullptr;
|
||||
}
|
||||
mRetryConfirmInterval = StaticPrefs::network_trr_retry_timeout_ms();
|
||||
if (mConfirmationState != CONFIRM_OK) {
|
||||
mConfirmationState = CONFIRM_TRYING;
|
||||
MaybeConfirm();
|
||||
mConfirmation.mRetryInterval =
|
||||
StaticPrefs::network_trr_retry_timeout_ms();
|
||||
if (mConfirmation.mState != CONFIRM_OK) {
|
||||
mConfirmation.mState = CONFIRM_TRYING;
|
||||
MaybeConfirm("cp-connectivity");
|
||||
}
|
||||
}
|
||||
|
||||
mCaptiveIsPassed = true;
|
||||
|
||||
nsCOMPtr<nsICaptivePortalService> cps = do_QueryInterface(aSubject);
|
||||
if (cps) {
|
||||
cps->GetState(&mConfirmation.mCaptivePortalStatus);
|
||||
}
|
||||
} else if (!strcmp(aTopic, kClearPrivateData) || !strcmp(aTopic, kPurge)) {
|
||||
// flush the TRR blocklist
|
||||
auto bl = mTRRBLStorage.Lock();
|
||||
|
@ -623,12 +628,23 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, NS_NETWORK_LINK_TOPIC) && mURISetByDetection) {
|
||||
// If the URI was set via SetDetectedTrrURI we need to restore it to the
|
||||
// default pref when a network link change occurs.
|
||||
CheckURIPrefs();
|
||||
if (!strcmp(aTopic, NS_NETWORK_LINK_TOPIC)) {
|
||||
if (NS_ConvertUTF16toUTF8(aData).EqualsLiteral(
|
||||
NS_NETWORK_LINK_DATA_DOWN)) {
|
||||
mConfirmation.RecordEvent("network-change");
|
||||
}
|
||||
if (mURISetByDetection) {
|
||||
// If the URI was set via SetDetectedTrrURI we need to restore it to the
|
||||
// default pref when a network link change occurs.
|
||||
CheckURIPrefs();
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(aTopic, "xpcom-shutdown-threads")) {
|
||||
// If a confirmation is still in progress we record the event.
|
||||
// Since there should be no more confirmations after this, the shutdown
|
||||
// reason would not really be recorded in telemetry.
|
||||
mConfirmation.RecordEvent("shutdown");
|
||||
|
||||
if (sTRRBackgroundThread) {
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
{
|
||||
|
@ -656,32 +672,48 @@ void TRRService::RebuildSuffixList(nsTArray<nsCString>&& aSuffixList) {
|
|||
}
|
||||
}
|
||||
|
||||
void TRRService::MaybeConfirm() {
|
||||
void TRRService::MaybeConfirm(const char* aReason) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MaybeConfirm_locked();
|
||||
MaybeConfirm_locked(aReason);
|
||||
}
|
||||
|
||||
void TRRService::MaybeConfirm_locked() {
|
||||
void TRRService::MaybeConfirm_locked(const char* aReason) {
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
if (mMode == nsIDNSService::MODE_TRROFF || mConfirmer ||
|
||||
mConfirmationState != CONFIRM_TRYING) {
|
||||
|
||||
if (mMode == nsIDNSService::MODE_TRROFF || mConfirmation.mTask ||
|
||||
mConfirmation.mState != CONFIRM_TRYING) {
|
||||
LOG(
|
||||
("TRRService:MaybeConfirm mode=%d, mConfirmer=%p "
|
||||
"mConfirmationState=%d\n",
|
||||
(int)mMode, (void*)mConfirmer, (int)mConfirmationState));
|
||||
("TRRService:MaybeConfirm mode=%d, mConfirmation.mTask=%p "
|
||||
"mConfirmation.mState=%d\n",
|
||||
(int)mMode, (void*)mConfirmation.mTask, (int)mConfirmation.mState));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mConfirmationNS.Equals("skip") || mMode == nsIDNSService::MODE_TRRONLY) {
|
||||
LOG(("TRRService starting confirmation test %s SKIPPED\n",
|
||||
mPrivateURI.get()));
|
||||
mConfirmationState = CONFIRM_OK;
|
||||
mConfirmation.mState = CONFIRM_OK;
|
||||
} else {
|
||||
LOG(("TRRService starting confirmation test %s %s\n", mPrivateURI.get(),
|
||||
mConfirmationNS.get()));
|
||||
mConfirmer = new TRR(this, mConfirmationNS, TRRTYPE_NS, ""_ns, false);
|
||||
mConfirmer->SetTimeout(StaticPrefs::network_trr_confirmation_timeout_ms());
|
||||
DispatchTRRRequestInternal(mConfirmer, false);
|
||||
|
||||
mConfirmation.mTask =
|
||||
new TRR(this, mConfirmationNS, TRRTYPE_NS, ""_ns, false);
|
||||
mConfirmation.mTask->SetTimeout(
|
||||
StaticPrefs::network_trr_confirmation_timeout_ms());
|
||||
|
||||
if (mLinkService) {
|
||||
mLinkService->GetNetworkID(mConfirmation.mNetworkId);
|
||||
}
|
||||
|
||||
if (mConfirmation.mFirstRequestTime.IsNull()) {
|
||||
mConfirmation.mFirstRequestTime = TimeStamp::Now();
|
||||
}
|
||||
if (mConfirmation.mTrigger.IsEmpty()) {
|
||||
mConfirmation.mTrigger.Assign(aReason);
|
||||
}
|
||||
|
||||
DispatchTRRRequestInternal(mConfirmation.mTask, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,12 +898,12 @@ void TRRService::AddToBlocklist(const nsACString& aHost,
|
|||
|
||||
NS_IMETHODIMP
|
||||
TRRService::Notify(nsITimer* aTimer) {
|
||||
if (aTimer == mRetryConfirmTimer) {
|
||||
mRetryConfirmTimer = nullptr;
|
||||
if (mConfirmationState == CONFIRM_FAILED) {
|
||||
if (aTimer == mConfirmation.mTimer) {
|
||||
mConfirmation.mTimer = nullptr;
|
||||
if (mConfirmation.mState == CONFIRM_FAILED) {
|
||||
LOG(("TRRService retry NS of %s\n", mConfirmationNS.get()));
|
||||
mConfirmationState = CONFIRM_TRYING;
|
||||
MaybeConfirm();
|
||||
mConfirmation.mState = CONFIRM_TRYING;
|
||||
MaybeConfirm("retry");
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH("Unknown timer");
|
||||
|
@ -892,25 +924,129 @@ void TRRService::TRRIsOkay(enum TrrOkay aReason) {
|
|||
? Telemetry::LABELS_DNS_TRR_SUCCESS2::Timeout
|
||||
: Telemetry::LABELS_DNS_TRR_SUCCESS2::Bad));
|
||||
if (aReason == OKAY_NORMAL) {
|
||||
mTRRFailures = 0;
|
||||
mConfirmation.mTRRFailures = 0;
|
||||
} else if ((mMode == nsIDNSService::MODE_TRRFIRST) &&
|
||||
(mConfirmationState == CONFIRM_OK)) {
|
||||
(mConfirmation.mState == CONFIRM_OK)) {
|
||||
// only count failures while in OK state
|
||||
uint32_t fails = ++mTRRFailures;
|
||||
uint32_t fails = ++mConfirmation.mTRRFailures;
|
||||
if (fails >= StaticPrefs::network_trr_max_fails()) {
|
||||
LOG(("TRRService goes FAILED after %u failures in a row\n", fails));
|
||||
mConfirmationState = CONFIRM_FAILED;
|
||||
mConfirmation.mState = CONFIRM_FAILED;
|
||||
mConfirmation.mTrigger.Assign("failed-lookups");
|
||||
// Fire off a timer and start re-trying the NS domain again
|
||||
NS_NewTimerWithCallback(getter_AddRefs(mRetryConfirmTimer), this,
|
||||
mRetryConfirmInterval, nsITimer::TYPE_ONE_SHOT);
|
||||
mTRRFailures = 0; // clear it again
|
||||
NS_NewTimerWithCallback(getter_AddRefs(mConfirmation.mTimer), this,
|
||||
mConfirmation.mRetryInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mConfirmation.mTRRFailures = 0; // clear it again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TRRService::ConfirmationContext::RecordEvent(const char* aReason) {
|
||||
// Reset the confirmation context attributes
|
||||
// Only resets the attributes that we keep for telemetry purposes.
|
||||
auto reset = [&]() {
|
||||
mAttemptCount = 0;
|
||||
mNetworkId.Truncate();
|
||||
mFirstRequestTime = TimeStamp();
|
||||
mContextChangeReason.Assign(aReason);
|
||||
mTrigger.Truncate();
|
||||
|
||||
mRetryInterval = StaticPrefs::network_trr_retry_timeout_ms();
|
||||
};
|
||||
|
||||
if (mAttemptCount == 0) {
|
||||
// XXX: resetting everything might not be the best thing here, even if the
|
||||
// context changes, because there might still be a confirmation pending.
|
||||
// But cancelling and retrying that confirmation might just make the whole
|
||||
// confirmation longer for no reason.
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::EventID eventType =
|
||||
Telemetry::EventID::NetworkDns_Trrconfirmation_Context;
|
||||
|
||||
nsAutoCString results;
|
||||
static_assert(RESULTS_SIZE < 64);
|
||||
|
||||
// mResults is a circular buffer ending at mAttemptCount
|
||||
if (mAttemptCount <= RESULTS_SIZE) {
|
||||
// We have fewer attempts than the size of the buffer, so all of the
|
||||
// results are in the buffer.
|
||||
results.Append(nsDependentCSubstring(mResults, mAttemptCount));
|
||||
} else {
|
||||
// More attempts than the buffer size.
|
||||
// That means past RESULTS_SIZE attempts in order are
|
||||
// [posInResults .. end-of-buffer) + [start-of-buffer .. posInResults)
|
||||
uint32_t posInResults = mAttemptCount % RESULTS_SIZE;
|
||||
|
||||
results.Append(nsDependentCSubstring(mResults + posInResults,
|
||||
RESULTS_SIZE - posInResults));
|
||||
results.Append(nsDependentCSubstring(mResults, posInResults));
|
||||
}
|
||||
|
||||
auto extra = Some<nsTArray<mozilla::Telemetry::EventExtraEntry>>({
|
||||
Telemetry::EventExtraEntry{"trigger"_ns, mTrigger},
|
||||
Telemetry::EventExtraEntry{"contextReason"_ns, mContextChangeReason},
|
||||
Telemetry::EventExtraEntry{"attemptCount"_ns,
|
||||
nsPrintfCString("%u", mAttemptCount)},
|
||||
Telemetry::EventExtraEntry{"results"_ns, results},
|
||||
Telemetry::EventExtraEntry{
|
||||
"time"_ns,
|
||||
nsPrintfCString(
|
||||
"%f",
|
||||
!mFirstRequestTime.IsNull()
|
||||
? (TimeStamp::Now() - mFirstRequestTime).ToMilliseconds()
|
||||
: 0.0)},
|
||||
Telemetry::EventExtraEntry{"networkID"_ns, mNetworkId},
|
||||
Telemetry::EventExtraEntry{"captivePortal"_ns,
|
||||
nsPrintfCString("%i", mCaptivePortalStatus)},
|
||||
});
|
||||
|
||||
ConfirmationState state = mState;
|
||||
Telemetry::RecordEvent(eventType, mozilla::Some(nsPrintfCString("%u", state)),
|
||||
extra);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void TRRService::ConfirmationContext::RequestCompleted(
|
||||
nsresult aLookupStatus, nsresult aChannelStatus) {
|
||||
auto statusToChar = [aLookupStatus, aChannelStatus]() -> char {
|
||||
if (aChannelStatus == NS_OK) {
|
||||
// Return + if confirmation was OK, or - if confirmation failed
|
||||
return aLookupStatus == NS_OK ? '+' : '-';
|
||||
}
|
||||
|
||||
switch (aChannelStatus) {
|
||||
case NS_ERROR_NET_TIMEOUT_EXTERNAL:
|
||||
// TRR timeout expired
|
||||
return 't';
|
||||
case NS_ERROR_UNKNOWN_HOST:
|
||||
// TRRServiceChannel failed to due to unresolved host
|
||||
return 'd';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// The error is a network error
|
||||
if (NS_ERROR_GET_MODULE(aChannelStatus) == NS_ERROR_MODULE_NETWORK) {
|
||||
return 'n';
|
||||
}
|
||||
|
||||
// Some other kind of failure.
|
||||
return '?';
|
||||
};
|
||||
|
||||
mResults[mAttemptCount % RESULTS_SIZE] = statusToChar();
|
||||
mAttemptCount++;
|
||||
}
|
||||
|
||||
AHostResolver::LookupStatus TRRService::CompleteLookup(
|
||||
nsHostRecord* rec, nsresult status, AddrInfo* aNewRRSet, bool pb,
|
||||
const nsACString& aOriginSuffix, nsHostRecord::TRRSkippedReason aReason) {
|
||||
const nsACString& aOriginSuffix, nsHostRecord::TRRSkippedReason aReason,
|
||||
TRR* aTRRRequest) {
|
||||
// this is an NS check for the TRR blocklist or confirmationNS check
|
||||
|
||||
MOZ_ASSERT_IF(XRE_IsParentProcess(), NS_IsMainThread() || IsOnTRRThread());
|
||||
|
@ -923,35 +1059,44 @@ AHostResolver::LookupStatus TRRService::CompleteLookup(
|
|||
#ifdef DEBUG
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(!mConfirmer || (mConfirmationState == CONFIRM_TRYING));
|
||||
MOZ_ASSERT(!mConfirmation.mTask ||
|
||||
(mConfirmation.mState == CONFIRM_TRYING));
|
||||
}
|
||||
#endif
|
||||
if (mConfirmationState == CONFIRM_TRYING) {
|
||||
if (mConfirmation.mState == CONFIRM_TRYING) {
|
||||
mConfirmation.RequestCompleted(status, aTRRRequest->ChannelStatus());
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(mConfirmer);
|
||||
mConfirmationState = NS_SUCCEEDED(status) ? CONFIRM_OK : CONFIRM_FAILED;
|
||||
MOZ_ASSERT(mConfirmation.mTask);
|
||||
mConfirmation.mState = NS_SUCCEEDED(status) ? CONFIRM_OK : CONFIRM_FAILED;
|
||||
LOG(("TRRService finishing confirmation test %s %d %X\n",
|
||||
mPrivateURI.get(), (int)mConfirmationState, (unsigned int)status));
|
||||
mConfirmer = nullptr;
|
||||
|
||||
if (mConfirmationState == CONFIRM_OK) {
|
||||
// A fresh confirmation means previous blocked entries might not
|
||||
// be valid anymore.
|
||||
auto bl = mTRRBLStorage.Lock();
|
||||
bl->Clear();
|
||||
}
|
||||
mPrivateURI.get(), (int)mConfirmation.mState, (unsigned int)status));
|
||||
mConfirmation.mTask = nullptr;
|
||||
}
|
||||
if (mConfirmationState == CONFIRM_FAILED) {
|
||||
// retry failed NS confirmation
|
||||
NS_NewTimerWithCallback(getter_AddRefs(mRetryConfirmTimer), this,
|
||||
mRetryConfirmInterval, nsITimer::TYPE_ONE_SHOT);
|
||||
if (mRetryConfirmInterval < 64000) {
|
||||
// double the interval up to this point
|
||||
mRetryConfirmInterval *= 2;
|
||||
}
|
||||
|
||||
if (mConfirmation.mState == CONFIRM_OK) {
|
||||
mConfirmation.mRetryInterval =
|
||||
StaticPrefs::network_trr_retry_timeout_ms();
|
||||
|
||||
// Record event and start new confirmation context
|
||||
mConfirmation.RecordEvent("success");
|
||||
|
||||
// A fresh confirmation means previous blocked entries might not
|
||||
// be valid anymore.
|
||||
auto bl = mTRRBLStorage.Lock();
|
||||
bl->Clear();
|
||||
} else {
|
||||
mRetryConfirmInterval = StaticPrefs::network_trr_retry_timeout_ms();
|
||||
MOZ_ASSERT(mConfirmation.mState == CONFIRM_FAILED);
|
||||
|
||||
// retry failed NS confirmation
|
||||
NS_NewTimerWithCallback(getter_AddRefs(mConfirmation.mTimer), this,
|
||||
mConfirmation.mRetryInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
if (mConfirmation.mRetryInterval < 64000) {
|
||||
// double the interval up to this point
|
||||
mConfirmation.mRetryInterval *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMode != nsIDNSService::MODE_TRRONLY) {
|
||||
|
@ -959,7 +1104,7 @@ AHostResolver::LookupStatus TRRService::CompleteLookup(
|
|||
// confirmation in trr-first mode
|
||||
Telemetry::Accumulate(Telemetry::DNS_TRR_NS_VERFIFIED2,
|
||||
TRRService::AutoDetectedKey(),
|
||||
(mConfirmationState == CONFIRM_OK));
|
||||
(mConfirmation.mState == CONFIRM_OK));
|
||||
}
|
||||
|
||||
return LOOKUP_OK;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsWeakReference.h"
|
||||
#include "ODoHService.h"
|
||||
#include "TRRServiceBase.h"
|
||||
#include "nsICaptivePortalService.h"
|
||||
|
||||
class nsDNSService;
|
||||
class nsIPrefBranch;
|
||||
|
@ -39,7 +40,7 @@ class TRRService : public TRRServiceBase,
|
|||
nsresult Init();
|
||||
nsresult Start();
|
||||
bool Enabled(nsIRequest::TRRMode aRequestMode = nsIRequest::TRR_DEFAULT_MODE);
|
||||
bool IsConfirmed() { return mConfirmationState == CONFIRM_OK; }
|
||||
bool IsConfirmed() { return mConfirmation.mState == CONFIRM_OK; }
|
||||
|
||||
bool DisableIPv6() { return mDisableIPv6; }
|
||||
nsresult GetURI(nsACString& result);
|
||||
|
@ -48,7 +49,8 @@ class TRRService : public TRRServiceBase,
|
|||
|
||||
LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*,
|
||||
bool pb, const nsACString& aOriginSuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason) override;
|
||||
nsHostRecord::TRRSkippedReason aReason,
|
||||
TRR* aTrrRequest) override;
|
||||
LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
|
||||
mozilla::net::TypeRecordResultType&,
|
||||
uint32_t, bool pb) override;
|
||||
|
@ -85,8 +87,8 @@ class TRRService : public TRRServiceBase,
|
|||
|
||||
nsresult ReadPrefs(const char* name);
|
||||
void GetPrefBranch(nsIPrefBranch** result);
|
||||
void MaybeConfirm();
|
||||
void MaybeConfirm_locked();
|
||||
void MaybeConfirm(const char* aReason);
|
||||
void MaybeConfirm_locked(const char* aReason);
|
||||
friend class ::nsDNSService;
|
||||
void SetDetectedTrrURI(const nsACString& aURI);
|
||||
|
||||
|
@ -139,13 +141,53 @@ class TRRService : public TRRServiceBase,
|
|||
CONFIRM_OK = 2,
|
||||
CONFIRM_FAILED = 3
|
||||
};
|
||||
Atomic<ConfirmationState, Relaxed> mConfirmationState;
|
||||
RefPtr<TRR> mConfirmer;
|
||||
nsCOMPtr<nsITimer> mRetryConfirmTimer;
|
||||
uint32_t mRetryConfirmInterval; // milliseconds until retry
|
||||
Atomic<uint32_t, Relaxed> mTRRFailures;
|
||||
|
||||
class ConfirmationContext {
|
||||
static const size_t RESULTS_SIZE = 32;
|
||||
|
||||
public:
|
||||
Atomic<ConfirmationState, Relaxed> mState;
|
||||
RefPtr<TRR> mTask;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
uint32_t mRetryInterval = 125; // milliseconds until retry
|
||||
// The number of TRR requests that failed in a row.
|
||||
Atomic<uint32_t, Relaxed> mTRRFailures;
|
||||
|
||||
// The number of confirmation retries.
|
||||
uint32_t mAttemptCount = 0;
|
||||
|
||||
// The results of past confirmation attempts.
|
||||
// This is circular buffer ending at mAttemptCount.
|
||||
char mResults[RESULTS_SIZE] = {0};
|
||||
|
||||
// Time when first confirmation started. Needed so we can
|
||||
// record the time from start to confirmed.
|
||||
TimeStamp mFirstRequestTime;
|
||||
// The network ID at the start of the last confirmation attempt
|
||||
nsCString mNetworkId;
|
||||
// Captive portal status at the time of recording.
|
||||
int32_t mCaptivePortalStatus = nsICaptivePortalService::UNKNOWN;
|
||||
|
||||
// The reason the confirmation context changed.
|
||||
nsCString mContextChangeReason;
|
||||
|
||||
// What triggered the confirmation
|
||||
nsCString mTrigger;
|
||||
|
||||
// Called when a confirmation completes successfully or when the
|
||||
// confirmation context changes.
|
||||
void RecordEvent(const char* aReason);
|
||||
|
||||
// Called when a confirmation request is completed. The status is recorded
|
||||
// in the results.
|
||||
void RequestCompleted(nsresult aLookupStatus, nsresult aChannelStatus);
|
||||
};
|
||||
|
||||
ConfirmationContext mConfirmation;
|
||||
|
||||
bool mParentalControlEnabled;
|
||||
RefPtr<ODoHService> mODoHService;
|
||||
nsCOMPtr<nsINetworkLinkService> mLinkService;
|
||||
};
|
||||
|
||||
extern TRRService* gTRRService;
|
||||
|
|
|
@ -754,7 +754,7 @@ void nsHostResolver::ClearPendingQueue(
|
|||
rec->Cancel();
|
||||
if (rec->IsAddrRecord()) {
|
||||
CompleteLookup(rec, NS_ERROR_ABORT, nullptr, rec->pb, rec->originSuffix,
|
||||
rec->mTRRTRRSkippedReason);
|
||||
rec->mTRRTRRSkippedReason, nullptr);
|
||||
} else {
|
||||
mozilla::net::TypeRecordResultType empty(Nothing{});
|
||||
CompleteLookupByType(rec, NS_ERROR_ABORT, empty, 0, rec->pb);
|
||||
|
@ -1865,7 +1865,8 @@ void nsHostResolver::AddToEvictionQ(nsHostRecord* rec) {
|
|||
// returns LOOKUP_RESOLVEAGAIN, but only if 'status' is not NS_ERROR_ABORT.
|
||||
nsHostResolver::LookupStatus nsHostResolver::CompleteLookup(
|
||||
nsHostRecord* rec, nsresult status, AddrInfo* aNewRRSet, bool pb,
|
||||
const nsACString& aOriginsuffix, nsHostRecord::TRRSkippedReason aReason) {
|
||||
const nsACString& aOriginsuffix, nsHostRecord::TRRSkippedReason aReason,
|
||||
mozilla::net::TRR* aTRRRequest) {
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(rec);
|
||||
MOZ_ASSERT(rec->pb == pb);
|
||||
|
@ -2231,9 +2232,9 @@ void nsHostResolver::ThreadFunc() {
|
|||
LOG1(("DNS lookup thread - lookup completed for host [%s]: %s.\n",
|
||||
rec->host.get(), ai ? "success" : "failure: unknown host"));
|
||||
|
||||
if (LOOKUP_RESOLVEAGAIN == CompleteLookup(rec, status, ai, rec->pb,
|
||||
rec->originSuffix,
|
||||
rec->mTRRTRRSkippedReason)) {
|
||||
if (LOOKUP_RESOLVEAGAIN ==
|
||||
CompleteLookup(rec, status, ai, rec->pb, rec->originSuffix,
|
||||
rec->mTRRTRRSkippedReason, nullptr)) {
|
||||
// leave 'rec' assigned and loop to make a renewed host resolve
|
||||
LOG(("DNS lookup thread - Re-resolving host [%s].\n", rec->host.get()));
|
||||
} else {
|
||||
|
|
|
@ -421,10 +421,11 @@ class AHostResolver {
|
|||
LOOKUP_RESOLVEAGAIN,
|
||||
};
|
||||
|
||||
virtual LookupStatus CompleteLookup(
|
||||
nsHostRecord*, nsresult, mozilla::net::AddrInfo*, bool pb,
|
||||
const nsACString& aOriginsuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason) = 0;
|
||||
virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult,
|
||||
mozilla::net::AddrInfo*, bool pb,
|
||||
const nsACString& aOriginsuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason,
|
||||
mozilla::net::TRR*) = 0;
|
||||
virtual LookupStatus CompleteLookupByType(
|
||||
nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool pb) = 0;
|
||||
|
@ -551,7 +552,8 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||
|
||||
LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*,
|
||||
bool pb, const nsACString& aOriginsuffix,
|
||||
nsHostRecord::TRRSkippedReason aReason) override;
|
||||
nsHostRecord::TRRSkippedReason aReason,
|
||||
mozilla::net::TRR* aTRRRequest) override;
|
||||
LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
|
||||
mozilla::net::TypeRecordResultType& aResult,
|
||||
uint32_t aTtl, bool pb) override;
|
||||
|
|
Загрузка…
Ссылка в новой задаче