bug 1441391 - TRR: restart failed NS confirms in TRR-only mode r?valentin draft
authorDaniel Stenberg <daniel@haxx.se>
Fri, 09 Mar 2018 09:05:48 +0100
changeset 765304 65c5dfa198a65b7ea4ba8469bd1abc61205fc747
parent 764770 a6a32fb286fa9e5d5f6d5b3b77423ab6b96c9502
push id102011
push userbmo:daniel@haxx.se
push dateFri, 09 Mar 2018 13:36:34 +0000
reviewersvalentin
bugs1441391
milestone60.0a1
bug 1441391 - TRR: restart failed NS confirms in TRR-only mode r?valentin MozReview-Commit-ID: FHw3Zx07iFG
netwerk/dns/TRR.cpp
netwerk/dns/TRRService.cpp
netwerk/dns/TRRService.h
--- a/netwerk/dns/TRR.cpp
+++ b/netwerk/dns/TRR.cpp
@@ -41,17 +41,16 @@ extern mozilla::LazyLogModule gHostResol
 NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor, nsIStreamListener, nsIRunnable)
 
 const uint8_t kDNS_CLASS_IN = 1;
 
 NS_IMETHODIMP
 TRR::Notify(nsITimer *aTimer)
 {
   if (aTimer == mTimeout) {
-    LOG(("TRR request for %s timed out\n", mHost.get()));
     mTimeout = nullptr;
     Cancel();
   } else {
     MOZ_CRASH("Unknown timer");
   }
 
   return NS_OK;
 }
--- a/netwerk/dns/TRRService.cpp
+++ b/netwerk/dns/TRRService.cpp
@@ -39,16 +39,17 @@ TRRService::TRRService()
   , mLock("trrservice")
   , mConfirmationNS(NS_LITERAL_CSTRING("example.com"))
   , mWaitForCaptive(true)
   , mRfc1918(false)
   , mCaptiveIsPassed(false)
   , mUseGET(false)
   , mClearTRRBLStorage(false)
   , mConfirmationState(CONFIRM_INIT)
+  , mRetryConfirmInterval(1000)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
 }
 
 nsresult
 TRRService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
@@ -78,23 +79,29 @@ TRRService::Init()
   LOG(("Initialized TRRService\n"));
   return NS_OK;
 }
 
 bool
 TRRService::Enabled()
 {
   if (mConfirmationState == CONFIRM_INIT && !mWaitForCaptive) {
+    LOG(("TRRService::Enabled => CONFIRM_TRYING\n"));
     mConfirmationState = CONFIRM_TRYING;
   }
 
   if (mConfirmationState == CONFIRM_TRYING) {
+    LOG(("TRRService::Enabled MaybeConfirm()\n"));
     MaybeConfirm();
   }
 
+  if (mConfirmationState != CONFIRM_OK) {
+    LOG(("TRRService::Enabled mConfirmationState=%d\n", (int)mConfirmationState));
+  }
+
   return (mConfirmationState == CONFIRM_OK);
 }
 
 void
 TRRService::GetPrefBranch(nsIPrefBranch **result)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
   *result = nullptr;
@@ -285,16 +292,18 @@ TRRService::Observe(nsISupports *aSubjec
   return NS_OK;
 }
 
 void
 TRRService::MaybeConfirm()
 {
   if ((mMode == MODE_NATIVEONLY) || mConfirmer ||
       mConfirmationState != CONFIRM_TRYING) {
+    LOG(("TRRService:MaybeConfirm mode=%d, mConfirmer=%p mConfirmationState=%d\n",
+         (int)mMode, (void *)mConfirmer, (int)mConfirmationState));
     return;
   }
   nsAutoCString host;
   {
     MutexAutoLock lock(mLock);
     host = mConfirmationNS;
   }
   if (host.Equals("skip")) {
@@ -473,16 +482,34 @@ TRRService::TRRBlacklist(const nsACStrin
 
       // check if there's an NS entry for this name
       RefPtr<TRR> trr = new TRR(this, check, TRRTYPE_NS, privateBrowsing);
       NS_DispatchToMainThread(trr);
     }
   }
 }
 
+NS_IMETHODIMP
+TRRService::Notify(nsITimer *aTimer)
+{
+  if (aTimer == mRetryConfirmTimer) {
+    mRetryConfirmTimer = nullptr;
+    if (mConfirmationState == CONFIRM_FAILED) {
+      LOG(("TRRService retry NS of %s\n", mConfirmationNS.get()));
+      mConfirmationState = CONFIRM_TRYING;
+      MaybeConfirm();
+    }
+  } else {
+    MOZ_CRASH("Unknown timer");
+  }
+
+  return NS_OK;
+}
+
+
 AHostResolver::LookupStatus
 TRRService::CompleteLookup(nsHostRecord *rec, nsresult status, AddrInfo *aNewRRSet, bool pb)
 {
   // this is an NS check for the TRR blacklist or confirmationNS check
 
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!rec);
 
@@ -491,16 +518,28 @@ TRRService::CompleteLookup(nsHostRecord 
 
   MOZ_ASSERT(!mConfirmer || (mConfirmationState == CONFIRM_TRYING));
   if (mConfirmationState == CONFIRM_TRYING) {
     MOZ_ASSERT(mConfirmer);
     mConfirmationState = 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_FAILED) && (mMode == MODE_TRRONLY)) {
+      // in TRR-only mode; retry failed confirmations
+      NS_NewTimerWithCallback(getter_AddRefs(mRetryConfirmTimer),
+                              this, mRetryConfirmInterval,
+                              nsITimer::TYPE_ONE_SHOT);
+      if (mRetryConfirmInterval < 64000) {
+        // double the interval up to this point
+        mRetryConfirmInterval *= 2;
+      }
+    } else {
+      mRetryConfirmInterval = 1000;
+    }
     return LOOKUP_OK;
   }
 
   // when called without a host record, this is a domain name check response.
   if (NS_SUCCEEDED(status)) {
     LOG(("TRR verified %s to be fine!\n", newRRSet->mHostName));
   } else {
     LOG(("TRR says %s doesn't resove as NS!\n", newRRSet->mHostName));
--- a/netwerk/dns/TRRService.h
+++ b/netwerk/dns/TRRService.h
@@ -14,22 +14,24 @@
 
 class nsIPrefBranch;
 
 namespace mozilla {
 namespace net {
 
 class TRRService
   : public nsIObserver
+  , public nsITimerCallback
   , public nsSupportsWeakReference
   , public AHostResolver
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSITIMERCALLBACK
 
   TRRService();
   nsresult Init();
   nsresult Start();
   bool Enabled();
 
   uint32_t Mode() { return mMode; }
   bool AllowRFC1918() { return mRfc1918; }
@@ -74,17 +76,19 @@ private:
 
   enum ConfirmationState {
     CONFIRM_INIT = 0,
     CONFIRM_TRYING = 1,
     CONFIRM_OK = 2,
     CONFIRM_FAILED = 3
   };
   Atomic<ConfirmationState, Relaxed>  mConfirmationState;
-  RefPtr<TRR>           mConfirmer;
+  RefPtr<TRR> mConfirmer;
+  nsCOMPtr<nsITimer> mRetryConfirmTimer;
+  uint32_t mRetryConfirmInterval; // milliseconds until retry
 };
 
 extern TRRService *gTRRService;
 
 } // namespace net
 } // namespace mozilla
 
 #endif // TRRService_h_