If FastFallbackToIPv4 is set disable IPv6 on backup connections. draft
authorDragana Damjanovic <dd.mozilla@gmail.com>
Thu, 18 Feb 2021 19:14:42 +0000
changeset 3548288 31bfd25f327bf763419978fe4f6b44acea953380
parent 3545063 3d42785f84cb4251378b1cd3583df18fd8aa8bd9
child 3548289 56569391301e067939b5088bbcbf59f3e9b379be
push id656965
push userreviewbot
push dateThu, 18 Feb 2021 19:15:05 +0000
treeherdertry@56569391301e [default view] [failures only]
bugs1692734
milestone87.0a1
If FastFallbackToIPv4 is set disable IPv6 on backup connections. Reviewers: #necko-reviewers! Tags: #secure-revision Bug #: 1692734 Differential Revision: https://phabricator.services.mozilla.com/D105482 Differential Diff: PHID-DIFF-hbjha2ye44xqud2m4ped
netwerk/protocol/http/DnsAndConnectSocket.cpp
--- a/netwerk/protocol/http/DnsAndConnectSocket.cpp
+++ b/netwerk/protocol/http/DnsAndConnectSocket.cpp
@@ -143,31 +143,39 @@ void DnsAndConnectSocket::CheckProxyConf
     }
   }
 }
 
 nsresult DnsAndConnectSocket::SetupDnsFlags() {
   LOG(("DnsAndConnectSocket::SetupDnsFlags [this=%p] ", this));
 
   uint32_t dnsFlags = 0;
+  bool disableIpv6ForBackup = false;
   if (mCaps & NS_HTTP_REFRESH_DNS) {
     dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE;
   }
   if (mCaps & NS_HTTP_DISABLE_IPV4) {
     dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
   } else if (mCaps & NS_HTTP_DISABLE_IPV6) {
     dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
   } else if (mEnt->PreferenceKnown()) {
     if (mEnt->mPreferIPv6) {
       dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
     } else if (mEnt->mPreferIPv4) {
       dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
     }
     mPrimaryTransport.mRetryWithDifferentIPFamily = true;
     mBackupTransport.mRetryWithDifferentIPFamily = true;
+  } else if (gHttpHandler->FastFallbackToIPv4()) {
+    // For backup connections, we disable IPv6. That's because some users have
+    // broken IPv6 connectivity (leading to very long timeouts), and disabling
+    // IPv6 on the backup connection gives them a much better user experience
+    // with dual-stack hosts, though they still pay the 250ms delay for each new
+    // connection. This strategy is also known as "happy eyeballs".
+    disableIpv6ForBackup = true;
   }
 
   if (mEnt->mConnInfo->HasIPHintAddress()) {
     nsresult rv;
     nsCOMPtr<nsIDNSService> dns =
         do_GetService("@mozilla.org/network/dns-service;1", &rv);
     if (NS_FAILED(rv)) {
       return rv;
@@ -196,16 +204,22 @@ nsresult DnsAndConnectSocket::SetupDnsFl
   dnsFlags |= nsIDNSService::RESOLVE_IGNORE_SOCKS_DNS;
 
   NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) ||
                    !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4),
                "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4");
 
   mPrimaryTransport.mDnsFlags = dnsFlags;
   mBackupTransport.mDnsFlags = dnsFlags;
+  if (disableIpv6ForBackup) {
+    mBackupTransport.mDnsFlags |= nsISocketTransport::DISABLE_IPV6;
+  }
+  NS_ASSERTION(!( mBackupTransport.mDnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) ||
+                   !( mBackupTransport.mDnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4),
+               "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4");
   return NS_OK;
 }
 
 nsresult DnsAndConnectSocket::SetupEvent(SetupEvents event) {
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
   LOG(("DnsAndConnectSocket::SetupEvent state=%d event=%d", mState, event));
   switch (event) {
     case SetupEvents::INIT_EVENT: {