Bug 1460537 - Connectivity Service - Add check for IPv4/v6 connectivity r=dragana

This is likely not the best approach to detecting IP connectivity.
The check has a slight delay until the failure counter reaches the threshold.
A more reliable way will be added in a follow-up.

Depends on D7844

Differential Revision: https://phabricator.services.mozilla.com/D8704

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Valentin Gosu 2018-10-25 15:49:08 +00:00
Родитель 23793b33e1
Коммит 0774dd10ce
7 изменённых файлов: 77 добавлений и 12 удалений

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

@ -6,6 +6,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "xpcpublic.h"
#include "nsSocketTransport2.h"
namespace mozilla {
namespace net {
@ -64,6 +65,27 @@ NetworkConnectivityService::GetDNSv6(int32_t *aState)
return NS_OK;
}
NS_IMETHODIMP
NetworkConnectivityService::GetIPv4(int32_t *aState)
{
NS_ENSURE_ARG(aState);
*aState = nsSocketTransport::HasIPv4Connectivity()
? nsINetworkConnectivityService::OK
: nsINetworkConnectivityService::NOT_AVAILABLE;
return NS_OK;
}
NS_IMETHODIMP
NetworkConnectivityService::GetIPv6(int32_t *aState)
{
NS_ENSURE_ARG(aState);
*aState = nsSocketTransport::HasIPv6Connectivity()
? nsINetworkConnectivityService::OK
: nsINetworkConnectivityService::NOT_AVAILABLE;
return NS_OK;
}
void
NetworkConnectivityService::PerformChecks()
{

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

@ -9,9 +9,7 @@
namespace mozilla {
namespace net {
namespace {
StaticRefPtr<RedirectChannelRegistrar> gSingleton;
}
StaticRefPtr<RedirectChannelRegistrar> RedirectChannelRegistrar::gSingleton;
NS_IMPL_ISUPPORTS(RedirectChannelRegistrar, nsIRedirectChannelRegistrar)

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

@ -43,6 +43,8 @@ protected:
ParentChannelHashtable mParentChannels;
uint32_t mId;
Mutex mLock;
static StaticRefPtr<RedirectChannelRegistrar> gSingleton;
};
} // namespace net

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

@ -22,6 +22,10 @@ interface nsINetworkConnectivityService : nsISupports
readonly attribute long DNSv4;
readonly attribute long DNSv6;
/* If connecting to IPv4/v6 works on the current network */
readonly attribute long IPv4;
readonly attribute long IPv6;
/* Starts the DNS request to check for DNS v4/v6 availability */
void recheckDNS();
};

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

@ -755,6 +755,15 @@ nsSocketOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
// socket transport impl
//-----------------------------------------------------------------------------
// We assume we have connectivity at first.
bool nsSocketTransport::sHasIPv4Connectivity = true;
bool nsSocketTransport::sHasIPv6Connectivity = true;
uint32_t nsSocketTransport::sIPv4FailedCounter = 0;
uint32_t nsSocketTransport::sIPv6FailedCounter = 0;
const uint32_t kFailureThreshold = 50;
nsSocketTransport::nsSocketTransport()
: mTypes(nullptr)
, mTypeCount(0)
@ -1857,14 +1866,25 @@ nsSocketTransport::RecoverFromError()
if (NS_SUCCEEDED(mFirstRetryError)) {
mFirstRetryError = mCondition;
}
if ((mState == STATE_CONNECTING) && mDNSRecord &&
mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
if ((mState == STATE_CONNECTING) && mDNSRecord) {
if (mNetAddr.raw.family == AF_INET) {
Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
UNSUCCESSFUL_CONNECTING_TO_IPV4_ADDRESS);
sIPv4FailedCounter++;
if (sIPv4FailedCounter > kFailureThreshold) {
sHasIPv4Connectivity = false;
}
if (mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
UNSUCCESSFUL_CONNECTING_TO_IPV4_ADDRESS);
}
} else if (mNetAddr.raw.family == AF_INET6) {
Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
UNSUCCESSFUL_CONNECTING_TO_IPV6_ADDRESS);
sIPv6FailedCounter++;
if (sIPv6FailedCounter > kFailureThreshold) {
sHasIPv6Connectivity = false;
}
if (mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
UNSUCCESSFUL_CONNECTING_TO_IPV6_ADDRESS);
}
}
}
@ -2346,12 +2366,18 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
//
OnSocketConnected();
if (mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
if (mNetAddr.raw.family == AF_INET) {
if (mNetAddr.raw.family == AF_INET) {
sIPv4FailedCounter = 0;
sHasIPv4Connectivity = true;
if (mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
Telemetry::Accumulate(
Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
SUCCESSFUL_CONNECTING_TO_IPV4_ADDRESS);
} else if (mNetAddr.raw.family == AF_INET6) {
}
} else if (mNetAddr.raw.family == AF_INET6) {
sIPv6FailedCounter = 0;
sHasIPv6Connectivity = true;
if (mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
Telemetry::Accumulate(
Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
SUCCESSFUL_CONNECTING_TO_IPV6_ADDRESS);

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

@ -177,6 +177,10 @@ public:
Telemetry::HistogramID aIDConnectivityChange,
Telemetry::HistogramID aIDLinkChange,
Telemetry::HistogramID aIDOffline);
static bool HasIPv4Connectivity() { return sHasIPv4Connectivity; }
static bool HasIPv6Connectivity() { return sHasIPv6Connectivity; }
protected:
virtual ~nsSocketTransport();
@ -487,6 +491,11 @@ private:
nsresult mFirstRetryError;
bool mDoNotRetryToConnect;
static bool sHasIPv4Connectivity;
static bool sHasIPv6Connectivity;
static uint32_t sIPv4FailedCounter;
static uint32_t sIPv6FailedCounter;
};
} // namespace net

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

@ -50,4 +50,8 @@ add_task(async function testDNS() {
equal(ncs.DNSv4, Ci.nsINetworkConnectivityService.OK, "Check DNSv4 support (expect OK)");
equal(ncs.DNSv6, Ci.nsINetworkConnectivityService.OK, "Check DNSv6 support (expect OK)");
// It's difficult to check when there's no connectivity in automation,
equal(ncs.IPv4, Ci.nsINetworkConnectivityService.OK, "Check IPv4 support (expect OK)");
equal(ncs.IPv6, Ci.nsINetworkConnectivityService.OK, "Check IPv6 support (expect OK)");
});